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 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
  [![CI](https://github.com/semrel-extra/zx-bulk-release/workflows/CI/badge.svg)](https://github.com/semrel-extra/zx-bulk-release/actions)
5
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/bb94e929b1b6430781b5/maintainability)](https://codeclimate.com/github/semrel-extra/zx-bulk-release/maintainability)
6
6
  [![Test Coverage](https://api.codeclimate.com/v1/badges/bb94e929b1b6430781b5/test_coverage)](https://codeclimate.com/github/semrel-extra/zx-bulk-release/test_coverage)
7
+ [![npm (tag)](https://img.shields.io/npm/v/zx-bulk-release)](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` flag).
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
- [Readable and clear logs](https://github.com/semrel-extra/demo-zx-bulk-release/runs/7090161341?check_suite_focus=true#step:6:1)
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: GH_USER || GH_USERNAME || GITHUB_USER || GITHUB_USERNAME,
121
- ghToken: GH_TOKEN || GITHUB_TOKEN,
122
- npmToken: NPM_TOKEN,
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: NPMRC || NPM_USERCONFIG || NPM_CONFIG_USERCONFIG,
125
- npmRegistry: NPM_REGISTRY || 'https://registry.npmjs.org',
126
- gitCommitterName: GIT_COMMITTER_NAME || 'Semrel Extra Bot',
127
- gitCommitterEmail: GIT_COMMITTER_EMAIL || 'semrel-extra-bot@hotmail.com',
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zx-bulk-release",
3
- "version": "1.16.2",
3
+ "version": "1.17.2",
4
4
  "description": "zx-based alternative for multi-semantic-release",
5
5
  "type": "module",
6
6
  "exports": "./src/main/js/index.js",
@@ -2,5 +2,6 @@
2
2
 
3
3
  import {argv} from 'zx-extra'
4
4
  import {run} from './index.js'
5
+ import {normalizeFlags} from './config.js';
5
6
 
6
- run({flags: argv})
7
+ run({flags: normalizeFlags(argv)})
@@ -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}), {})
@@ -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
  }
@@ -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
+ }
@@ -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 '@semrel-extra/topo'
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()