zx-bulk-release 1.3.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## [1.4.2](https://github.com/semrel-extra/zx-bulk-release/compare/v1.4.1...v1.4.2) (2022-06-21)
2
+
3
+ ### Fixes & improvements
4
+ * refactor: use common iface for push internals ([e614e42](https://github.com/semrel-extra/zx-bulk-release/commit/e614e42d8b323749082b94611f4552fdacebe1f5))
5
+
6
+ ## [1.4.1](https://github.com/semrel-extra/zx-bulk-release/compare/v1.4.0...v1.4.1) (2022-06-21)
7
+
8
+ ### Fixes & improvements
9
+ * fix: fix commits refs in release data ([1ddd2e9](https://github.com/semrel-extra/zx-bulk-release/commit/1ddd2e99e88e245bf5d6b477adb6fca0d2c4c663))
10
+
11
+ ## [1.4.0](https://github.com/semrel-extra/zx-bulk-release/compare/v1.3.0...v1.4.0) (2022-06-21)
12
+
13
+ ### Features
14
+ * feat: add gh release ([df43fca](https://github.com/semrel-extra/zx-bulk-release/commit/df43fca694668a838f287d38b4f298aa9da2acdd))
15
+
16
+ ### Fixes & improvements
17
+ * refactor: add parseEnv util ([936b5ed](https://github.com/semrel-extra/zx-bulk-release/commit/936b5edaf3472f66dba2f9c60bb9745096fda729))
18
+
1
19
  ## [1.3.0](https://github.com/semrel-extra/zx-bulk-release/compare/v1.2.0...v1.3.0) (2022-06-21)
2
20
 
3
21
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zx-bulk-release",
3
- "version": "1.3.0",
3
+ "version": "1.4.2",
4
4
  "description": "zx-based alternative for multi-semantic-release",
5
5
  "type": "module",
6
6
  "exports": "./src/main/js/index.js",
@@ -16,6 +16,7 @@ export const run = async ({cwd = process.cwd(), env = process.env, flags = {}} =
16
16
  const depsChanges = await updateDeps(pkg, packages)
17
17
  const changes = [...semanticChanges, ...depsChanges]
18
18
 
19
+ pkg.changes = changes
19
20
  pkg.version = resolvePkgVersion(changes, pkg.latest.tag?.version || pkg.manifest.version)
20
21
  pkg.manifest.version = pkg.version
21
22
 
@@ -2,22 +2,112 @@ import {formatTag, getLatestTag} from './tag.js'
2
2
  import {tempy, ctx, fs, path} from 'zx-extra'
3
3
  import {copydir} from 'git-glob-cp'
4
4
 
5
- const branches = {}
6
5
  const META_VERSION = '1'
7
6
 
7
+ export const publish = async (pkg) => {
8
+ await pushTag(pkg)
9
+ await pushMeta(pkg)
10
+ await npmPublish(pkg)
11
+ await createGhRelease(pkg)
12
+ }
13
+
14
+ export const pushTag = (pkg) => ctx(async ($) => {
15
+ const {absPath: cwd, name, version} = pkg
16
+ const tag = formatTag({name, version})
17
+ const {gitCommitterEmail, gitCommitterName} = parseEnv($.env)
18
+ $.cwd = cwd
19
+
20
+ console.log(`push release tag ${tag}`)
21
+
22
+ await $`git config user.name ${gitCommitterName}`
23
+ await $`git config user.email ${gitCommitterEmail}`
24
+ await $`git tag -m ${tag} ${tag}`
25
+ await $`git push origin ${tag}`
26
+ })
27
+
28
+ export const pushMeta = async (pkg) => {
29
+ console.log('push artifact to branch `meta`')
30
+
31
+ const cwd = pkg.absPath
32
+ const {name, version} = pkg
33
+ const tag = formatTag({name, version})
34
+ const to = getArtifactPath(tag)
35
+ const branch = 'meta'
36
+ const msg = `chore: release meta ${name} ${version}`
37
+ const meta = {
38
+ META_VERSION,
39
+ name: pkg.name,
40
+ version: pkg.version,
41
+ dependencies: pkg.dependencies,
42
+ devDependencies: pkg.devDependencies,
43
+ peerDependencies: pkg.peerDependencies,
44
+ optionalDependencies: pkg.optionalDependencies,
45
+ }
46
+ const files = [{relpath: 'meta.json', contents: meta}]
47
+
48
+ await push({cwd, to, branch, msg, files})
49
+ }
50
+
51
+ export const npmPublish = ({absPath: cwd}) => ctx(async ($) => {
52
+ const {npmRegistry, npmToken, npmConfig} = parseEnv($.env)
53
+ const npmrc = npmConfig ? npmConfig : path.resolve(cwd, '.npmrc')
54
+
55
+ console.log(`publish npm package to ${npmRegistry}`)
56
+ $.cwd = cwd
57
+ if (!npmConfig) {
58
+ await $.raw`echo ${npmRegistry.replace(/https?:/, '')}/:_authToken=${npmToken} >> ${npmrc}`
59
+ }
60
+ await $`npm publish --no-git-tag-version --registry=${npmRegistry} --userconfig ${npmrc} --no-workspaces`
61
+ })
62
+
63
+ export const createGhRelease = (pkg) => ctx(async ($) => {
64
+ console.log('create gh release')
65
+
66
+ const cwd = pkg.absPath
67
+ const {name, version} = pkg
68
+ const {ghUser, ghToken} = parseEnv($.env)
69
+ const {repoName, repoPublicUrl} = await parseRepo(cwd)
70
+
71
+ if (!ghToken || !ghUser) return null
72
+
73
+ const tag = formatTag({name, version})
74
+ const releaseDiffRef = `## [${name}@${version}](${repoPublicUrl}/compare/${pkg.latest.tag?.ref}...${tag}) (${new Date().toISOString().slice(0, 10)})`
75
+ const releaseDetails = Object.values(pkg.changes
76
+ .reduce((acc, {group, subj, short, hash}) => {
77
+ const {commits} = acc[group] || (acc[group] = {commits: [], group})
78
+ const commitRef = `* ${subj}${short ? ` [${short}](${repoPublicUrl}/commit/${hash})` : ''}`
79
+
80
+ commits.push(commitRef)
81
+
82
+ return acc
83
+ }, {}))
84
+ .map(({group, commits}) => `
85
+ ### ${group}
86
+ ${commits.join('\n')}`).join('\n')
87
+
88
+ const releaseNotes = releaseDiffRef + '\n' + releaseDetails + '\n'
89
+ const releaseData = JSON.stringify({
90
+ name: tag,
91
+ tag_name: tag,
92
+ body: releaseNotes
93
+ })
94
+
95
+ $.cwd = cwd
96
+ await $`curl -u ${ghUser}:${ghToken} -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/${repoName}/releases -d ${releaseData}`
97
+ })
98
+
8
99
  export const getOrigin = (cwd) => ctx(async ($) => {
9
100
  $.cwd = cwd
10
- const {GH_USER, GH_USERNAME, GITHUB_USER, GITHUB_USERNAME, GH_TOKEN, GITHUB_TOKEN} = $.env
11
- const username = GH_USER || GITHUB_USER || GH_USERNAME || GITHUB_USERNAME
12
- const token = GH_TOKEN || GITHUB_TOKEN
101
+ const {ghToken, ghUser} = parseEnv($.env)
13
102
  const originUrl = (await $`git config --get remote.origin.url`).toString().trim()
14
103
  const [,,repoHost, repoName] = originUrl.replace(':', '/').replace(/\.git/, '').match(/.+(@|\/\/)([^/]+)\/(.+)$/) || []
15
104
 
16
- return token && username && repoHost && repoName?
17
- `https://${username}:${token}@${repoHost}/${repoName}`
105
+ return ghToken && ghUser && repoHost && repoName?
106
+ `https://${ghUser}:${ghToken}@${repoHost}/${repoName}`
18
107
  : originUrl
19
108
  })
20
109
 
110
+ const branches = {}
21
111
  export const fetch = async ({cwd: _cwd, branch, origin: _origin}) => ctx(async ($) => {
22
112
  let cwd = branches[branch]
23
113
  if (cwd) return cwd
@@ -40,6 +130,7 @@ export const fetch = async ({cwd: _cwd, branch, origin: _origin}) => ctx(async (
40
130
 
41
131
  export const push = async ({cwd, from, to, branch, origin, msg, ignoreFiles, files = []}) => ctx(async ($) => {
42
132
  const _cwd = await fetch({cwd, branch, origin})
133
+ const {gitCommitterEmail, gitCommitterName} = parseEnv($.env)
43
134
 
44
135
  for (let {relpath, contents} of files) {
45
136
  const _contents = typeof contents === 'string' ? contents : JSON.stringify(contents, null, 2)
@@ -49,38 +140,13 @@ export const push = async ({cwd, from, to, branch, origin, msg, ignoreFiles, fil
49
140
 
50
141
  $.cwd = _cwd
51
142
 
52
- await $`git config user.name ${$.env.GIT_COMMITTER_NAME || 'Semrel Extra Bot'}`
53
- await $`git config user.email ${$.env.GIT_COMMITTER_EMAIL || 'semrel-extra-bot@hotmail.com'}`
143
+ await $`git config user.name ${gitCommitterEmail}`
144
+ await $`git config user.email ${gitCommitterName}`
54
145
  await $`git add .`
55
146
  await $`git commit -m ${msg}`
56
147
  await $.raw`git push origin HEAD:refs/heads/${branch}`
57
148
  })
58
149
 
59
- export const publish = async (pkg, env) => ctx(async ($) => {
60
- const {name, version} = pkg.manifest
61
- const tag = formatTag({name, version})
62
- const cwd = pkg.absPath
63
-
64
- $.cwd = cwd
65
- $.env = env
66
-
67
- console.log(`push release tag ${tag}`)
68
- await $`git config user.name ${$.env.GIT_COMMITTER_NAME || 'Semrel Extra Bot'}`
69
- await $`git config user.email ${$.env.GIT_COMMITTER_EMAIL || 'semrel-extra-bot@hotmail.com'}`
70
- await $`git tag -m ${tag} ${tag}`
71
- await $`git push origin ${tag}`
72
-
73
- console.log('push artifact to branch `meta`')
74
- await pushMeta(pkg)
75
-
76
- const registry = env.NPM_REGISTRY || 'https://registry.npmjs.org'
77
- const npmrc = path.resolve(cwd, '.npmrc')
78
- console.log(`publish npm package to ${registry}`)
79
-
80
- await $.raw`echo ${registry.replace(/https?:/, '')}/:_authToken=${$.env.NPM_TOKEN} >> ${npmrc}`
81
- await $`npm publish --no-git-tag-version --registry=${registry} --userconfig ${npmrc} --no-workspaces`
82
- })
83
-
84
150
  export const getArtifactPath = (tag) => tag.toLowerCase().replace(/[^a-z0-9-]/g, '-')
85
151
 
86
152
  export const getLatestMeta = async (cwd, tag) => {
@@ -94,27 +160,6 @@ export const getLatestMeta = async (cwd, tag) => {
94
160
  return null
95
161
  }
96
162
 
97
- export const pushMeta = async (pkg) => ctx(async ($) => {
98
- const cwd = pkg.absPath
99
- const {name, version} = pkg
100
- const tag = formatTag({name, version})
101
- const to = getArtifactPath(tag)
102
- const branch = 'meta'
103
- const msg = `chore: release meta ${name} ${version}`
104
- const meta = {
105
- META_VERSION,
106
- name: pkg.name,
107
- version: pkg.version,
108
- dependencies: pkg.dependencies,
109
- devDependencies: pkg.devDependencies,
110
- peerDependencies: pkg.peerDependencies,
111
- optionalDependencies: pkg.optionalDependencies,
112
- }
113
- const files = [{relpath: 'meta.json', contents: meta}]
114
-
115
- await push({cwd, to, branch, msg, files})
116
- })
117
-
118
163
  export const getLatest = async (cwd, name) => {
119
164
  const tag = await getLatestTag(cwd, name)
120
165
  const meta = await getLatestMeta(cwd, tag?.ref)
@@ -124,3 +169,30 @@ export const getLatest = async (cwd, name) => {
124
169
  meta
125
170
  }
126
171
  }
172
+
173
+ export const parseEnv = (env = process.env) => {
174
+ 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
175
+
176
+ return {
177
+ ghUser: GH_USER || GH_USERNAME || GITHUB_USER || GITHUB_USERNAME,
178
+ ghToken: GH_TOKEN || GITHUB_TOKEN,
179
+ npmConfig: NPMRC || NPM_USERCONFIG || NPM_CONFIG_USERCONFIG,
180
+ npmToken: NPM_TOKEN,
181
+ npmRegistry: NPM_REGISTRY || 'https://registry.npmjs.org',
182
+ gitCommitterName: GIT_COMMITTER_NAME || 'Semrel Extra Bot',
183
+ gitCommitterEmail: GIT_COMMITTER_EMAIL || 'semrel-extra-bot@hotmail.com',
184
+ }
185
+ }
186
+
187
+ export const parseRepo = (cwd, origin) => ctx(async ($) => {
188
+ $.cwd = cwd
189
+ const originUrl = origin || (await $`git config --get remote.origin.url`).toString().trim()
190
+ const [,,repoHost, repoName] = originUrl.replace(':', '/').replace(/\.git/, '').match(/.+(@|\/\/)([^/]+)\/(.+)$/) || []
191
+
192
+ const repoPublicUrl = `https://${repoHost}/${repoName}`
193
+ return {
194
+ repoName,
195
+ repoHost,
196
+ repoPublicUrl
197
+ }
198
+ })
@@ -62,7 +62,12 @@ const lerna = {
62
62
  if (!semver.valid(version)) return null
63
63
 
64
64
  return {name, version, format: 'lerna', ref: tag}
65
- }
65
+ },
66
+ // format({name, version}) {
67
+ // if (!semver.valid(version)) return null
68
+ //
69
+ // return `${name}@${version}`
70
+ // }
66
71
  }
67
72
 
68
73
  // TODO