zx-bulk-release 1.26.0 → 1.26.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,13 @@
1
+ ## [1.26.2](https://github.com/semrel-extra/zx-bulk-release/compare/v1.26.1...v1.26.2) (2023-03-21)
2
+
3
+ ### Fixes & improvements
4
+ * refactor: separate processor layer ([dae6b96](https://github.com/semrel-extra/zx-bulk-release/commit/dae6b9682cd7d283e4f776c69f30c5f50fe9fa41))
5
+
6
+ ## [1.26.1](https://github.com/semrel-extra/zx-bulk-release/compare/v1.26.0...v1.26.1) (2023-02-08)
7
+
8
+ ### Fixes & improvements
9
+ * fix: allow multiple scopes in prefix ([2df6cb7](https://github.com/semrel-extra/zx-bulk-release/commit/2df6cb7999bed91968693069b80adeeb29b3890a))
10
+
1
11
  ## [1.26.0](https://github.com/semrel-extra/zx-bulk-release/compare/v1.25.3...v1.26.0) (2023-01-17)
2
12
 
3
13
  ### Features
package/README.md CHANGED
@@ -278,7 +278,7 @@ Release process state is reported to the console and to a file if `--report` fla
278
278
  events: [
279
279
  {msg: ['zx-bulk-release'], scope:'~', date: 1665839585488, level: 'info'},
280
280
  {msg: ['queue:',['a','b']], scope:'~', date: 1665839585493, level: 'info'},
281
- {msg: ["run buildCmd 'yarn && yarn build && yarn test'"], scope: 'a', date:1665839585719, level:'info'},
281
+ {msg: ["run buildCmd 'yarn && yarn build && yarn test'"], scope: 'a', date: 1665839585719, level:'info'},
282
282
  // ...
283
283
  ]
284
284
  }
@@ -299,6 +299,8 @@ Release process state is reported to the console and to a file if `--report` fla
299
299
  * [vercel/turborepo](https://github.com/vercel/turborepo)
300
300
  * [lerna/lerna](https://github.com/lerna/lerna)
301
301
  * [nrwl/nx](https://github.com/nrwl/nx)
302
+ * [moonrepo/moon](https://github.com/moonrepo/moon)
303
+ * [ojkelly/yarn.build](https://github.com/ojkelly/yarn.build)
302
304
 
303
305
  ## License
304
306
  [MIT](./LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zx-bulk-release",
3
- "version": "1.26.0",
3
+ "version": "1.26.2",
4
4
  "description": "zx-based alternative for multi-semantic-release",
5
5
  "type": "module",
6
6
  "exports": {
@@ -21,14 +21,14 @@
21
21
  "docs": "mkdir -p docs && cp ./README.md ./docs/README.md"
22
22
  },
23
23
  "dependencies": {
24
- "@semrel-extra/topo": "^1.4.4",
25
- "cosmiconfig": "^8.0.0",
26
- "zx-extra": "^2.5.3"
24
+ "@semrel-extra/topo": "^1.6.0",
25
+ "cosmiconfig": "^8.1.3",
26
+ "zx-extra": "^2.5.4"
27
27
  },
28
28
  "devDependencies": {
29
- "c8": "^7.12.0",
29
+ "c8": "^7.13.0",
30
30
  "uvu": "^0.5.6",
31
- "verdaccio": "^5.19.1"
31
+ "verdaccio": "^5.22.1"
32
32
  },
33
33
  "publishConfig": {
34
34
  "access": "public"
@@ -1,7 +1,7 @@
1
1
  import {ctx, semver} from 'zx-extra'
2
2
  import {updateDeps} from './deps.js'
3
3
  import {formatTag} from './tag.js';
4
- import {log} from './util.js'
4
+ import {log} from './log.js'
5
5
 
6
6
  export const analyze = async (pkg, packages) => {
7
7
  const semanticChanges = await getSemanticChanges(pkg.absPath, pkg.latest.tag?.ref)
@@ -21,7 +21,7 @@ export const analyze = async (pkg, packages) => {
21
21
  export const releaseSeverityOrder = ['major', 'minor', 'patch']
22
22
  export const semanticRules = [
23
23
  {group: 'Features', releaseType: 'minor', prefixes: ['feat']},
24
- {group: 'Fixes & improvements', releaseType: 'patch', prefixes: ['fix', 'perf', 'refactor', 'docs']},
24
+ {group: 'Fixes & improvements', releaseType: 'patch', prefixes: ['fix', 'perf', 'refactor', 'docs', 'patch']},
25
25
  {group: 'BREAKING CHANGES', releaseType: 'major', keywords: ['BREAKING CHANGE', 'BREAKING CHANGES']},
26
26
  ]
27
27
 
@@ -41,10 +41,14 @@ export const getPkgCommits = async (cwd, since) => ctx(async ($) => {
41
41
 
42
42
  export const getSemanticChanges = async (cwd, since) => {
43
43
  const commits = await getPkgCommits(cwd, since)
44
- const semanticChanges = commits
45
- .reduce((acc, {subj, body, short, hash}) => {
44
+
45
+ return analyzeCommits(commits)
46
+ }
47
+
48
+ export const analyzeCommits = (commits) =>
49
+ commits.reduce((acc, {subj, body, short, hash}) => {
46
50
  semanticRules.forEach(({group, releaseType, prefixes, keywords}) => {
47
- const prefixMatcher = prefixes && new RegExp(`^(${prefixes.join('|')})(\\([a-z0-9\\-_]+\\))?:\\s.+$`)
51
+ const prefixMatcher = prefixes && new RegExp(`^(${prefixes.join('|')})(\\([a-z0-9\\-_,]+\\))?:\\s.+$`)
48
52
  const keywordsMatcher = keywords && new RegExp(`(${keywords.join('|')}):\\s(.+)`)
49
53
  const change = subj.match(prefixMatcher)?.[0] || body.match(keywordsMatcher)?.[2]
50
54
 
@@ -63,9 +67,6 @@ export const getSemanticChanges = async (cwd, since) => {
63
67
  return acc
64
68
  }, [])
65
69
 
66
- return semanticChanges
67
- }
68
-
69
70
  export const getNextReleaseType = (changes) => changes.length
70
71
  ? releaseSeverityOrder.find(type => changes.find(({releaseType}) => type === releaseType))
71
72
  : null
@@ -1,6 +1,6 @@
1
1
  import {traverseDeps} from './deps.js'
2
2
  import {fetchPkg} from './npm.js'
3
- import {runHook} from './util.js'
3
+ import {runHook} from './processor.js'
4
4
 
5
5
  export const build = async (pkg, packages) => {
6
6
  if (pkg.built) return true
@@ -1,62 +1 @@
1
- import {within, $} from 'zx-extra'
2
- import {analyze} from './analyze.js'
3
- import {publish} from './publish.js'
4
- import {build} from './build.js'
5
- import {contextify} from './contextify.js'
6
- import {topo} from './topo.js'
7
- import {createReporter, log} from './util.js';
8
-
9
- export {getLatestTaggedVersion} from './tag.js'
10
-
11
- export const run = async ({cwd = process.cwd(), env, flags = {}} = {}) => within(async () => {
12
- const reporter = $.r = createReporter(flags.report)
13
- $.env = {...process.env, ...env}
14
- $.verbose = !!(flags.debug || $.env.DEBUG ) || $.verbose
15
- log()('zx-bulk-release')
16
-
17
- try {
18
- const {packages, queue, root} = await topo({cwd, flags})
19
- log()('queue:', queue)
20
-
21
- reporter.setQueue(queue, packages)
22
- reporter.setStatus('pending')
23
-
24
- for (let name of queue) {
25
- const pkg = packages[name]
26
-
27
- reporter.setStatus('analyzing', name)
28
- await contextify(pkg, packages, root)
29
- await analyze(pkg, packages)
30
- reporter.setState('config', pkg.config, name)
31
- reporter.setState('version', pkg.version, name)
32
- reporter.setState('prevVersion', pkg.latest.tag?.version || pkg.manifest.version, name)
33
- reporter.setState('releaseType', pkg.releaseType, name)
34
- reporter.setState('tag', pkg.tag, name)
35
-
36
- if (!pkg.releaseType) {
37
- reporter.setStatus('skipped', name)
38
- continue
39
- }
40
-
41
- reporter.setStatus('building', name)
42
- await build(pkg, packages)
43
-
44
- if (flags.dryRun) {
45
- reporter.setStatus('success', name)
46
- continue
47
- }
48
-
49
- reporter.setStatus('publishing', name)
50
- await publish(pkg)
51
-
52
- reporter.setStatus('success', name)
53
- }
54
- } catch (e) {
55
- log({level: 'error'})(e)
56
- reporter.setState('error', e)
57
- reporter.setStatus('failure')
58
- throw e
59
- }
60
- reporter.setStatus('success')
61
- log()('Great success!')
62
- })
1
+ export {run} from './processor.js'
@@ -0,0 +1,9 @@
1
+ import {$} from 'zx-extra'
2
+
3
+ export const log = (ctx) => {
4
+ if ($.state) {
5
+ return $.state.log(ctx)
6
+ }
7
+
8
+ return console.log
9
+ }
@@ -1,5 +1,5 @@
1
1
  import {parseEnv} from './config.js'
2
- import {log} from './util.js'
2
+ import {log} from './log.js'
3
3
  import {$, ctx, fs, path, tempy, copy, INI, fetch} from 'zx-extra'
4
4
 
5
5
  export const fetchPkg = async (pkg, {env = $.env} = {}) => {
@@ -0,0 +1,74 @@
1
+ import os from 'node:os'
2
+ import {$, fs, within} from 'zx-extra'
3
+ import {log} from './log.js'
4
+ import {topo} from './topo.js'
5
+ import {contextify} from './contextify.js'
6
+ import {analyze} from './analyze.js'
7
+ import {build} from './build.js'
8
+ import {publish} from './publish.js'
9
+ import {createState} from './state.js'
10
+ import {tpl} from "./util.js";
11
+
12
+ export const run = async ({cwd = process.cwd(), env, flags = {}, concurrency = os.cpus().length} = {}) => within(async () => {
13
+ const state = createState({file: flags.report})
14
+ $.state = state
15
+ $.env = {...process.env, ...env}
16
+ $.verbose = !!(flags.debug || $.env.DEBUG ) || $.verbose
17
+
18
+ log()('zx-bulk-release')
19
+
20
+ try {
21
+ const {packages, queue, root} = await topo({cwd, flags})
22
+ log()('queue:', queue)
23
+
24
+ state.setQueue(queue, packages)
25
+ state.setStatus('pending')
26
+
27
+ for (let name of queue) {
28
+ const pkg = packages[name]
29
+
30
+ state.setStatus('analyzing', name)
31
+ await contextify(pkg, packages, root)
32
+ await analyze(pkg, packages)
33
+ state.set('config', pkg.config, name)
34
+ state.set('version', pkg.version, name)
35
+ state.set('prevVersion', pkg.latest.tag?.version || pkg.manifest.version, name)
36
+ state.set('releaseType', pkg.releaseType, name)
37
+ state.set('tag', pkg.tag, name)
38
+
39
+ if (!pkg.releaseType) {
40
+ state.setStatus('skipped', name)
41
+ continue
42
+ }
43
+
44
+ state.setStatus('building', name)
45
+ await build(pkg, packages)
46
+
47
+ if (flags.dryRun) {
48
+ state.setStatus('success', name)
49
+ continue
50
+ }
51
+
52
+ state.setStatus('publishing', name)
53
+ await publish(pkg)
54
+
55
+ state.setStatus('success', name)
56
+ }
57
+ } catch (e) {
58
+ log({level: 'error'})(e)
59
+ state.set('error', e)
60
+ state.setStatus('failure')
61
+ throw e
62
+ }
63
+ state.setStatus('success')
64
+ log()('Great success!')
65
+ })
66
+
67
+ export const runHook = async (pkg, name) => {
68
+ const cmd = tpl(pkg.config[name], {...pkg, ...pkg.context})
69
+
70
+ if (cmd) {
71
+ log({pkg})(`run ${name} '${cmd}'`)
72
+ await $.o({cwd: pkg.absPath, quote: v => v, preferLocal: true})`${cmd}`
73
+ }
74
+ }
@@ -1,9 +1,11 @@
1
- import {formatTag, getLatestTag, pushTag} from './tag.js'
2
1
  import {fs, path, $} from 'zx-extra'
2
+ import {formatTag, getLatestTag, pushTag} from './tag.js'
3
3
  import {push, fetch, parseRepo} from './repo.js'
4
4
  import {parseEnv} from './config.js'
5
5
  import {fetchManifest, npmPublish} from './npm.js'
6
- import {restJoin, runHook, log} from './util.js'
6
+ import {restJoin} from './util.js'
7
+ import {runHook} from './processor.js'
8
+ import {log} from './log.js'
7
9
 
8
10
  export const publish = async (pkg) => {
9
11
  await fs.writeJson(pkg.manifestPath, pkg.manifest, {spaces: 2})
@@ -1,6 +1,6 @@
1
1
  import {$, ctx, fs, path, tempy, copy} from 'zx-extra'
2
2
  import {parseEnv} from './config.js'
3
- import {log} from './util.js'
3
+ import {log} from './log.js'
4
4
 
5
5
  const branches = {}
6
6
  export const fetch = async ({cwd: _cwd, branch, origin: _origin}) => ctx(async ($) => {
@@ -58,8 +58,8 @@ export const parseRepo = async (_cwd) => {
58
58
  const originUrl = await getOrigin(cwd)
59
59
  const [, , repoHost, repoName] = originUrl.replace(':', '/').replace(/\.git/, '').match(/.+(@|\/\/)([^/]+)\/(.+)$/) || []
60
60
  const repoPublicUrl = `https://${repoHost}/${repoName}`
61
- const repoAuthedUrl = ghToken && ghUser && repoHost && repoName ?
62
- `https://${ghUser}:${ghToken}@${repoHost}/${repoName}.git`
61
+ const repoAuthedUrl = ghToken && ghUser && repoHost && repoName
62
+ ? `https://${ghUser}:${ghToken}@${repoHost}/${repoName}.git`
63
63
  : originUrl
64
64
 
65
65
  repos[cwd] = {
@@ -0,0 +1,56 @@
1
+ import {get, set, tpl} from './util.js'
2
+ import {fs} from 'zx-extra'
3
+
4
+ export const createState = ({logger = console, file = null} = {}) => ({
5
+ logger,
6
+ file,
7
+ status: 'initial',
8
+ queue: [],
9
+ packages: [],
10
+ events: [],
11
+ setQueue(queue, packages) {
12
+ this.queue = queue
13
+ this.packages = queue.map(name => {
14
+ const {manifest: {version}, absPath, relPath} = packages[name]
15
+ return {
16
+ status: 'initial',
17
+ name,
18
+ version,
19
+ path: absPath,
20
+ relPath
21
+ }
22
+ })
23
+ },
24
+ get(key, pkgName) {
25
+ return get(
26
+ pkgName ? this.packages.find(({name}) => name === pkgName) : this,
27
+ key
28
+ )
29
+ },
30
+ set(key, value, pkgName) {
31
+ set(
32
+ pkgName ? this.packages.find(({name}) => name === pkgName) : this,
33
+ key,
34
+ value
35
+ )
36
+ },
37
+ setStatus(status, name) {
38
+ this.set('status', status, name)
39
+ this.save()
40
+ },
41
+ getStatus(status, name) {
42
+ return this.get('status', name)
43
+ },
44
+ log(ctx = {}) {
45
+ return function (...chunks) {
46
+ const {pkg, scope = pkg?.name || '~', level = 'info'} = ctx
47
+ const msg = chunks.map(c => typeof c === 'string' ? tpl(c, ctx) : c)
48
+ const event = {msg, scope, date: Date.now(), level}
49
+ this.events.push(event)
50
+ logger[level](`[${scope}]`, ...msg)
51
+ }.bind(this)
52
+ },
53
+ save() {
54
+ this.file && fs.outputJsonSync(this.file, this)
55
+ }
56
+ })
@@ -3,7 +3,7 @@
3
3
  import {ctx, semver, $} from 'zx-extra'
4
4
  import {Buffer} from 'buffer'
5
5
  import {parseEnv} from './config.js'
6
- import {log} from './util.js'
6
+ import {log} from './log.js'
7
7
 
8
8
  export const pushTag = (pkg) => ctx(async ($) => {
9
9
  const {absPath: cwd, name, version} = pkg
@@ -30,73 +30,4 @@ export const set = (obj, path, value) => {
30
30
  return result
31
31
  }
32
32
 
33
- export const runHook = async (pkg, name) => {
34
- const cmd = tpl(pkg.config[name], {...pkg, ...pkg.context})
35
-
36
- if (cmd) {
37
- log({pkg})(`run ${name} '${cmd}'`)
38
- await $.o({cwd: pkg.absPath, quote: v => v, preferLocal: true})`${cmd}`
39
- }
40
- }
41
-
42
33
  export const restJoin = (rest, context, def) => tpl(rest.filter(Boolean).join(' ') || def, context)
43
-
44
- export const createReporter = (file, logger = console) => {
45
- const state = {
46
- status: 'initial',
47
- queue: [],
48
- packages: [],
49
- events: [],
50
- }
51
-
52
- return {
53
- setQueue(queue, packages) {
54
- state.queue = queue
55
- state.packages = queue.map(name => {
56
- const {manifest: {version}, absPath, relPath} = packages[name]
57
- return {
58
- status: 'initial',
59
- name,
60
- version,
61
- path: absPath,
62
- relPath
63
- }
64
- })
65
- },
66
- getState(key, pkgName) {
67
- const _state = pkgName ? state.packages.find(({name}) => name === pkgName) : state
68
- return get(_state, key)
69
- },
70
- setState(key, value, pkgName) {
71
- const _state = pkgName ? state.packages.find(({name}) => name === pkgName) : state
72
- set(_state, key, value)
73
- },
74
- setStatus(status, name) {
75
- this.setState('status', status, name)
76
-
77
- this.persistState()
78
- },
79
- getStatus (status, name) {
80
- return this.getState('status', name)
81
- },
82
- log(ctx = {}) { return (...chunks) => {
83
- const {pkg, scope = pkg?.name || '~', level = 'info'} = ctx
84
- const msg = chunks.map(c => typeof c === 'string' ? tpl(c, ctx) : c)
85
- const event = {msg, scope, date: Date.now(), level}
86
- state.events.push(event)
87
- logger[level](`[${scope}]`, ...msg)
88
- }},
89
- persistState() {
90
- file && fs.outputJsonSync(file, state)
91
- }
92
- }
93
- }
94
-
95
- export const log = (ctx) => {
96
- if (!$.r) {
97
- $.r = createReporter()
98
- }
99
-
100
- return $.r.log(ctx)
101
- }
102
-