@ebalzan/ci 0.0.0-stage → 3.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/LICENSE +21 -0
- package/README.md +302 -2
- package/bin/_json.mjs +95 -0
- package/bin/_lib.sh +153 -0
- package/bin/cli.mjs +105 -0
- package/bin/gh-bootstrap.sh +622 -0
- package/bin/gh-reset.sh +148 -0
- package/bin/onboard.sh +340 -0
- package/bin/sync-managed.sh +81 -0
- package/config/actions.env +33 -0
- package/config/repo-settings.json +10 -0
- package/config/repos.env +25 -0
- package/config/rulesets/protect-dev.json +10 -0
- package/config/rulesets/protect-main.json +10 -0
- package/config/rulesets/require-pull-request.json +33 -0
- package/config/secrets.env.example +31 -0
- package/docs/ARCHITECTURE.md +477 -0
- package/docs/AUTO_WORK_ITEMS_WORKFLOW.md +305 -0
- package/docs/CI_FLOW.md +205 -0
- package/docs/CLI.md +229 -0
- package/docs/COMMIT_GUIDE.md +133 -0
- package/docs/CONFIGURATION.md +177 -0
- package/docs/GITHUB_ACTIONS_SETUP.md +315 -0
- package/docs/MIGRATION.md +175 -0
- package/docs/ONBOARDING.md +166 -0
- package/docs/REPO_RULES.md +116 -0
- package/managed/scripts/release/validate-conventional-subject.sh +32 -0
- package/package.json +66 -4
- package/renovate/tooling.json +45 -0
- package/templates/.github/actions.env +17 -0
- package/templates/.github/workflows/auto-pr.yml +33 -0
- package/templates/.github/workflows/pr-checks.yml +48 -0
- package/templates/.github/workflows/promote-dev-to-main.yml +26 -0
- package/templates/.github/workflows/release.yml +36 -0
- package/templates/.husky/commit-msg +18 -0
- package/templates/eslint.config.mjs +6 -0
- package/templates/renovate.json +4 -0
package/bin/cli.mjs
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
//
|
|
3
|
+
// ebalzan-ci — the command-line entry point of @ebalzan/ci.
|
|
4
|
+
//
|
|
5
|
+
// Every command except commit-msg, path and version runs one of the bash tools
|
|
6
|
+
// next to this file with the arguments unchanged, so `ebalzan-ci <cmd> --help`
|
|
7
|
+
// prints that tool's own help. Reference: docs/CLI.md.
|
|
8
|
+
|
|
9
|
+
import { spawnSync } from 'node:child_process'
|
|
10
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
11
|
+
import { dirname, join } from 'node:path'
|
|
12
|
+
import process from 'node:process'
|
|
13
|
+
import { fileURLToPath } from 'node:url'
|
|
14
|
+
|
|
15
|
+
const BIN_DIR = dirname(fileURLToPath(import.meta.url))
|
|
16
|
+
const ROOT = dirname(BIN_DIR)
|
|
17
|
+
const VALIDATOR = join(ROOT, 'managed', 'scripts', 'release', 'validate-conventional-subject.sh')
|
|
18
|
+
|
|
19
|
+
const SCRIPTS = {
|
|
20
|
+
bootstrap: 'gh-bootstrap.sh',
|
|
21
|
+
reset: 'gh-reset.sh',
|
|
22
|
+
onboard: 'onboard.sh',
|
|
23
|
+
'sync-managed': 'sync-managed.sh',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Subjects git writes itself; they are not Conventional Commits and need not be.
|
|
27
|
+
const GIT_GENERATED = /^(Merge |Revert "|fixup! |squash! |amend! )/
|
|
28
|
+
|
|
29
|
+
const HELP = `Usage: ebalzan-ci <command> [options]
|
|
30
|
+
|
|
31
|
+
Commands:
|
|
32
|
+
onboard Add the shared workflows, hook and rules to a repo, then bootstrap it
|
|
33
|
+
bootstrap Sync variables, secrets, settings and rulesets onto a repo (or --all)
|
|
34
|
+
reset Delete Actions variables/secrets on a repo (typed confirmation)
|
|
35
|
+
commit-msg Validate a commit message (the husky commit-msg hook calls this)
|
|
36
|
+
sync-managed Refresh local copies of managed files (deprecated)
|
|
37
|
+
path Print the package directory (to source bin/_lib.sh, read config/)
|
|
38
|
+
version Print the package version
|
|
39
|
+
help Show this help
|
|
40
|
+
|
|
41
|
+
Run 'ebalzan-ci <command> --help' for a command's options.
|
|
42
|
+
Docs: https://github.com/ebalzan/ci#readme`
|
|
43
|
+
|
|
44
|
+
function version() {
|
|
45
|
+
return JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8')).version
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// commit-msg FILE|SUBJECT — husky passes the path of the message file; a
|
|
49
|
+
// non-path argument is checked as the subject itself (handy for scripts).
|
|
50
|
+
function commitMsg(args) {
|
|
51
|
+
const [arg] = args
|
|
52
|
+
if (!arg || arg === '--help' || arg === '-h') {
|
|
53
|
+
console.log('Usage: ebalzan-ci commit-msg <message-file | subject>')
|
|
54
|
+
return arg ? 0 : 1
|
|
55
|
+
}
|
|
56
|
+
const text = existsSync(arg) ? readFileSync(arg, 'utf8') : arg
|
|
57
|
+
const subject =
|
|
58
|
+
text
|
|
59
|
+
.split(/\r?\n/)
|
|
60
|
+
.find(line => line.trim() && !line.startsWith('#'))
|
|
61
|
+
?.trim() ?? ''
|
|
62
|
+
if (GIT_GENERATED.test(subject)) return 0
|
|
63
|
+
return run('sh', [VALIDATOR, subject, 'commit message'])
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function run(command, args) {
|
|
67
|
+
const result = spawnSync(command, args, { stdio: 'inherit' })
|
|
68
|
+
if (result.error) {
|
|
69
|
+
console.error(`ebalzan-ci: could not run ${command}: ${result.error.message}`)
|
|
70
|
+
if (command === 'bash' || command === 'sh') {
|
|
71
|
+
console.error('The tools need a POSIX shell (Linux, macOS, WSL or Git Bash on Windows).')
|
|
72
|
+
}
|
|
73
|
+
return 127
|
|
74
|
+
}
|
|
75
|
+
return result.status ?? 1
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function main(argv) {
|
|
79
|
+
const [command, ...args] = argv
|
|
80
|
+
if (Object.hasOwn(SCRIPTS, command ?? ''))
|
|
81
|
+
return run('bash', [join(BIN_DIR, SCRIPTS[command]), ...args])
|
|
82
|
+
switch (command) {
|
|
83
|
+
case 'commit-msg':
|
|
84
|
+
return commitMsg(args)
|
|
85
|
+
case 'path':
|
|
86
|
+
console.log(ROOT)
|
|
87
|
+
return 0
|
|
88
|
+
case 'version':
|
|
89
|
+
case '--version':
|
|
90
|
+
case '-v':
|
|
91
|
+
console.log(version())
|
|
92
|
+
return 0
|
|
93
|
+
case undefined:
|
|
94
|
+
case 'help':
|
|
95
|
+
case '--help':
|
|
96
|
+
case '-h':
|
|
97
|
+
console.log(HELP)
|
|
98
|
+
return command === undefined ? 1 : 0
|
|
99
|
+
default:
|
|
100
|
+
console.error(`ebalzan-ci: unknown command '${command}'.\n\n${HELP}`)
|
|
101
|
+
return 1
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
process.exit(main(process.argv.slice(2)))
|