zx-bulk-release 1.16.2 → 1.17.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 +19 -0
- package/README.md +94 -9
- package/package.json +1 -1
- package/src/main/js/cli.js +2 -1
- package/src/main/js/config.js +3 -0
- package/src/main/js/index.js +3 -5
- package/src/main/js/npm.js +4 -4
- package/src/main/js/topo.js +17 -0
- package/src/test/js/topo.test.js +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
## [1.17.2](https://github.com/semrel-extra/zx-bulk-release/compare/v1.17.1...v1.17.2) (2022-06-28)
|
|
2
|
+
|
|
3
|
+
### Fixes & improvements
|
|
4
|
+
* docs: add npm badge ([f63dfe3](https://github.com/semrel-extra/zx-bulk-release/commit/f63dfe338208641a8edd910b81e320deeed2446c))
|
|
5
|
+
|
|
6
|
+
## [1.17.1](https://github.com/semrel-extra/zx-bulk-release/compare/v1.17.0...v1.17.1) (2022-06-28)
|
|
7
|
+
|
|
8
|
+
### Fixes & improvements
|
|
9
|
+
* docs: describe `analyze` step ([ae611ad](https://github.com/semrel-extra/zx-bulk-release/commit/ae611ada7709d9f9fa72d20f39e74ebe05353a2d))
|
|
10
|
+
|
|
11
|
+
## [1.17.0](https://github.com/semrel-extra/zx-bulk-release/compare/v1.16.2...v1.17.0) (2022-06-28)
|
|
12
|
+
|
|
13
|
+
### Fixes & improvements
|
|
14
|
+
* docs: describe CLI options ([e744e97](https://github.com/semrel-extra/zx-bulk-release/commit/e744e97e8e5451ffff217283ad4e552f05073e7c))
|
|
15
|
+
* docs: describe internal release flow ([e29bfc9](https://github.com/semrel-extra/zx-bulk-release/commit/e29bfc968a519d7c48b0475ad30c826bef17fb96))
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
* feat: introduce `--include-private` and `ignore` flags ([d029b62](https://github.com/semrel-extra/zx-bulk-release/commit/d029b6242da2e3c7fabaa5e24d61709b47e42b94))
|
|
19
|
+
|
|
1
20
|
## [1.16.2](https://github.com/semrel-extra/zx-bulk-release/compare/v1.16.1...v1.16.2) (2022-06-28)
|
|
2
21
|
|
|
3
22
|
### Fixes & improvements
|
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
[](https://github.com/semrel-extra/zx-bulk-release/actions)
|
|
5
5
|
[](https://codeclimate.com/github/semrel-extra/zx-bulk-release/maintainability)
|
|
6
6
|
[](https://codeclimate.com/github/semrel-extra/zx-bulk-release/test_coverage)
|
|
7
|
+
[](https://www.npmjs.com/package/zx-bulk-release)
|
|
7
8
|
|
|
8
9
|
🚧 Work in progress. Early access preview
|
|
9
10
|
|
|
@@ -14,7 +15,7 @@
|
|
|
14
15
|
* No default branch blocking (no release commits).
|
|
15
16
|
* Pkg changelogs go to `changelog` branch (configurable).
|
|
16
17
|
* Docs are published to `gh-pages` branch (configurable).
|
|
17
|
-
* No extra builds. The required deps are fetched from the pkg registry (`npmFetch`
|
|
18
|
+
* No extra builds. The required deps are fetched from the pkg registry (`npmFetch` config opt).
|
|
18
19
|
|
|
19
20
|
## Requirements
|
|
20
21
|
* macOS / linux
|
|
@@ -22,10 +23,19 @@
|
|
|
22
23
|
* npm >=7 / yarn >= 3
|
|
23
24
|
|
|
24
25
|
## Usage
|
|
26
|
+
### Install
|
|
27
|
+
```shell
|
|
28
|
+
yarn add zx-bulk-release
|
|
29
|
+
```
|
|
25
30
|
### CLI
|
|
26
31
|
```shell
|
|
27
32
|
GH_TOKEN=ghtoken GH_USER=username NPM_TOKEN=npmtoken npx zx-bulk-release [opts]
|
|
28
33
|
```
|
|
34
|
+
| Flag | Description | Default |
|
|
35
|
+
|---------------------|----------------------------|----------|
|
|
36
|
+
| `--dry-run` | Dry run mode | `false` |
|
|
37
|
+
| `--ignore` | Packages to ignore: `a, b` | |
|
|
38
|
+
| `--include-private` | Include private pkgs | `false` |
|
|
29
39
|
|
|
30
40
|
### JS API
|
|
31
41
|
```js
|
|
@@ -59,7 +69,7 @@ Any [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) compliant format
|
|
|
59
69
|
|
|
60
70
|
### Output
|
|
61
71
|
|
|
62
|
-
[
|
|
72
|
+
[Compact and clear logs](https://github.com/semrel-extra/demo-zx-bulk-release/runs/7090161341?check_suite_focus=true#step:6:1)
|
|
63
73
|
|
|
64
74
|
```shell
|
|
65
75
|
Run npm_config_yes=true npx zx-bulk-release
|
|
@@ -99,6 +109,81 @@ zx-bulk-release
|
|
|
99
109
|
```
|
|
100
110
|
|
|
101
111
|
## Implementation notes
|
|
112
|
+
### Flow
|
|
113
|
+
```js
|
|
114
|
+
try {
|
|
115
|
+
const {packages, queue, root} = await topo({cwd, flags})
|
|
116
|
+
console.log('queue:', queue)
|
|
117
|
+
|
|
118
|
+
for (let name of queue) {
|
|
119
|
+
const pkg = packages[name]
|
|
120
|
+
|
|
121
|
+
await analyze(pkg, packages, root)
|
|
122
|
+
|
|
123
|
+
if (pkg.changes.length === 0) continue
|
|
124
|
+
|
|
125
|
+
await build(pkg, packages)
|
|
126
|
+
|
|
127
|
+
if (flags.dryRun) continue
|
|
128
|
+
|
|
129
|
+
await publish(pkg)
|
|
130
|
+
}
|
|
131
|
+
} catch (e) {
|
|
132
|
+
console.error(e)
|
|
133
|
+
throw e
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### `topo`
|
|
138
|
+
[Toposort](https://github.com/semrel-extra/topo) is used to resolve the pkg release queue.
|
|
139
|
+
By default, it omits the packages marked as `private`. You can override this by setting the `--include-private` flag.
|
|
140
|
+
|
|
141
|
+
### `analyze`
|
|
142
|
+
Determines pkg changes, release type, next version etc.
|
|
143
|
+
```js
|
|
144
|
+
export const analyze = async (pkg, packages, root) => {
|
|
145
|
+
pkg.config = await getConfig(pkg.absPath, root.absPath)
|
|
146
|
+
pkg.latest = await getLatest(pkg)
|
|
147
|
+
|
|
148
|
+
const semanticChanges = await getSemanticChanges(pkg.absPath, pkg.latest.tag?.ref)
|
|
149
|
+
const depsChanges = await updateDeps(pkg, packages)
|
|
150
|
+
const changes = [...semanticChanges, ...depsChanges]
|
|
151
|
+
|
|
152
|
+
pkg.changes = changes
|
|
153
|
+
pkg.version = resolvePkgVersion(changes, pkg.latest.tag?.version || pkg.manifest.version)
|
|
154
|
+
pkg.manifest.version = pkg.version
|
|
155
|
+
|
|
156
|
+
console.log(`[${pkg.name}] semantic changes`, changes)
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `build`
|
|
161
|
+
Applies `config.cmd` to build pkg assets: bundles, docs, etc.
|
|
162
|
+
```js
|
|
163
|
+
export const build = async (pkg, packages) => {
|
|
164
|
+
// ...
|
|
165
|
+
if (!pkg.fetched && config.cmd) {
|
|
166
|
+
console.log(`[${pkg.name}] run cmd '${config.cmd}'`)
|
|
167
|
+
await $.o({cwd: pkg.absPath, quote: v => v})`${config.cmd}`
|
|
168
|
+
}
|
|
169
|
+
// ...
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### `publish`
|
|
174
|
+
Publish the pkg to git, npm, gh-pages, gh-release, etc.
|
|
175
|
+
```js
|
|
176
|
+
export const publish = async (pkg) => {
|
|
177
|
+
await fs.writeJson(pkg.manifestPath, pkg.manifest, {spaces: 2})
|
|
178
|
+
await pushTag(pkg)
|
|
179
|
+
await pushMeta(pkg)
|
|
180
|
+
await pushChangelog(pkg)
|
|
181
|
+
await npmPublish(pkg)
|
|
182
|
+
await ghRelease(pkg)
|
|
183
|
+
await ghPages(pkg)
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
102
187
|
### Tags
|
|
103
188
|
[Lerna](https://github.com/lerna/lerna) tags (like `@pkg/name@v1.0.0-beta.0`) are suitable for monorepos, but they don’t follow [semver spec](https://semver.org/). Therefore, we propose another contract:
|
|
104
189
|
```js
|
|
@@ -117,14 +202,14 @@ export const parseEnv = (env = process.env) => {
|
|
|
117
202
|
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
|
|
118
203
|
|
|
119
204
|
return {
|
|
120
|
-
ghUser:
|
|
121
|
-
ghToken:
|
|
122
|
-
npmToken:
|
|
205
|
+
ghUser: GH_USER || GH_USERNAME || GITHUB_USER || GITHUB_USERNAME,
|
|
206
|
+
ghToken: GH_TOKEN || GITHUB_TOKEN,
|
|
207
|
+
npmToken: NPM_TOKEN,
|
|
123
208
|
// npmConfig suppresses npmToken
|
|
124
|
-
npmConfig:
|
|
125
|
-
npmRegistry:
|
|
126
|
-
gitCommitterName:
|
|
127
|
-
gitCommitterEmail:
|
|
209
|
+
npmConfig: NPMRC || NPM_USERCONFIG || NPM_CONFIG_USERCONFIG,
|
|
210
|
+
npmRegistry: NPM_REGISTRY || 'https://registry.npmjs.org',
|
|
211
|
+
gitCommitterName: GIT_COMMITTER_NAME || 'Semrel Extra Bot',
|
|
212
|
+
gitCommitterEmail: GIT_COMMITTER_EMAIL || 'semrel-extra-bot@hotmail.com',
|
|
128
213
|
}
|
|
129
214
|
}
|
|
130
215
|
```
|
package/package.json
CHANGED
package/src/main/js/cli.js
CHANGED
package/src/main/js/config.js
CHANGED
|
@@ -46,3 +46,6 @@ export const parseEnv = (env = process.env) => {
|
|
|
46
46
|
gitCommitterEmail: GIT_COMMITTER_EMAIL || 'semrel-extra-bot@hotmail.com',
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
const camelize = s => s.replace(/-./g, x=>x[1].toUpperCase())
|
|
51
|
+
export const normalizeFlags = (flags = {}) => Object.entries(flags).reduce((acc, [k, v]) => ({...acc, [camelize(k)]: v}), {})
|
package/src/main/js/index.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import {topo} from '@semrel-extra/topo'
|
|
2
1
|
import {analyze} from './analyze.js'
|
|
3
2
|
import {publish} from './publish.js'
|
|
4
3
|
import {build} from './build.js'
|
|
4
|
+
import {topo} from './topo.js'
|
|
5
5
|
|
|
6
6
|
export const run = async ({cwd = process.cwd(), env = process.env, flags = {}} = {}) => {
|
|
7
7
|
console.log('zx-bulk-release')
|
|
8
8
|
|
|
9
9
|
try {
|
|
10
|
-
const {packages, queue, root} = await topo({cwd})
|
|
11
|
-
const dryRun = flags['dry-run'] || flags.dryRun
|
|
12
|
-
|
|
10
|
+
const {packages, queue, root} = await topo({cwd, flags})
|
|
13
11
|
console.log('queue:', queue)
|
|
14
12
|
|
|
15
13
|
for (let name of queue) {
|
|
@@ -21,7 +19,7 @@ export const run = async ({cwd = process.cwd(), env = process.env, flags = {}} =
|
|
|
21
19
|
|
|
22
20
|
await build(pkg, packages)
|
|
23
21
|
|
|
24
|
-
if (dryRun) continue
|
|
22
|
+
if (flags.dryRun) continue
|
|
25
23
|
|
|
26
24
|
await publish(pkg)
|
|
27
25
|
}
|
package/src/main/js/npm.js
CHANGED
|
@@ -50,10 +50,6 @@ export const npmPublish = (pkg) => ctx(async ($) => {
|
|
|
50
50
|
await $`npm publish --no-git-tag-version --registry=${npmRegistry} --userconfig ${npmrc} --no-workspaces`
|
|
51
51
|
})
|
|
52
52
|
|
|
53
|
-
// NOTE registry-auth-token does not work with localhost:4873
|
|
54
|
-
export const getAuthToken = (registry, npmrc) =>
|
|
55
|
-
(Object.entries(npmrc).find(([reg]) => reg.startsWith(registry.replace(/^https?/, ''))) || [])[1]
|
|
56
|
-
|
|
57
53
|
// $`npm view ${name}@${version} dist.tarball`
|
|
58
54
|
export const getTarballUrl = (registry, name, version) => `${registry}/${name}/-/${name.replace(/^.+(%2f|\/)/,'')}-${version}.tgz`
|
|
59
55
|
|
|
@@ -65,3 +61,7 @@ export const getBearerToken = async (npmRegistry, npmToken, npmConfig) => {
|
|
|
65
61
|
: npmToken
|
|
66
62
|
return `Bearer ${token}`
|
|
67
63
|
}
|
|
64
|
+
|
|
65
|
+
// NOTE registry-auth-token does not work with localhost:4873
|
|
66
|
+
export const getAuthToken = (registry, npmrc) =>
|
|
67
|
+
(Object.entries(npmrc).find(([reg]) => reg.startsWith(registry.replace(/^https?/, ''))) || [])[1]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {topo as _topo} from '@semrel-extra/topo'
|
|
2
|
+
|
|
3
|
+
export const topo = async ({flags = {}, cwd} = {}) => {
|
|
4
|
+
const ignore = typeof flags.ignore === 'string'
|
|
5
|
+
? flags.ignore.split(/\s*,\s*/)
|
|
6
|
+
: Array.isArray(flags.ignore)
|
|
7
|
+
? flags.ignore
|
|
8
|
+
: []
|
|
9
|
+
|
|
10
|
+
const filter = flags.includePrivate
|
|
11
|
+
? () => true
|
|
12
|
+
: ({manifest: {private: _private, name}}) =>
|
|
13
|
+
flags.includePrivate ? true : !_private &&
|
|
14
|
+
!ignore.includes(name)
|
|
15
|
+
|
|
16
|
+
return _topo({cwd, filter})
|
|
17
|
+
}
|
package/src/test/js/topo.test.js
CHANGED
|
@@ -2,7 +2,7 @@ import {suite} from 'uvu'
|
|
|
2
2
|
import * as assert from 'uvu/assert'
|
|
3
3
|
import {fileURLToPath} from "node:url"
|
|
4
4
|
import path from 'node:path'
|
|
5
|
-
import {topo} from '
|
|
5
|
+
import {topo} from '../../main/js/topo.js'
|
|
6
6
|
|
|
7
7
|
const test = suite('topo')
|
|
8
8
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
@@ -14,4 +14,9 @@ test('topo returns pkg info and release queue', async () => {
|
|
|
14
14
|
assert.equal(queue, ['a', 'b', 'd', 'c'])
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
+
test('topo applies pkg filter', async () => {
|
|
18
|
+
const {nodes, queue} = await topo({cwd: path.resolve(fixtures, 'regular-monorepo'), flags: {ignore: 'b,c'}})
|
|
19
|
+
assert.equal(queue, ['a', 'd'])
|
|
20
|
+
})
|
|
21
|
+
|
|
17
22
|
test.run()
|