@catladder/cli 0.0.0-next-dccc0a36 → 0.0.0-next-78f04d3f
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/dist/apps/cli/src/catci.js +23 -0
- package/dist/apps/cli/src/catci.js.map +1 -1
- package/dist/apps/cli/src/release/githubQueuedRelease.d.ts +14 -0
- package/dist/apps/cli/src/release/githubQueuedRelease.js +152 -0
- package/dist/apps/cli/src/release/githubQueuedRelease.js.map +1 -0
- package/dist/bundles/catci/index.js +3 -3
- package/dist/bundles/catenv/index.js +272 -69
- package/dist/bundles/cli/index.js +272 -69
- package/dist/bundles/skills/catladder-releases/SKILL.md +13 -2
- package/dist/packages/pipeline/src/backends/github/GithubBackend.js +7 -0
- package/dist/packages/pipeline/src/backends/github/GithubBackend.js.map +1 -1
- package/dist/packages/pipeline/src/backends/github/githubReleaseJobs.d.ts +18 -2
- package/dist/packages/pipeline/src/backends/github/githubReleaseJobs.js +92 -10
- package/dist/packages/pipeline/src/backends/github/githubReleaseJobs.js.map +1 -1
- package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js +31 -5
- package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
- package/dist/packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.d.ts +285 -3
- package/dist/packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.js +142 -54
- package/dist/packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.js.map +1 -1
- package/dist/packages/pipeline/src/types/github-types.d.ts +1 -0
- package/dist/packages/pipeline/src/types/release.d.ts +7 -1
- package/dist/skills/catladder-releases/SKILL.md +13 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/catci.ts +30 -0
- package/src/release/githubQueuedRelease.ts +173 -0
|
@@ -1,90 +1,178 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getGitlabReleaseJobs = void 0;
|
|
3
|
+
exports.getGitlabReleaseJobs = exports.RELEASE_EXECUTOR_JOB_NAME = exports.RELEASE_BUTTON_JOB_NAME = void 0;
|
|
4
4
|
const rules_1 = require("../../rules");
|
|
5
5
|
const release_1 = require("../../release");
|
|
6
6
|
const EXPIRED_TOKEN_HELP = "echo '👉 If this job failed with access denied, the project access token might be invald - run `project-renew-token` in catladder CLI to fix.'";
|
|
7
|
+
/**
|
|
8
|
+
* gitlab rejects jobs with more than 50 `needs:` entries (default
|
|
9
|
+
* limit). Pipelines beyond that fall back to the legacy manual release
|
|
10
|
+
* job, which is only playable once all prior stages finished.
|
|
11
|
+
*/
|
|
12
|
+
const GITLAB_MAX_NEEDS = 50;
|
|
13
|
+
exports.RELEASE_BUTTON_JOB_NAME = "create release";
|
|
14
|
+
exports.RELEASE_EXECUTOR_JOB_NAME = "🚀 release once pipeline succeeds";
|
|
7
15
|
const baseReleaseRules = [
|
|
8
16
|
rules_1.RULE_NEVER_ON_RELEASE_COMMIT,
|
|
9
17
|
rules_1.RULE_NEVER_ON_AGENT_TRIGGER,
|
|
10
18
|
rules_1.RULE_NEVER_ON_SCHEDULE,
|
|
11
19
|
];
|
|
12
|
-
|
|
20
|
+
// NOTE: with `rules:`, when: manual defaults to allow_failure: false,
|
|
21
|
+
// which turns every unclicked pipeline into status "blocked" — the
|
|
22
|
+
// manual release jobs therefore carry allow_failure: true so pipelines
|
|
23
|
+
// end "passed" when nobody releases
|
|
24
|
+
const manualReleaseRules = [
|
|
25
|
+
...baseReleaseRules,
|
|
26
|
+
{
|
|
27
|
+
if: rules_1.RULE_CONDITION_MAIN_BRANCH,
|
|
28
|
+
when: "manual",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
if: rules_1.RULE_CONDITION_HOTFIX_BRANCH,
|
|
32
|
+
when: "manual",
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
const getGitlabReleaseJobs = (config, images,
|
|
36
|
+
/**
|
|
37
|
+
* names of the jobs that run automatically in main-branch pipelines
|
|
38
|
+
* (manual jobs excluded: a needed-but-unplayed manual job would make
|
|
39
|
+
* gitlab skip the release executor)
|
|
40
|
+
*/
|
|
41
|
+
mainBranchJobNames) => {
|
|
13
42
|
var _a;
|
|
14
43
|
const method = (0, release_1.getReleaseMethod)(config);
|
|
15
44
|
// NOTE: only the resolved image url is used, not the `need`: release
|
|
16
|
-
// jobs have no `needs` on purpose —
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
// longer wait for the build/deploy stages.
|
|
45
|
+
// jobs have no `needs` on the whole pipeline on purpose — where they
|
|
46
|
+
// must wait for it, the wait is expressed by enumerating the jobs
|
|
47
|
+
// explicitly (see the executor below).
|
|
20
48
|
const releaseImage = images.resolveRef({
|
|
21
49
|
catladderImage: method.image,
|
|
22
50
|
}).image;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
...baseReleaseRules,
|
|
31
|
-
{
|
|
32
|
-
if: rules_1.RULE_CONDITION_MAIN_BRANCH,
|
|
33
|
-
when: ((_a = config.releases) === null || _a === void 0 ? void 0 : _a.when) === "auto" ? "on_success" : "manual",
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
if: rules_1.RULE_CONDITION_HOTFIX_BRANCH,
|
|
37
|
-
when: "manual",
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
},
|
|
51
|
+
const releaseJobBase = {
|
|
52
|
+
stage: "release",
|
|
53
|
+
image: releaseImage,
|
|
54
|
+
script: [method.script],
|
|
55
|
+
after_script: [EXPIRED_TOKEN_HELP],
|
|
56
|
+
};
|
|
57
|
+
const forceReleaseJob = {
|
|
41
58
|
["⚠️ force create release"]: {
|
|
42
|
-
|
|
43
|
-
image: releaseImage,
|
|
44
|
-
script: [method.script],
|
|
45
|
-
after_script: [EXPIRED_TOKEN_HELP],
|
|
59
|
+
...releaseJobBase,
|
|
46
60
|
needs: [],
|
|
61
|
+
allow_failure: true,
|
|
47
62
|
// force semantics of the method's script (e.g. changesets:
|
|
48
63
|
// release a patch bump even without pending changesets)
|
|
49
64
|
...(method.forceReleaseVariables
|
|
50
65
|
? { variables: method.forceReleaseVariables }
|
|
51
66
|
: {}),
|
|
67
|
+
rules: manualReleaseRules,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
// informational MR check of the release method (e.g. the changeset
|
|
71
|
+
// check): warns via allow_failure, the report lands in the MR
|
|
72
|
+
// widget as an exposed artifact
|
|
73
|
+
const checkJob = method.checkScript
|
|
74
|
+
? {
|
|
75
|
+
["🦋 changeset check"]: {
|
|
76
|
+
stage: "test",
|
|
77
|
+
image: releaseImage,
|
|
78
|
+
script: [method.checkScript],
|
|
79
|
+
allow_failure: true,
|
|
80
|
+
artifacts: {
|
|
81
|
+
paths: ["changeset-report.md"],
|
|
82
|
+
expose_as: "changeset report",
|
|
83
|
+
// the report must survive the warning exit
|
|
84
|
+
when: "always",
|
|
85
|
+
},
|
|
86
|
+
rules: [
|
|
87
|
+
rules_1.RULE_NEVER_ON_AGENT_TRIGGER,
|
|
88
|
+
rules_1.RULE_NEVER_ON_SCHEDULE,
|
|
89
|
+
rules_1.RULE_IS_MERGE_REQUEST,
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
: {};
|
|
94
|
+
if (((_a = config.releases) === null || _a === void 0 ? void 0 : _a.when) === "auto") {
|
|
95
|
+
return {
|
|
96
|
+
[exports.RELEASE_BUTTON_JOB_NAME]: {
|
|
97
|
+
...releaseJobBase,
|
|
98
|
+
rules: [
|
|
99
|
+
...baseReleaseRules,
|
|
100
|
+
{
|
|
101
|
+
if: rules_1.RULE_CONDITION_MAIN_BRANCH,
|
|
102
|
+
when: "on_success",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
if: rules_1.RULE_CONDITION_HOTFIX_BRANCH,
|
|
106
|
+
when: "manual",
|
|
107
|
+
// per-rule: only the unclicked hotfix button must not
|
|
108
|
+
// block — a failed automatic release stays loud
|
|
109
|
+
allow_failure: true,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
...forceReleaseJob,
|
|
114
|
+
...checkJob,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const executorNeeds = [
|
|
118
|
+
{ job: exports.RELEASE_BUTTON_JOB_NAME },
|
|
119
|
+
// optional: hotfix pipelines (and rules-filtered jobs) contain a
|
|
120
|
+
// different job subset
|
|
121
|
+
...mainBranchJobNames.map((name) => ({ job: name, optional: true })),
|
|
122
|
+
];
|
|
123
|
+
if (executorNeeds.length > GITLAB_MAX_NEEDS) {
|
|
124
|
+
console.warn(`⚠️ the main-branch pipeline has more than ${GITLAB_MAX_NEEDS} jobs — ` +
|
|
125
|
+
`the "${exports.RELEASE_BUTTON_JOB_NAME}" job falls back to being playable ` +
|
|
126
|
+
`only once the pipeline finished (gitlab caps needs: at ${GITLAB_MAX_NEEDS})`);
|
|
127
|
+
return {
|
|
128
|
+
[exports.RELEASE_BUTTON_JOB_NAME]: {
|
|
129
|
+
...releaseJobBase,
|
|
130
|
+
allow_failure: true,
|
|
131
|
+
rules: manualReleaseRules,
|
|
132
|
+
},
|
|
133
|
+
...forceReleaseJob,
|
|
134
|
+
...checkJob,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
// the queue button: playable from the first second of the pipeline.
|
|
139
|
+
// It only records the intent to release — the executor below does
|
|
140
|
+
// the actual work once every other job succeeded. Clicking after the
|
|
141
|
+
// pipeline finished works the same (the executor starts right away).
|
|
142
|
+
[exports.RELEASE_BUTTON_JOB_NAME]: {
|
|
143
|
+
stage: "release",
|
|
144
|
+
image: releaseImage,
|
|
145
|
+
script: [
|
|
146
|
+
`echo "release queued — '${exports.RELEASE_EXECUTOR_JOB_NAME}' runs it as soon as every other job in this pipeline succeeded"`,
|
|
147
|
+
],
|
|
148
|
+
needs: [],
|
|
149
|
+
// allow_failure keeps the unclicked button from blocking the
|
|
150
|
+
// pipeline AND makes the executor's needs treat it as optional
|
|
151
|
+
// (skipped executor instead of a forever-waiting pipeline)
|
|
152
|
+
allow_failure: true,
|
|
153
|
+
rules: manualReleaseRules,
|
|
154
|
+
},
|
|
155
|
+
// the executor: never played manually. Skipped when the button was
|
|
156
|
+
// not clicked; otherwise starts automatically as soon as the button
|
|
157
|
+
// and every other (non-manual) job of the pipeline succeeded, and
|
|
158
|
+
// is skipped when any of them failed.
|
|
159
|
+
[exports.RELEASE_EXECUTOR_JOB_NAME]: {
|
|
160
|
+
...releaseJobBase,
|
|
161
|
+
needs: executorNeeds,
|
|
52
162
|
rules: [
|
|
53
163
|
...baseReleaseRules,
|
|
54
164
|
{
|
|
55
165
|
if: rules_1.RULE_CONDITION_MAIN_BRANCH,
|
|
56
|
-
when: "
|
|
166
|
+
when: "on_success",
|
|
57
167
|
},
|
|
58
168
|
{
|
|
59
169
|
if: rules_1.RULE_CONDITION_HOTFIX_BRANCH,
|
|
60
|
-
when: "
|
|
170
|
+
when: "on_success",
|
|
61
171
|
},
|
|
62
172
|
],
|
|
63
173
|
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// widget as an exposed artifact
|
|
67
|
-
...(method.checkScript
|
|
68
|
-
? {
|
|
69
|
-
["🦋 changeset check"]: {
|
|
70
|
-
stage: "test",
|
|
71
|
-
image: releaseImage,
|
|
72
|
-
script: [method.checkScript],
|
|
73
|
-
allow_failure: true,
|
|
74
|
-
artifacts: {
|
|
75
|
-
paths: ["changeset-report.md"],
|
|
76
|
-
expose_as: "changeset report",
|
|
77
|
-
// the report must survive the warning exit
|
|
78
|
-
when: "always",
|
|
79
|
-
},
|
|
80
|
-
rules: [
|
|
81
|
-
rules_1.RULE_NEVER_ON_AGENT_TRIGGER,
|
|
82
|
-
rules_1.RULE_NEVER_ON_SCHEDULE,
|
|
83
|
-
rules_1.RULE_IS_MERGE_REQUEST,
|
|
84
|
-
],
|
|
85
|
-
},
|
|
86
|
-
}
|
|
87
|
-
: {}),
|
|
174
|
+
...forceReleaseJob,
|
|
175
|
+
...checkJob,
|
|
88
176
|
};
|
|
89
177
|
};
|
|
90
178
|
exports.getGitlabReleaseJobs = getGitlabReleaseJobs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitlabReleaseJobs.js","sourceRoot":"","sources":["../../../../../../../../packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.ts"],"names":[],"mappings":";;;AAAA,uCAOqB;AAErB,2CAAiD;AAIjD,MAAM,kBAAkB,GACtB,gJAAgJ,CAAC;AAEnJ,MAAM,gBAAgB,GAAG;IACvB,oCAA4B;IAC5B,mCAA2B;IAC3B,8BAAsB;CACvB,CAAC;
|
|
1
|
+
{"version":3,"file":"gitlabReleaseJobs.js","sourceRoot":"","sources":["../../../../../../../../packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,13 @@ export type ReleaseMethod = "semantic-release" | "changesets";
|
|
|
14
14
|
export type ReleaseConfig = {
|
|
15
15
|
/**
|
|
16
16
|
* Whether to release automatically or manually on main branch.
|
|
17
|
-
*
|
|
17
|
+
* - "manual" (default): the pipeline offers a `create release`
|
|
18
|
+
* button that can be clicked at any time — the release then runs
|
|
19
|
+
* automatically as soon as every other job of the pipeline
|
|
20
|
+
* succeeded (clicking after a green pipeline releases right away).
|
|
21
|
+
* A `force create release` button releases immediately, ignoring
|
|
22
|
+
* the pipeline state.
|
|
23
|
+
* - "auto": every main-branch pipeline releases at the end.
|
|
18
24
|
*/
|
|
19
25
|
when?: "manual" | "auto";
|
|
20
26
|
/**
|
|
@@ -23,12 +23,23 @@ are generated, never hand-edited.
|
|
|
23
23
|
## `when` — who triggers the release
|
|
24
24
|
|
|
25
25
|
- **`manual`** (default) — the `create release` job on the main branch
|
|
26
|
-
|
|
26
|
+
can be clicked **at any time**, even while the pipeline is still
|
|
27
|
+
running: it queues the release, which then runs automatically as soon
|
|
28
|
+
as every other job of the pipeline succeeded (and is skipped if the
|
|
29
|
+
pipeline fails). Clicking after a green pipeline releases right away.
|
|
30
|
+
- On GitLab the button is a quick no-op job; the actual release runs
|
|
31
|
+
in the automatic `🚀 release once pipeline succeeds` job (skipped
|
|
32
|
+
when the button was never clicked — never run it by hand).
|
|
33
|
+
- On GitHub the `create-release` dispatch task releases immediately
|
|
34
|
+
when the main workflow for HEAD is green, queues the release when
|
|
35
|
+
it is still running (the `catladder release on green` workflow then
|
|
36
|
+
picks it up on completion), and fails when the run concluded red.
|
|
27
37
|
- **`auto`** — the release job runs automatically on every main-branch
|
|
28
38
|
pipeline (it still no-ops when there is nothing to release).
|
|
29
39
|
|
|
30
40
|
There is always also a manual **`⚠️ force create release`** job as an
|
|
31
|
-
escape hatch
|
|
41
|
+
escape hatch: it releases **immediately**, ignoring the state of the
|
|
42
|
+
pipeline. With `method: "changesets"` it has an extra meaning: it
|
|
32
43
|
releases **even when no changesets are pending** (patch bump with a
|
|
33
44
|
generic changelog entry) — the recovery path when a change was merged
|
|
34
45
|
without a changeset and must ship now.
|