zx-bulk-release 3.0.4 → 3.0.5
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 +5 -0
- package/package.json +1 -1
- package/src/main/js/post/courier/index.js +36 -11
- package/src/main/js/post/release.js +54 -69
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
## [3.0.5](https://github.com/semrel-extra/zx-bulk-release/compare/v3.0.4...v3.0.5) (2026-04-11)
|
|
2
|
+
|
|
3
|
+
### Fixes & improvements
|
|
4
|
+
* perf: minor code imprs ([2564f3f](https://github.com/semrel-extra/zx-bulk-release/commit/2564f3fd8fdd42c08a2aa32e1e9f2cfee7d3199d))
|
|
5
|
+
|
|
1
6
|
## [3.0.4](https://github.com/semrel-extra/zx-bulk-release/compare/v3.0.3...v3.0.4) (2026-04-11)
|
|
2
7
|
|
|
3
8
|
### Fixes & improvements
|
package/package.json
CHANGED
|
@@ -74,8 +74,9 @@ const pool = async (tasks, concurrency, fn) => {
|
|
|
74
74
|
|
|
75
75
|
// Parcels grouped by package, sorted by semver asc (latest last).
|
|
76
76
|
// Groups run in parallel (concurrency-limited), entries within a group — sequential.
|
|
77
|
-
export const
|
|
78
|
-
const
|
|
77
|
+
export const inspect = async (tars, env = process.env) => {
|
|
78
|
+
const parcels = []
|
|
79
|
+
const skipped = []
|
|
79
80
|
|
|
80
81
|
for (const tarPath of tars) {
|
|
81
82
|
const fname = path.basename(tarPath)
|
|
@@ -83,22 +84,46 @@ export const deliver = async (tars, env = process.env, {concurrency = 4} = {}) =
|
|
|
83
84
|
const p = await openParcel(tarPath, env)
|
|
84
85
|
if (!p) continue
|
|
85
86
|
if (p.warn) {
|
|
86
|
-
|
|
87
|
-
if (p.tarPath) await fs.writeFile(tarPath, 'skip')
|
|
87
|
+
skipped.push({file: fname, reason: p.warn, tarPath: p.tarPath})
|
|
88
88
|
continue
|
|
89
89
|
}
|
|
90
|
-
|
|
91
|
-
if (!groups.has(key)) groups.set(key, [])
|
|
92
|
-
groups.get(key).push(p)
|
|
90
|
+
parcels.push(p)
|
|
93
91
|
} catch (e) {
|
|
94
|
-
|
|
92
|
+
skipped.push({file: fname, reason: e.message})
|
|
95
93
|
}
|
|
96
94
|
}
|
|
97
95
|
|
|
96
|
+
// group by package, sort by semver asc within each group
|
|
97
|
+
const groups = new Map()
|
|
98
|
+
for (const p of parcels) {
|
|
99
|
+
const key = p.resolved.name || p.resolved.channel
|
|
100
|
+
if (!groups.has(key)) groups.set(key, [])
|
|
101
|
+
groups.get(key).push(p)
|
|
102
|
+
}
|
|
98
103
|
for (const g of groups.values())
|
|
99
104
|
g.sort((a, b) => semver.compare(a.resolved.version || '0.0.0', b.resolved.version || '0.0.0'))
|
|
100
105
|
|
|
101
|
-
|
|
106
|
+
return {groups, skipped, total: tars.length, pending: parcels.length}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const deliver = async (tars, env = process.env, {concurrency = 4, dryRun = false} = {}) => {
|
|
110
|
+
const {groups, skipped, total, pending} = await inspect(tars, env)
|
|
111
|
+
|
|
112
|
+
for (const {file, reason, tarPath} of skipped) {
|
|
113
|
+
log.warn(`skipping ${file}: ${reason}`)
|
|
114
|
+
if (!dryRun && tarPath) await fs.writeFile(tarPath, 'skip')
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const entries = []
|
|
118
|
+
const toEntry = ({resolved}) => ({channel: resolved.channel, name: resolved.name, version: resolved.version})
|
|
119
|
+
|
|
120
|
+
if (dryRun) {
|
|
121
|
+
for (const group of groups.values())
|
|
122
|
+
for (const p of group)
|
|
123
|
+
entries.push(toEntry(p))
|
|
124
|
+
return {total, pending: entries.length, delivered: 0, skipped: skipped.length, entries}
|
|
125
|
+
}
|
|
126
|
+
|
|
102
127
|
await pool([...groups.values()], concurrency, async (group) => {
|
|
103
128
|
for (const {ch, resolved, destDir, tarPath} of group) {
|
|
104
129
|
await within(async () => {
|
|
@@ -106,9 +131,9 @@ export const deliver = async (tars, env = process.env, {concurrency = 4} = {}) =
|
|
|
106
131
|
await ch.run(resolved, destDir)
|
|
107
132
|
})
|
|
108
133
|
await fs.writeFile(tarPath, 'released')
|
|
109
|
-
|
|
134
|
+
entries.push(toEntry({resolved}))
|
|
110
135
|
}
|
|
111
136
|
})
|
|
112
137
|
|
|
113
|
-
return delivered
|
|
138
|
+
return {total, pending, delivered: entries.length, skipped: skipped.length, entries}
|
|
114
139
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import os from 'node:os'
|
|
2
2
|
import {createRequire} from 'node:module'
|
|
3
|
-
import {$, within,
|
|
3
|
+
import {$, within, glob, path} from 'zx-extra'
|
|
4
4
|
import {queuefy} from 'queuefy'
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
import {createReport, log} from './log.js'
|
|
7
|
+
import {topo, traverseQueue} from './depot/deps.js'
|
|
7
8
|
import {exec} from './depot/exec.js'
|
|
8
|
-
|
|
9
9
|
import {contextify} from './depot/steps/contextify.js'
|
|
10
10
|
import {analyze} from './depot/steps/analyze.js'
|
|
11
11
|
import {build} from './depot/steps/build.js'
|
|
@@ -13,48 +13,58 @@ import {pack} from './depot/steps/pack.js'
|
|
|
13
13
|
import {publish} from './depot/steps/publish.js'
|
|
14
14
|
import {clean} from './depot/steps/clean.js'
|
|
15
15
|
import {test} from './depot/steps/test.js'
|
|
16
|
-
|
|
17
16
|
import {deliver, defaultOrder as channels} from './courier/index.js'
|
|
18
17
|
|
|
19
18
|
const PARCELS_DIR = 'parcels'
|
|
19
|
+
const ZBR_VERSION = createRequire(import.meta.url)('../../../../package.json').version
|
|
20
|
+
|
|
21
|
+
export const run = async ({cwd = process.cwd(), env: _env, flags = {}} = {}) => within(async () => {
|
|
22
|
+
if (flags.v || flags.version)
|
|
23
|
+
return console.log(ZBR_VERSION)
|
|
24
|
+
|
|
25
|
+
const env = {...process.env, ..._env}
|
|
26
|
+
log.secret(env.GH_TOKEN, env.GITHUB_TOKEN, env.NPM_TOKEN)
|
|
27
|
+
log.info(`zx-bulk-release@${ZBR_VERSION}`)
|
|
28
|
+
|
|
29
|
+
return flags.deliver
|
|
30
|
+
? runDeliver({env, flags})
|
|
31
|
+
: runPipeline({cwd, env, flags})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
// --deliver [dir]
|
|
35
|
+
const runDeliver = async ({env, flags}) => {
|
|
36
|
+
const dir = typeof flags.deliver === 'string' ? flags.deliver : PARCELS_DIR
|
|
37
|
+
const report = createReport({flags})
|
|
20
38
|
|
|
21
|
-
export const run = async ({cwd = process.cwd(), env, flags = {}} = {}) => within(async () => {
|
|
22
39
|
$.memo = new Map()
|
|
40
|
+
$.report = report
|
|
23
41
|
|
|
24
|
-
|
|
25
|
-
if (flags.v || flags.version) {
|
|
26
|
-
console.log(zbrVersion)
|
|
27
|
-
return
|
|
28
|
-
}
|
|
42
|
+
report.setStatus('inspecting')
|
|
29
43
|
|
|
30
|
-
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const delivered = await deliver(tars, _env)
|
|
42
|
-
log.info(`deliver: done, ${delivered} delivered`)
|
|
43
|
-
return
|
|
44
|
-
}
|
|
44
|
+
const tars = await glob(path.join(dir, 'parcel.*.tar'))
|
|
45
|
+
if (!tars.length) return report.setStatus('success').log(`no parcels in ${dir}`)
|
|
46
|
+
|
|
47
|
+
report.setStatus('delivering').log(`parcels: ${tars.length}`)
|
|
48
|
+
const result = await deliver(tars, env, {dryRun: flags.dryRun})
|
|
49
|
+
report.set('delivery', result).setStatus('success')
|
|
50
|
+
|
|
51
|
+
for (const {channel, name, version} of result.entries)
|
|
52
|
+
log.info(`${channel} ${name}@${version}`)
|
|
53
|
+
log.info(`done: ${result.delivered} delivered, ${result.skipped} skipped`)
|
|
54
|
+
}
|
|
45
55
|
|
|
56
|
+
// full pipeline (legacy / --pack)
|
|
57
|
+
const runPipeline = async ({cwd, env, flags}) => {
|
|
46
58
|
const ctx = await createContext({flags, env, cwd})
|
|
47
59
|
const {report, packages, queue, prev} = ctx
|
|
48
60
|
|
|
49
61
|
const forEachPkg = (cb) => traverseQueue({queue, prev, cb: (name) => within(async () => {
|
|
50
62
|
$.scope = name
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return cb(pkg)
|
|
63
|
+
await contextify(packages[name], ctx)
|
|
64
|
+
return cb(packages[name])
|
|
54
65
|
})})
|
|
55
66
|
|
|
56
67
|
report
|
|
57
|
-
.log(`zx-bulk-release@${zbrVersion}`)
|
|
58
68
|
.log('queue:', queue)
|
|
59
69
|
.log('graphs', ctx.graphs)
|
|
60
70
|
|
|
@@ -74,36 +84,16 @@ export const run = async ({cwd = process.cwd(), env, flags = {}} = {}) => within
|
|
|
74
84
|
report.setStatus('pending')
|
|
75
85
|
|
|
76
86
|
await forEachPkg(async (pkg) => {
|
|
77
|
-
if (!pkg.releaseType) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
report.setStatus('testing', pkg.name)
|
|
88
|
-
await test(pkg)
|
|
89
|
-
}
|
|
90
|
-
if (flags.dryRun || flags.publish === false) {
|
|
91
|
-
report.setStatus('success', pkg.name)
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
report.setStatus('packing', pkg.name)
|
|
96
|
-
await pack(pkg)
|
|
97
|
-
|
|
98
|
-
// --pack <dir>: pack only, skip delivery.
|
|
99
|
-
if (flags.pack) {
|
|
100
|
-
report.setStatus('packed', pkg.name)
|
|
101
|
-
return
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
report.setStatus('publishing', pkg.name)
|
|
105
|
-
await publish(pkg)
|
|
106
|
-
report.setStatus('success', pkg.name)
|
|
87
|
+
if (!pkg.releaseType) { pkg.skipped = true; return report.setStatus('skipped', pkg.name) }
|
|
88
|
+
if (flags.build !== false) { report.setStatus('building', pkg.name); await build(pkg) }
|
|
89
|
+
if (flags.test !== false) { report.setStatus('testing', pkg.name); await test(pkg) }
|
|
90
|
+
if (flags.dryRun || flags.publish === false) return report.setStatus('success', pkg.name)
|
|
91
|
+
|
|
92
|
+
report.setStatus('packing', pkg.name); await pack(pkg)
|
|
93
|
+
if (flags.pack) return report.setStatus('packed', pkg.name)
|
|
94
|
+
|
|
95
|
+
report.setStatus('publishing', pkg.name); await publish(pkg)
|
|
96
|
+
report.setStatus('success', pkg.name)
|
|
107
97
|
})
|
|
108
98
|
} catch (e) {
|
|
109
99
|
report.error(e, e.stack).set('error', e).setStatus('failure')
|
|
@@ -112,23 +102,18 @@ export const run = async ({cwd = process.cwd(), env, flags = {}} = {}) => within
|
|
|
112
102
|
await clean(ctx)
|
|
113
103
|
}
|
|
114
104
|
report.setStatus('success').log('Great success!')
|
|
115
|
-
}
|
|
105
|
+
}
|
|
116
106
|
|
|
117
|
-
export const createContext = async ({flags, env
|
|
107
|
+
export const createContext = async ({flags, env, cwd}) => {
|
|
118
108
|
const {packages, queue, root, prev, graphs} = await topo({cwd, flags})
|
|
119
109
|
const report = createReport({packages, queue, flags})
|
|
120
|
-
const env = {...process.env, ..._env}
|
|
121
|
-
|
|
122
|
-
log.secret(env.GH_TOKEN, env.GITHUB_TOKEN, env.NPM_TOKEN)
|
|
123
110
|
|
|
124
111
|
$.report = report
|
|
125
112
|
$.env = env
|
|
126
113
|
$.verbose = !!(flags.debug || env.DEBUG) || $.verbose
|
|
127
114
|
$.quiet = !$.verbose
|
|
115
|
+
$.memo = new Map()
|
|
128
116
|
|
|
129
|
-
return {
|
|
130
|
-
|
|
131
|
-
channels,
|
|
132
|
-
run: queuefy(exec, flags.concurrency || os.cpus().length),
|
|
133
|
-
}
|
|
117
|
+
return {cwd, env, flags, root, packages, queue, prev, graphs, report, channels,
|
|
118
|
+
run: queuefy(exec, flags.concurrency || os.cpus().length)}
|
|
134
119
|
}
|