2020-09-04 17:22:15 +09:00
|
|
|
import { join } from 'path'
|
|
|
|
|
|
|
|
import { Octokit } from '@octokit/rest'
|
|
|
|
import chalk from 'chalk'
|
|
|
|
import { Command } from 'clipanion'
|
|
|
|
|
|
|
|
import { getNapiConfig } from './consts'
|
|
|
|
import { debugFactory } from './debug'
|
|
|
|
import { spawn } from './spawn'
|
|
|
|
import { updatePackageJson } from './update-package'
|
|
|
|
import { readFileAsync, writeFileAsync } from './utils'
|
|
|
|
|
|
|
|
const debug = debugFactory('prepublish')
|
|
|
|
|
|
|
|
interface PackageInfo {
|
|
|
|
name: string
|
|
|
|
version: string
|
|
|
|
tag: string
|
|
|
|
}
|
|
|
|
|
|
|
|
export class PrePublishCommand extends Command {
|
|
|
|
static usage = Command.Usage({
|
|
|
|
description:
|
|
|
|
'Update package.json and copy addons into per platform packages',
|
|
|
|
})
|
|
|
|
|
|
|
|
@Command.String(`-p,--prefix`)
|
|
|
|
prefix = 'npm'
|
|
|
|
|
|
|
|
@Command.String('--tagstyle,-t')
|
|
|
|
tagStyle: 'npm' | 'lerna' = 'lerna'
|
|
|
|
|
|
|
|
@Command.String('-c,--config')
|
|
|
|
configFileName?: string
|
|
|
|
|
|
|
|
@Command.Boolean('--dry-run')
|
|
|
|
isDryRun = false
|
|
|
|
|
|
|
|
@Command.Path('prepublish')
|
|
|
|
async execute() {
|
|
|
|
const {
|
|
|
|
packageJsonPath,
|
|
|
|
platforms,
|
|
|
|
version,
|
|
|
|
muslPlatforms,
|
|
|
|
packageName,
|
|
|
|
binaryName,
|
|
|
|
} = getNapiConfig(this.configFileName)
|
|
|
|
debug(`Update optionalDependencies in [${packageJsonPath}]`)
|
|
|
|
if (!this.isDryRun) {
|
|
|
|
await updatePackageJson(packageJsonPath, {
|
|
|
|
optionalDependencies: platforms.reduce(
|
|
|
|
(acc: Record<string, string>, cur: NodeJS.Platform) => {
|
|
|
|
acc[`${packageName}-${cur}`] = `^${version}`
|
|
|
|
return acc
|
|
|
|
},
|
|
|
|
{},
|
|
|
|
),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const { owner, repo, pkgInfo } = await this.createGhRelease(
|
|
|
|
packageName,
|
|
|
|
version,
|
|
|
|
)
|
|
|
|
|
|
|
|
for (const name of [...platforms, ...muslPlatforms]) {
|
|
|
|
const pkgDir = join(process.cwd(), this.prefix, name)
|
|
|
|
const filename = `${binaryName}.${name}.node`
|
|
|
|
debug(`Read [${chalk.greenBright(filename)}] content`)
|
|
|
|
const bindingFile = await readFileAsync(join(process.cwd(), filename))
|
|
|
|
const dstPath = join(pkgDir, filename)
|
|
|
|
await writeFileAsync(dstPath, bindingFile)
|
|
|
|
debug(`Write [${chalk.yellowBright(dstPath)}] content`)
|
|
|
|
if (!this.isDryRun) {
|
|
|
|
await spawn('npm publish', {
|
|
|
|
cwd: pkgDir,
|
|
|
|
env: process.env,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
debug(
|
|
|
|
`Start upload [${chalk.greenBright(
|
|
|
|
dstPath,
|
|
|
|
)}] to Github release, [${chalk.greenBright(pkgInfo.tag)}]`,
|
|
|
|
)
|
|
|
|
if (!this.isDryRun) {
|
|
|
|
const putasset = require('putasset')
|
2020-09-08 00:18:04 +09:00
|
|
|
try {
|
|
|
|
const downloadUrl = await putasset(process.env.GITHUB_TOKEN, {
|
|
|
|
owner,
|
|
|
|
repo,
|
|
|
|
tag: pkgInfo.tag,
|
|
|
|
filename: dstPath,
|
|
|
|
})
|
|
|
|
console.info(`${chalk.green(dstPath)} upload success`)
|
|
|
|
console.info(`Download url: ${chalk.blueBright(downloadUrl)}`)
|
|
|
|
} catch (e) {
|
|
|
|
debug(
|
|
|
|
`Param: ${{ owner, repo, tag: pkgInfo.tag, filename: dstPath }}`,
|
|
|
|
)
|
|
|
|
console.error(e)
|
|
|
|
}
|
2020-09-04 17:22:15 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private async createGhRelease(packageName: string, version: string) {
|
|
|
|
const headCommit = (await spawn('git log -1 --pretty=%B'))
|
|
|
|
.toString('utf8')
|
|
|
|
.trim()
|
2020-09-08 00:18:04 +09:00
|
|
|
|
|
|
|
debug(`Github repository: ${process.env.GITHUB_REPOSITORY}`)
|
2020-09-04 17:22:15 +09:00
|
|
|
const [owner, repo] = process.env.GITHUB_REPOSITORY!.split('/')
|
|
|
|
const octokit = new Octokit({
|
|
|
|
auth: process.env.GITHUB_TOKEN,
|
|
|
|
})
|
|
|
|
let pkgInfo: PackageInfo | undefined
|
|
|
|
if (this.tagStyle === 'lerna') {
|
|
|
|
const packagesToPublish = headCommit
|
|
|
|
.split('\n')
|
|
|
|
.map((line) => line.trim())
|
|
|
|
.filter((line, index) => line.length && index)
|
|
|
|
.map((line) => line.substr(2))
|
|
|
|
.map(this.parseTag)
|
|
|
|
pkgInfo = packagesToPublish.find(
|
|
|
|
(pkgInfo) => pkgInfo.name === packageName,
|
|
|
|
)
|
|
|
|
if (!pkgInfo) {
|
|
|
|
throw new TypeError(
|
|
|
|
`No release commit found with ${packageName}, original commit info: ${headCommit}`,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
pkgInfo = {
|
2020-09-07 23:22:56 +09:00
|
|
|
tag: `v${version}`,
|
2020-09-04 17:22:15 +09:00
|
|
|
version,
|
|
|
|
name: packageName,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!this.isDryRun) {
|
2020-09-08 00:18:04 +09:00
|
|
|
try {
|
|
|
|
await octokit.repos.createRelease({
|
|
|
|
owner,
|
|
|
|
repo,
|
|
|
|
tag_name: pkgInfo.tag,
|
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
debug(`Params: ${{ owner, repo, tag_name: pkgInfo.tag }}`)
|
|
|
|
console.error(e)
|
|
|
|
}
|
2020-09-04 17:22:15 +09:00
|
|
|
}
|
|
|
|
return { owner, repo, pkgInfo }
|
|
|
|
}
|
|
|
|
|
|
|
|
private parseTag(tag: string) {
|
|
|
|
const segments = tag.split('@')
|
|
|
|
const version = segments.pop()!
|
|
|
|
const name = segments.join('@')
|
|
|
|
|
|
|
|
return {
|
|
|
|
name,
|
|
|
|
version,
|
|
|
|
tag,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|