zx-bulk-release 1.26.1 → 2.0.0
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 +13 -0
- package/README.md +3 -1
- package/package.json +7 -6
- package/src/main/js/analyze.js +1 -1
- package/src/main/js/build.js +6 -4
- package/src/main/js/index.js +1 -62
- package/src/main/js/log.js +9 -0
- package/src/main/js/npm.js +1 -1
- package/src/main/js/processor.js +81 -0
- package/src/main/js/publish.js +8 -6
- package/src/main/js/repo.js +36 -24
- package/src/main/js/state.js +56 -0
- package/src/main/js/tag.js +1 -1
- package/src/main/js/topo.js +15 -1
- package/src/main/js/util.js +10 -66
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## [2.0.0](https://github.com/semrel-extra/zx-bulk-release/compare/v1.26.2...v2.0.0) (2023-03-21)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
* feat: replace sequent flow with concurrent ([ec35d7e](https://github.com/semrel-extra/zx-bulk-release/commit/ec35d7e337e64369f0423b71008345177f3ac949))
|
|
5
|
+
|
|
6
|
+
### BREAKING CHANGES
|
|
7
|
+
* concurrent flow might cause throttling issues ([ec35d7e](https://github.com/semrel-extra/zx-bulk-release/commit/ec35d7e337e64369f0423b71008345177f3ac949))
|
|
8
|
+
|
|
9
|
+
## [1.26.2](https://github.com/semrel-extra/zx-bulk-release/compare/v1.26.1...v1.26.2) (2023-03-21)
|
|
10
|
+
|
|
11
|
+
### Fixes & improvements
|
|
12
|
+
* refactor: separate processor layer ([dae6b96](https://github.com/semrel-extra/zx-bulk-release/commit/dae6b9682cd7d283e4f776c69f30c5f50fe9fa41))
|
|
13
|
+
|
|
1
14
|
## [1.26.1](https://github.com/semrel-extra/zx-bulk-release/compare/v1.26.0...v1.26.1) (2023-02-08)
|
|
2
15
|
|
|
3
16
|
### Fixes & improvements
|
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": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "zx-based alternative for multi-semantic-release",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -21,14 +21,15 @@
|
|
|
21
21
|
"docs": "mkdir -p docs && cp ./README.md ./docs/README.md"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@semrel-extra/topo": "^1.
|
|
25
|
-
"cosmiconfig": "^8.
|
|
26
|
-
"
|
|
24
|
+
"@semrel-extra/topo": "^1.6.0",
|
|
25
|
+
"cosmiconfig": "^8.1.3",
|
|
26
|
+
"queuefy": "^1.2.1",
|
|
27
|
+
"zx-extra": "^2.5.4"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"c8": "^7.
|
|
30
|
+
"c8": "^7.13.0",
|
|
30
31
|
"uvu": "^0.5.6",
|
|
31
|
-
"verdaccio": "^5.
|
|
32
|
+
"verdaccio": "^5.22.1"
|
|
32
33
|
},
|
|
33
34
|
"publishConfig": {
|
|
34
35
|
"access": "public"
|
package/src/main/js/analyze.js
CHANGED
|
@@ -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 './
|
|
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)
|
package/src/main/js/build.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import {traverseDeps} from './deps.js'
|
|
2
2
|
import {fetchPkg} from './npm.js'
|
|
3
|
-
import {
|
|
3
|
+
import {runCmd} from './processor.js'
|
|
4
4
|
|
|
5
|
-
export const build = async (pkg, packages) => {
|
|
5
|
+
export const build = async (pkg, packages, run = runCmd) => {
|
|
6
6
|
if (pkg.built) return true
|
|
7
7
|
|
|
8
8
|
await traverseDeps(pkg, packages, async (_, {pkg}) => build(pkg, packages))
|
|
9
9
|
|
|
10
10
|
const {config} = pkg
|
|
11
11
|
|
|
12
|
-
if (pkg.changes.length === 0 && config.npmFetch)
|
|
12
|
+
if (pkg.changes.length === 0 && config.npmFetch) {
|
|
13
|
+
await fetchPkg(pkg)
|
|
14
|
+
}
|
|
13
15
|
|
|
14
16
|
if (!pkg.fetched && config.buildCmd) {
|
|
15
|
-
await
|
|
17
|
+
await run(pkg, 'buildCmd')
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
pkg.built = true
|
package/src/main/js/index.js
CHANGED
|
@@ -1,62 +1 @@
|
|
|
1
|
-
|
|
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'
|
package/src/main/js/npm.js
CHANGED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import os from 'node:os'
|
|
2
|
+
import {$, fs, within} from 'zx-extra'
|
|
3
|
+
import {log} from './log.js'
|
|
4
|
+
import {topo, traverse} 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
|
+
import {queuefy} from 'queuefy'
|
|
12
|
+
|
|
13
|
+
export const run = async ({cwd = process.cwd(), env, flags = {}, concurrency = os.cpus().length} = {}) => within(async () => {
|
|
14
|
+
const state = createState({file: flags.report})
|
|
15
|
+
const _runCmd = queuefy(runCmd, concurrency)
|
|
16
|
+
|
|
17
|
+
$.state = state
|
|
18
|
+
$.env = {...process.env, ...env}
|
|
19
|
+
$.verbose = !!(flags.debug || $.env.DEBUG ) || $.verbose
|
|
20
|
+
|
|
21
|
+
log()('zx-bulk-release')
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const {packages, queue, root, sources, next, prev, nodes} = await topo({cwd, flags})
|
|
25
|
+
log()('queue:', queue)
|
|
26
|
+
|
|
27
|
+
state.setQueue(queue, packages)
|
|
28
|
+
|
|
29
|
+
await traverse({nodes, prev, async cb(name) {
|
|
30
|
+
state.setStatus('analyzing', name)
|
|
31
|
+
const pkg = packages[name]
|
|
32
|
+
await contextify(pkg, packages, root)
|
|
33
|
+
await analyze(pkg, packages)
|
|
34
|
+
state.set('config', pkg.config, name)
|
|
35
|
+
state.set('version', pkg.version, name)
|
|
36
|
+
state.set('prevVersion', pkg.latest.tag?.version || pkg.manifest.version, name)
|
|
37
|
+
state.set('releaseType', pkg.releaseType, name)
|
|
38
|
+
state.set('tag', pkg.tag, name)
|
|
39
|
+
}})
|
|
40
|
+
|
|
41
|
+
state.setStatus('pending')
|
|
42
|
+
|
|
43
|
+
await traverse({nodes, prev, async cb(name) {
|
|
44
|
+
const pkg = packages[name]
|
|
45
|
+
|
|
46
|
+
if (!pkg.releaseType) {
|
|
47
|
+
state.setStatus('skipped', name)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
state.setStatus('building', name)
|
|
52
|
+
await build(pkg, packages, _runCmd)
|
|
53
|
+
|
|
54
|
+
if (flags.dryRun) {
|
|
55
|
+
state.setStatus('success', name)
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
state.setStatus('publishing', name)
|
|
60
|
+
await publish(pkg, _runCmd)
|
|
61
|
+
|
|
62
|
+
state.setStatus('success', name)
|
|
63
|
+
}})
|
|
64
|
+
} catch (e) {
|
|
65
|
+
log({level: 'error'})(e)
|
|
66
|
+
state.set('error', e)
|
|
67
|
+
state.setStatus('failure')
|
|
68
|
+
throw e
|
|
69
|
+
}
|
|
70
|
+
state.setStatus('success')
|
|
71
|
+
log()('Great success!')
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
export const runCmd = async (pkg, name) => {
|
|
75
|
+
const cmd = tpl(pkg.config[name], {...pkg, ...pkg.context})
|
|
76
|
+
|
|
77
|
+
if (cmd) {
|
|
78
|
+
log({pkg})(`run ${name} '${cmd}'`)
|
|
79
|
+
await $.o({cwd: pkg.absPath, quote: v => v, preferLocal: true})`${cmd}`
|
|
80
|
+
}
|
|
81
|
+
}
|
package/src/main/js/publish.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
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 {
|
|
6
|
+
import {msgJoin} from './util.js'
|
|
7
|
+
import {runCmd} from './processor.js'
|
|
8
|
+
import {log} from './log.js'
|
|
7
9
|
|
|
8
|
-
export const publish = async (pkg) => {
|
|
10
|
+
export const publish = async (pkg, run = runCmd) => {
|
|
9
11
|
await fs.writeJson(pkg.manifestPath, pkg.manifest, {spaces: 2})
|
|
10
12
|
await pushTag(pkg)
|
|
11
13
|
await pushMeta(pkg)
|
|
@@ -13,7 +15,7 @@ export const publish = async (pkg) => {
|
|
|
13
15
|
await npmPublish(pkg)
|
|
14
16
|
await ghRelease(pkg)
|
|
15
17
|
await ghPages(pkg)
|
|
16
|
-
await
|
|
18
|
+
await run(pkg, 'publishCmd')
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
export const pushMeta = async (pkg) => {
|
|
@@ -68,7 +70,7 @@ const pushChangelog = async (pkg) => {
|
|
|
68
70
|
? opts.split(' ')
|
|
69
71
|
: [opts.branch, opts.file, opts.msg]
|
|
70
72
|
const _cwd = await fetch({cwd: pkg.absPath, branch})
|
|
71
|
-
const msg =
|
|
73
|
+
const msg = msgJoin(_msg, pkg, 'chore: update changelog ${{name}}')
|
|
72
74
|
const releaseNotes = await formatReleaseNotes(pkg)
|
|
73
75
|
|
|
74
76
|
await $.o({cwd: _cwd})`echo ${releaseNotes}"\n$(cat ./${file})" > ./${file}`
|
|
@@ -103,7 +105,7 @@ const ghPages = async (pkg) => {
|
|
|
103
105
|
const [branch = 'gh-pages', from = 'docs', to = '.', ..._msg] = typeof opts === 'string'
|
|
104
106
|
? opts.split(' ')
|
|
105
107
|
: [opts.branch, opts.from, opts.to, opts.msg]
|
|
106
|
-
const msg =
|
|
108
|
+
const msg = msgJoin(_msg, pkg, 'docs: update docs ${{name}} ${{version}}')
|
|
107
109
|
|
|
108
110
|
log({pkg})(`publish docs to ${branch}`)
|
|
109
111
|
|
package/src/main/js/repo.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {$, ctx, fs, path, tempy, copy} from 'zx-extra'
|
|
2
2
|
import {parseEnv} from './config.js'
|
|
3
|
-
import {log} from './
|
|
3
|
+
import {log} from './log.js'
|
|
4
|
+
import {keyByValue} from './util.js'
|
|
4
5
|
|
|
5
6
|
const branches = {}
|
|
6
7
|
export const fetch = async ({cwd: _cwd, branch, origin: _origin}) => ctx(async ($) => {
|
|
@@ -25,28 +26,39 @@ export const fetch = async ({cwd: _cwd, branch, origin: _origin}) => ctx(async (
|
|
|
25
26
|
})
|
|
26
27
|
|
|
27
28
|
export const push = async ({cwd, from, to, branch, origin, msg, ignoreFiles, files = []}) => ctx(async ($) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
29
|
+
let retries = 3
|
|
30
|
+
let _cwd
|
|
31
|
+
|
|
32
|
+
while (retries > 0) {
|
|
33
|
+
try {
|
|
34
|
+
const {gitCommitterEmail, gitCommitterName} = parseEnv($.env)
|
|
35
|
+
_cwd = await fetch({cwd, branch, origin})
|
|
36
|
+
|
|
37
|
+
for (let {relpath, contents} of files) {
|
|
38
|
+
const _contents = typeof contents === 'string' ? contents : JSON.stringify(contents, null, 2)
|
|
39
|
+
await fs.outputFile(path.resolve(_cwd, to, relpath), _contents)
|
|
40
|
+
}
|
|
41
|
+
if (from) await copy({baseFrom: cwd, from, baseTo: _cwd, to, ignoreFiles, cwd})
|
|
42
|
+
|
|
43
|
+
$.cwd = _cwd
|
|
44
|
+
|
|
45
|
+
await $`git config user.name ${gitCommitterName}`
|
|
46
|
+
await $`git config user.email ${gitCommitterEmail}`
|
|
47
|
+
await $`git add .`
|
|
48
|
+
try {
|
|
49
|
+
await $`git commit -m ${msg}`
|
|
50
|
+
} catch {
|
|
51
|
+
log({level: 'warn'})(`no changes to commit to ${branch}`)
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return await $.raw`git push origin HEAD:refs/heads/${branch}`
|
|
56
|
+
} catch (e) {
|
|
57
|
+
retries -= 1
|
|
58
|
+
branches[keyByValue(branches, _cwd)] = null
|
|
59
|
+
console.warn('git push failed', 'retries left', retries, e)
|
|
60
|
+
}
|
|
47
61
|
}
|
|
48
|
-
|
|
49
|
-
await $.raw`git push origin HEAD:refs/heads/${branch}`
|
|
50
62
|
})
|
|
51
63
|
|
|
52
64
|
const repos = {}
|
|
@@ -58,8 +70,8 @@ export const parseRepo = async (_cwd) => {
|
|
|
58
70
|
const originUrl = await getOrigin(cwd)
|
|
59
71
|
const [, , repoHost, repoName] = originUrl.replace(':', '/').replace(/\.git/, '').match(/.+(@|\/\/)([^/]+)\/(.+)$/) || []
|
|
60
72
|
const repoPublicUrl = `https://${repoHost}/${repoName}`
|
|
61
|
-
const repoAuthedUrl = ghToken && ghUser && repoHost && repoName
|
|
62
|
-
`https://${ghUser}:${ghToken}@${repoHost}/${repoName}.git`
|
|
73
|
+
const repoAuthedUrl = ghToken && ghUser && repoHost && repoName
|
|
74
|
+
? `https://${ghUser}:${ghToken}@${repoHost}/${repoName}.git`
|
|
63
75
|
: originUrl
|
|
64
76
|
|
|
65
77
|
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
|
+
})
|
package/src/main/js/tag.js
CHANGED
|
@@ -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 './
|
|
6
|
+
import {log} from './log.js'
|
|
7
7
|
|
|
8
8
|
export const pushTag = (pkg) => ctx(async ($) => {
|
|
9
9
|
const {absPath: cwd, name, version} = pkg
|
package/src/main/js/topo.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {topo as _topo} from '@semrel-extra/topo'
|
|
2
|
+
import {getPromise} from './util.js'
|
|
2
3
|
|
|
3
4
|
export const topo = async ({flags = {}, cwd} = {}) => {
|
|
4
5
|
const ignore = typeof flags.ignore === 'string'
|
|
@@ -14,4 +15,17 @@ export const topo = async ({flags = {}, cwd} = {}) => {
|
|
|
14
15
|
!ignore.includes(name)
|
|
15
16
|
|
|
16
17
|
return _topo({cwd, filter})
|
|
17
|
-
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const traverse = async ({nodes, prev, cb}) => {
|
|
21
|
+
const waitings = nodes.reduce((acc, node) => {
|
|
22
|
+
acc[node] = getPromise()
|
|
23
|
+
return acc
|
|
24
|
+
}, {})
|
|
25
|
+
|
|
26
|
+
await Promise.all(nodes.map(async (name) => {
|
|
27
|
+
await Promise.all((prev.get(name) || []).map((p) => waitings[p].promise))
|
|
28
|
+
await cb(name)
|
|
29
|
+
waitings[name].resolve(true)
|
|
30
|
+
}))
|
|
31
|
+
}
|
package/src/main/js/util.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import {$, fs} from 'zx-extra'
|
|
2
|
-
|
|
3
1
|
export const tpl = (str, context) =>
|
|
4
2
|
str?.replace(/\$\{\{\s*([.a-z0-9]+)\s*}}/gi, (matched, key) => get(context, key) ?? '')
|
|
5
3
|
|
|
@@ -30,73 +28,19 @@ export const set = (obj, path, value) => {
|
|
|
30
28
|
return result
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
export const
|
|
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
|
-
export const restJoin = (rest, context, def) => tpl(rest.filter(Boolean).join(' ') || def, context)
|
|
31
|
+
export const msgJoin = (rest, context, def) => tpl(rest.filter(Boolean).join(' ') || def, context)
|
|
43
32
|
|
|
44
|
-
export const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
events: [],
|
|
50
|
-
}
|
|
33
|
+
export const getPromise = () => {
|
|
34
|
+
let resolve, reject
|
|
35
|
+
const promise = new Promise((...args) => {
|
|
36
|
+
[resolve, reject] = args
|
|
37
|
+
})
|
|
51
38
|
|
|
52
39
|
return {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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()
|
|
40
|
+
resolve,
|
|
41
|
+
reject,
|
|
42
|
+
promise,
|
|
98
43
|
}
|
|
99
|
-
|
|
100
|
-
return $.r.log(ctx)
|
|
101
44
|
}
|
|
102
45
|
|
|
46
|
+
export const keyByValue = (obj, value) => Object.keys(obj).find((key) => obj[key] === value)
|