Skip to content

Commit

Permalink
refactor: use common iface for push internals
Browse files Browse the repository at this point in the history
  • Loading branch information
antongolub committed Jun 21, 2022
1 parent 81157a1 commit e614e42
Showing 1 changed file with 95 additions and 84 deletions.
179 changes: 95 additions & 84 deletions src/main/js/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,100 @@ import {formatTag, getLatestTag} from './tag.js'
import {tempy, ctx, fs, path} from 'zx-extra'
import {copydir} from 'git-glob-cp'

const branches = {}
const META_VERSION = '1'

export const publish = async (pkg) => {
await pushTag(pkg)
await pushMeta(pkg)
await npmPublish(pkg)
await createGhRelease(pkg)
}

export const pushTag = (pkg) => ctx(async ($) => {
const {absPath: cwd, name, version} = pkg
const tag = formatTag({name, version})
const {gitCommitterEmail, gitCommitterName} = parseEnv($.env)
$.cwd = cwd

console.log(`push release tag ${tag}`)

await $`git config user.name ${gitCommitterName}`
await $`git config user.email ${gitCommitterEmail}`
await $`git tag -m ${tag} ${tag}`
await $`git push origin ${tag}`
})

export const pushMeta = async (pkg) => {
console.log('push artifact to branch `meta`')

const cwd = pkg.absPath
const {name, version} = pkg
const tag = formatTag({name, version})
const to = getArtifactPath(tag)
const branch = 'meta'
const msg = `chore: release meta ${name} ${version}`
const meta = {
META_VERSION,
name: pkg.name,
version: pkg.version,
dependencies: pkg.dependencies,
devDependencies: pkg.devDependencies,
peerDependencies: pkg.peerDependencies,
optionalDependencies: pkg.optionalDependencies,
}
const files = [{relpath: 'meta.json', contents: meta}]

await push({cwd, to, branch, msg, files})
}

export const npmPublish = ({absPath: cwd}) => ctx(async ($) => {
const {npmRegistry, npmToken, npmConfig} = parseEnv($.env)
const npmrc = npmConfig ? npmConfig : path.resolve(cwd, '.npmrc')

console.log(`publish npm package to ${npmRegistry}`)
$.cwd = cwd
if (!npmConfig) {
await $.raw`echo ${npmRegistry.replace(/https?:/, '')}/:_authToken=${npmToken} >> ${npmrc}`
}
await $`npm publish --no-git-tag-version --registry=${npmRegistry} --userconfig ${npmrc} --no-workspaces`
})

export const createGhRelease = (pkg) => ctx(async ($) => {
console.log('create gh release')

const cwd = pkg.absPath
const {name, version} = pkg
const {ghUser, ghToken} = parseEnv($.env)
const {repoName, repoPublicUrl} = await parseRepo(cwd)

if (!ghToken || !ghUser) return null

const tag = formatTag({name, version})
const releaseDiffRef = `## [${name}@${version}](${repoPublicUrl}/compare/${pkg.latest.tag?.ref}...${tag}) (${new Date().toISOString().slice(0, 10)})`
const releaseDetails = Object.values(pkg.changes
.reduce((acc, {group, subj, short, hash}) => {
const {commits} = acc[group] || (acc[group] = {commits: [], group})
const commitRef = `* ${subj}${short ? ` [${short}](${repoPublicUrl}/commit/${hash})` : ''}`

commits.push(commitRef)

return acc
}, {}))
.map(({group, commits}) => `
### ${group}
${commits.join('\n')}`).join('\n')

const releaseNotes = releaseDiffRef + '\n' + releaseDetails + '\n'
const releaseData = JSON.stringify({
name: tag,
tag_name: tag,
body: releaseNotes
})

$.cwd = cwd
await $`curl -u ${ghUser}:${ghToken} -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${repoName}/releases -d ${releaseData}`
})

export const getOrigin = (cwd) => ctx(async ($) => {
$.cwd = cwd
const {ghToken, ghUser} = parseEnv($.env)
Expand All @@ -16,6 +107,7 @@ export const getOrigin = (cwd) => ctx(async ($) => {
: originUrl
})

const branches = {}
export const fetch = async ({cwd: _cwd, branch, origin: _origin}) => ctx(async ($) => {
let cwd = branches[branch]
if (cwd) return cwd
Expand Down Expand Up @@ -55,33 +147,6 @@ export const push = async ({cwd, from, to, branch, origin, msg, ignoreFiles, fil
await $.raw`git push origin HEAD:refs/heads/${branch}`
})

export const publish = async (pkg, env) => ctx(async ($) => {
const {name, version} = pkg.manifest
const tag = formatTag({name, version})
const cwd = pkg.absPath
const {gitCommitterEmail, gitCommitterName, npmRegistry} = parseEnv(env)

$.cwd = cwd
$.env = env

console.log(`push release tag ${tag}`)
await $`git config user.name ${gitCommitterName}`
await $`git config user.email ${gitCommitterEmail}`
await $`git tag -m ${tag} ${tag}`
await $`git push origin ${tag}`

console.log('push artifact to branch `meta`')
await pushMeta(pkg)

console.log(`publish npm package to ${npmRegistry}`)
const npmrc = path.resolve(cwd, '.npmrc')
await $.raw`echo ${npmRegistry.replace(/https?:/, '')}/:_authToken=${$.env.NPM_TOKEN} >> ${npmrc}`
await $`npm publish --no-git-tag-version --registry=${npmRegistry} --userconfig ${npmrc} --no-workspaces`

console.log('create gh release')
await createGhRelease(pkg)
})

export const getArtifactPath = (tag) => tag.toLowerCase().replace(/[^a-z0-9-]/g, '-')

export const getLatestMeta = async (cwd, tag) => {
Expand All @@ -95,27 +160,6 @@ export const getLatestMeta = async (cwd, tag) => {
return null
}

export const pushMeta = async (pkg) => {
const cwd = pkg.absPath
const {name, version} = pkg
const tag = formatTag({name, version})
const to = getArtifactPath(tag)
const branch = 'meta'
const msg = `chore: release meta ${name} ${version}`
const meta = {
META_VERSION,
name: pkg.name,
version: pkg.version,
dependencies: pkg.dependencies,
devDependencies: pkg.devDependencies,
peerDependencies: pkg.peerDependencies,
optionalDependencies: pkg.optionalDependencies,
}
const files = [{relpath: 'meta.json', contents: meta}]

await push({cwd, to, branch, msg, files})
}

export const getLatest = async (cwd, name) => {
const tag = await getLatestTag(cwd, name)
const meta = await getLatestMeta(cwd, tag?.ref)
Expand All @@ -127,11 +171,12 @@ export const getLatest = async (cwd, name) => {
}

export const parseEnv = (env = process.env) => {
const {GH_USER, GH_USERNAME, GITHUB_USER, GITHUB_USERNAME, GH_TOKEN, GITHUB_TOKEN, NPM_TOKEN, NPM_REGISTRY, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL} = env
const {GH_USER, GH_USERNAME, GITHUB_USER, GITHUB_USERNAME, GH_TOKEN, GITHUB_TOKEN, NPM_TOKEN, NPM_REGISTRY, NPMRC, NPM_USERCONFIG, NPM_CONFIG_USERCONFIG, GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL} = env

return {
ghUser: GH_USER || GH_USERNAME || GITHUB_USER || GITHUB_USERNAME,
ghToken: GH_TOKEN || GITHUB_TOKEN,
npmConfig: NPMRC || NPM_USERCONFIG || NPM_CONFIG_USERCONFIG,
npmToken: NPM_TOKEN,
npmRegistry: NPM_REGISTRY || 'https://registry.npmjs.org',
gitCommitterName: GIT_COMMITTER_NAME || 'Semrel Extra Bot',
Expand All @@ -151,37 +196,3 @@ export const parseRepo = (cwd, origin) => ctx(async ($) => {
repoPublicUrl
}
})

export const createGhRelease = (pkg) => ctx(async ($) => {
const cwd = pkg.absPath
const {name, version} = pkg
const {ghUser, ghToken} = parseEnv($.env)
const {repoName, repoPublicUrl} = await parseRepo(cwd)

if (!ghToken || !ghUser) return null

const tag = formatTag({name, version})
const releaseDiffRef = `## [${name}@${version}](${repoPublicUrl}/compare/${pkg.latest.tag?.ref}...${tag}) (${new Date().toISOString().slice(0, 10)})`
const releaseDetails = Object.values(pkg.changes
.reduce((acc, {group, subj, short, hash}) => {
const {commits} = acc[group] || (acc[group] = {commits: [], group})
const commitRef = `* ${subj}${short ? ` [${short}](${repoPublicUrl}/commit/${hash})` : ''}`

commits.push(commitRef)

return acc
}, {}))
.map(({group, commits}) => `
### ${group}
${commits.join('\n')}`).join('\n')

const releaseNotes = releaseDiffRef + '\n' + releaseDetails + '\n'
const releaseData = JSON.stringify({
name: tag,
tag_name: tag,
body: releaseNotes
})

$.cwd = cwd
await $`curl -u ${ghUser}:${ghToken} -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${repoName}/releases -d ${releaseData}`
})

0 comments on commit e614e42

Please sign in to comment.