@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
|
@@ -2463,6 +2463,13 @@ class GithubBackend {
|
|
|
2463
2463
|
manualJobConditions[id] = `inputs.job == '${id}'`;
|
|
2464
2464
|
manualDispatchOptions.push(id);
|
|
2465
2465
|
}
|
|
2466
|
+
// manual release mode: the workflow that runs a queued release
|
|
2467
|
+
// once the main workflow completed green
|
|
2468
|
+
const releaseOnGreen = (0, githubReleaseJobs_1.getGithubReleaseOnGreenWorkflow)(config, images, TRIGGER_WORKFLOWS.mainBranch.name, workflowEnv);
|
|
2469
|
+
if (releaseOnGreen) {
|
|
2470
|
+
workflows[`${GENERATED_FILE_PREFIX}release-on-green.yml`] =
|
|
2471
|
+
releaseOnGreen;
|
|
2472
|
+
}
|
|
2466
2473
|
}
|
|
2467
2474
|
if (Object.keys(jobs).length > 0) {
|
|
2468
2475
|
workflows[`${GENERATED_FILE_PREFIX}${workflowFileName(trigger)}`] = {
|
|
@@ -3007,16 +3014,21 @@ exports.getUploadProviderIds = getUploadProviderIds;
|
|
|
3007
3014
|
"use strict";
|
|
3008
3015
|
|
|
3009
3016
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3010
|
-
exports.getGithubReleaseCheckJobs = exports.getGithubReleaseJobs = void 0;
|
|
3017
|
+
exports.getGithubReleaseCheckJobs = exports.getGithubReleaseOnGreenWorkflow = exports.getGithubReleaseJobs = void 0;
|
|
3011
3018
|
const createGithubJobs_1 = __nccwpck_require__(57877);
|
|
3012
3019
|
const release_1 = __nccwpck_require__(38904);
|
|
3013
|
-
const
|
|
3020
|
+
const shippedCatci_1 = __nccwpck_require__(79024);
|
|
3021
|
+
const CATCI = `${shippedCatci_1.GENERATED_CATCI_FOLDER}/index.js`;
|
|
3022
|
+
const createReleaseJob = (config, images, options = {}) => {
|
|
3023
|
+
var _a;
|
|
3014
3024
|
const method = (0, release_1.getReleaseMethod)(config);
|
|
3015
3025
|
const resolved = images.resolveRef({ catladderImage: method.image });
|
|
3016
|
-
const imageNeeds =
|
|
3026
|
+
const imageNeeds = !options.skipImageNeeds &&
|
|
3027
|
+
resolved.need &&
|
|
3028
|
+
typeof resolved.need === "object"
|
|
3017
3029
|
? [(0, createGithubJobs_1.githubGlobalJobId)(resolved.need.job)]
|
|
3018
3030
|
: [];
|
|
3019
|
-
const allNeeds = [...imageNeeds, ...(needs !== null &&
|
|
3031
|
+
const allNeeds = [...imageNeeds, ...((_a = options.needs) !== null && _a !== void 0 ? _a : [])];
|
|
3020
3032
|
return {
|
|
3021
3033
|
name: "create release",
|
|
3022
3034
|
"runs-on": "ubuntu-latest",
|
|
@@ -3045,7 +3057,7 @@ const createReleaseJob = (config, images, needs, extraEnv) => {
|
|
|
3045
3057
|
...(allNeeds.length > 0 ? { needs: allNeeds } : {}),
|
|
3046
3058
|
env: {
|
|
3047
3059
|
GITHUB_TOKEN: "${{ github.token }}",
|
|
3048
|
-
...extraEnv,
|
|
3060
|
+
...options.extraEnv,
|
|
3049
3061
|
},
|
|
3050
3062
|
steps: [
|
|
3051
3063
|
{
|
|
@@ -3055,8 +3067,21 @@ const createReleaseJob = (config, images, needs, extraEnv) => {
|
|
|
3055
3067
|
// tags since the last release) to determine the version
|
|
3056
3068
|
with: { "fetch-depth": 0 },
|
|
3057
3069
|
},
|
|
3070
|
+
...(options.queueCheck
|
|
3071
|
+
? [
|
|
3072
|
+
{
|
|
3073
|
+
name: "check main workflow",
|
|
3074
|
+
id: "queue",
|
|
3075
|
+
run: `node ${CATCI} release github-queue-check`,
|
|
3076
|
+
shell: "bash",
|
|
3077
|
+
},
|
|
3078
|
+
]
|
|
3079
|
+
: []),
|
|
3058
3080
|
{
|
|
3059
3081
|
name: "create release",
|
|
3082
|
+
...(options.queueCheck
|
|
3083
|
+
? { if: "steps.queue.outputs.queued != 'true'" }
|
|
3084
|
+
: {}),
|
|
3060
3085
|
run: method.script,
|
|
3061
3086
|
shell: "bash",
|
|
3062
3087
|
},
|
|
@@ -3070,7 +3095,10 @@ const createReleaseJob = (config, images, needs, extraEnv) => {
|
|
|
3070
3095
|
* workflow after all other jobs; a force variant goes to the manual
|
|
3071
3096
|
* tasks workflow
|
|
3072
3097
|
* - otherwise (manual, the default): the release job goes to the
|
|
3073
|
-
* manual tasks workflow
|
|
3098
|
+
* manual tasks workflow. Its queue-check step releases right away on
|
|
3099
|
+
* a green main run and otherwise queues the release for the
|
|
3100
|
+
* release-on-green workflow (see getGithubReleaseOnGreenWorkflow) —
|
|
3101
|
+
* the counterpart of gitlab's queue button + executor pair.
|
|
3074
3102
|
*/
|
|
3075
3103
|
const getGithubReleaseJobs = (config, mainWorkflowJobIds, images) => {
|
|
3076
3104
|
var _a;
|
|
@@ -3078,28 +3106,89 @@ const getGithubReleaseJobs = (config, mainWorkflowJobIds, images) => {
|
|
|
3078
3106
|
if (((_a = config.releases) === null || _a === void 0 ? void 0 : _a.when) === "auto") {
|
|
3079
3107
|
return {
|
|
3080
3108
|
main: {
|
|
3081
|
-
"create-release": createReleaseJob(config, images,
|
|
3109
|
+
"create-release": createReleaseJob(config, images, {
|
|
3110
|
+
needs: mainWorkflowJobIds,
|
|
3111
|
+
}),
|
|
3082
3112
|
},
|
|
3083
3113
|
manual: {
|
|
3084
|
-
"force-create-release": createReleaseJob(config, images,
|
|
3114
|
+
"force-create-release": createReleaseJob(config, images, {
|
|
3115
|
+
extraEnv: method.forceReleaseVariables,
|
|
3116
|
+
}),
|
|
3085
3117
|
},
|
|
3086
3118
|
};
|
|
3087
3119
|
}
|
|
3088
3120
|
return {
|
|
3089
3121
|
main: {},
|
|
3090
3122
|
manual: {
|
|
3091
|
-
"create-release": createReleaseJob(config, images),
|
|
3123
|
+
"create-release": createReleaseJob(config, images, { queueCheck: true }),
|
|
3092
3124
|
// an explicit force option wherever the method distinguishes it
|
|
3093
3125
|
// (e.g. changesets: release a patch bump without changesets)
|
|
3094
3126
|
...(method.forceReleaseVariables
|
|
3095
3127
|
? {
|
|
3096
|
-
"force-create-release": createReleaseJob(config, images,
|
|
3128
|
+
"force-create-release": createReleaseJob(config, images, {
|
|
3129
|
+
extraEnv: method.forceReleaseVariables,
|
|
3130
|
+
}),
|
|
3097
3131
|
}
|
|
3098
3132
|
: {}),
|
|
3099
3133
|
},
|
|
3100
3134
|
};
|
|
3101
3135
|
};
|
|
3102
3136
|
exports.getGithubReleaseJobs = getGithubReleaseJobs;
|
|
3137
|
+
/**
|
|
3138
|
+
* the release-on-green workflow (manual release mode only): runs on
|
|
3139
|
+
* every completed main workflow run. A lightweight host job checks the
|
|
3140
|
+
* queue marker (written by the create-release task while the main
|
|
3141
|
+
* workflow was still running) — most runs have nothing queued and end
|
|
3142
|
+
* after that single quick job. When the marker matches the completed
|
|
3143
|
+
* run, the containerized release job creates the release.
|
|
3144
|
+
*
|
|
3145
|
+
* No image-build jobs here: the release image was ensured by the main
|
|
3146
|
+
* workflow run that just completed (same commit, same content-hashed
|
|
3147
|
+
* tag).
|
|
3148
|
+
*/
|
|
3149
|
+
const getGithubReleaseOnGreenWorkflow = (config, images, mainWorkflowName, workflowEnv) => {
|
|
3150
|
+
var _a;
|
|
3151
|
+
if (((_a = config.releases) === null || _a === void 0 ? void 0 : _a.when) === "auto") {
|
|
3152
|
+
return null;
|
|
3153
|
+
}
|
|
3154
|
+
return {
|
|
3155
|
+
name: "catladder release on green",
|
|
3156
|
+
on: {
|
|
3157
|
+
workflow_run: {
|
|
3158
|
+
workflows: [mainWorkflowName],
|
|
3159
|
+
types: ["completed"],
|
|
3160
|
+
},
|
|
3161
|
+
},
|
|
3162
|
+
env: workflowEnv,
|
|
3163
|
+
jobs: {
|
|
3164
|
+
guard: {
|
|
3165
|
+
name: "check queued release",
|
|
3166
|
+
"runs-on": "ubuntu-latest",
|
|
3167
|
+
// consuming the queue marker is a ref deletion
|
|
3168
|
+
permissions: { contents: "write" },
|
|
3169
|
+
env: { GITHUB_TOKEN: "${{ github.token }}" },
|
|
3170
|
+
outputs: { release: "${{ steps.guard.outputs.release }}" },
|
|
3171
|
+
steps: [
|
|
3172
|
+
{ name: "Checkout", uses: "actions/checkout@v4" },
|
|
3173
|
+
{
|
|
3174
|
+
name: "check queued release",
|
|
3175
|
+
id: "guard",
|
|
3176
|
+
run: `node ${CATCI} release github-queued-guard "\${{ github.event.workflow_run.head_sha }}" "\${{ github.event.workflow_run.conclusion }}"`,
|
|
3177
|
+
shell: "bash",
|
|
3178
|
+
},
|
|
3179
|
+
],
|
|
3180
|
+
},
|
|
3181
|
+
"create-release": {
|
|
3182
|
+
...createReleaseJob(config, images, {
|
|
3183
|
+
needs: ["guard"],
|
|
3184
|
+
skipImageNeeds: true,
|
|
3185
|
+
}),
|
|
3186
|
+
if: "${{ needs.guard.outputs.release == 'true' }}",
|
|
3187
|
+
},
|
|
3188
|
+
},
|
|
3189
|
+
};
|
|
3190
|
+
};
|
|
3191
|
+
exports.getGithubReleaseOnGreenWorkflow = getGithubReleaseOnGreenWorkflow;
|
|
3103
3192
|
/**
|
|
3104
3193
|
* the informational MR/PR check job of the release method (e.g. the
|
|
3105
3194
|
* changeset check), added to the mr workflow. continue-on-error keeps
|
|
@@ -3294,6 +3383,7 @@ const config_1 = __nccwpck_require__(17860);
|
|
|
3294
3383
|
const createAllJobs_1 = __nccwpck_require__(54114);
|
|
3295
3384
|
const jobImagesPlan_1 = __nccwpck_require__(47864);
|
|
3296
3385
|
const shippedCatci_1 = __nccwpck_require__(79024);
|
|
3386
|
+
const release_1 = __nccwpck_require__(38904);
|
|
3297
3387
|
const index_1 = __nccwpck_require__(68906);
|
|
3298
3388
|
const createGitlabJobs_1 = __nccwpck_require__(41509);
|
|
3299
3389
|
const createGitlabPipeline_1 = __nccwpck_require__(94411);
|
|
@@ -3380,12 +3470,29 @@ class GitlabBackend {
|
|
|
3380
3470
|
}
|
|
3381
3471
|
async createPipeline(config, images) {
|
|
3382
3472
|
const stages = (0, getPipelineStages_1.getPipelineStages)(config);
|
|
3383
|
-
// release
|
|
3384
|
-
//
|
|
3385
|
-
//
|
|
3386
|
-
|
|
3473
|
+
// register the release image first: the per-trigger job creation
|
|
3474
|
+
// below emits the build jobs of all images registered so far. The
|
|
3475
|
+
// release jobs themselves are created afterwards — they need the
|
|
3476
|
+
// main-branch job list for the queued-release executor's needs.
|
|
3477
|
+
images.resolveRef({ catladderImage: (0, release_1.getReleaseMethod)(config).image });
|
|
3387
3478
|
// for all triggers create jobs and add base rules
|
|
3388
|
-
const
|
|
3479
|
+
const jobsPerTrigger = await Promise.all(config_1.ALL_PIPELINE_TRIGGERS.map(async (trigger) => ({
|
|
3480
|
+
trigger,
|
|
3481
|
+
jobs: await (0, createGitlabJobs_1.createGitlabJobs)(await (0, createAllJobs_1.createAllJobs)({ config, trigger, pipelineType: this.type }), images, getGitlabRulesForTrigger(trigger)),
|
|
3482
|
+
})));
|
|
3483
|
+
const allJobsPerTrigger = jobsPerTrigger.flatMap(({ jobs }) => jobs);
|
|
3484
|
+
// the jobs the queued-release executor waits for: everything that
|
|
3485
|
+
// runs automatically in a main-branch pipeline. Manual jobs (stop,
|
|
3486
|
+
// rollback, gates) are excluded — gitlab skips a job whose needs
|
|
3487
|
+
// include an unplayed manual job.
|
|
3488
|
+
const mainBranchJobNames = [
|
|
3489
|
+
...new Set(jobsPerTrigger
|
|
3490
|
+
.filter(({ trigger }) => trigger === "mainBranch")
|
|
3491
|
+
.flatMap(({ jobs }) => jobs)
|
|
3492
|
+
.filter(({ gitlabJob }) => !isManualGitlabJob(gitlabJob))
|
|
3493
|
+
.map(({ name }) => name)),
|
|
3494
|
+
];
|
|
3495
|
+
const releaseJobs = (0, gitlabReleaseJobs_1.getGitlabReleaseJobs)(config, images, mainBranchJobNames);
|
|
3389
3496
|
const allWorkspaceJobs = allJobsPerTrigger
|
|
3390
3497
|
.filter((j) => { var _a; return ((_a = j.context) === null || _a === void 0 ? void 0 : _a.type) === "workspace"; }) // sort by componentName in the same order as they appear in the config
|
|
3391
3498
|
// this is purely for better readability in git diffs when you add new components
|
|
@@ -3451,6 +3558,14 @@ class GitlabBackend {
|
|
|
3451
3558
|
}
|
|
3452
3559
|
}
|
|
3453
3560
|
exports.GitlabBackend = GitlabBackend;
|
|
3561
|
+
/**
|
|
3562
|
+
* whether a job can end up waiting for a human in a main-branch
|
|
3563
|
+
* pipeline (catladder expresses manual-ness only through rules)
|
|
3564
|
+
*/
|
|
3565
|
+
function isManualGitlabJob(job) {
|
|
3566
|
+
var _a;
|
|
3567
|
+
return ((_a = job.rules) !== null && _a !== void 0 ? _a : []).some((rule) => rule.when === "manual");
|
|
3568
|
+
}
|
|
3454
3569
|
function getGitlabRulesForTrigger(trigger) {
|
|
3455
3570
|
// mainBranch: on push to main branch except it's a release commit
|
|
3456
3571
|
// mr: on merge request
|
|
@@ -3983,91 +4098,179 @@ exports.getPipelineStages = getPipelineStages;
|
|
|
3983
4098
|
"use strict";
|
|
3984
4099
|
|
|
3985
4100
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3986
|
-
exports.getGitlabReleaseJobs = void 0;
|
|
4101
|
+
exports.getGitlabReleaseJobs = exports.RELEASE_EXECUTOR_JOB_NAME = exports.RELEASE_BUTTON_JOB_NAME = void 0;
|
|
3987
4102
|
const rules_1 = __nccwpck_require__(35086);
|
|
3988
4103
|
const release_1 = __nccwpck_require__(38904);
|
|
3989
4104
|
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.'";
|
|
4105
|
+
/**
|
|
4106
|
+
* gitlab rejects jobs with more than 50 `needs:` entries (default
|
|
4107
|
+
* limit). Pipelines beyond that fall back to the legacy manual release
|
|
4108
|
+
* job, which is only playable once all prior stages finished.
|
|
4109
|
+
*/
|
|
4110
|
+
const GITLAB_MAX_NEEDS = 50;
|
|
4111
|
+
exports.RELEASE_BUTTON_JOB_NAME = "create release";
|
|
4112
|
+
exports.RELEASE_EXECUTOR_JOB_NAME = "🚀 release once pipeline succeeds";
|
|
3990
4113
|
const baseReleaseRules = [
|
|
3991
4114
|
rules_1.RULE_NEVER_ON_RELEASE_COMMIT,
|
|
3992
4115
|
rules_1.RULE_NEVER_ON_AGENT_TRIGGER,
|
|
3993
4116
|
rules_1.RULE_NEVER_ON_SCHEDULE,
|
|
3994
4117
|
];
|
|
3995
|
-
|
|
4118
|
+
// NOTE: with `rules:`, when: manual defaults to allow_failure: false,
|
|
4119
|
+
// which turns every unclicked pipeline into status "blocked" — the
|
|
4120
|
+
// manual release jobs therefore carry allow_failure: true so pipelines
|
|
4121
|
+
// end "passed" when nobody releases
|
|
4122
|
+
const manualReleaseRules = [
|
|
4123
|
+
...baseReleaseRules,
|
|
4124
|
+
{
|
|
4125
|
+
if: rules_1.RULE_CONDITION_MAIN_BRANCH,
|
|
4126
|
+
when: "manual",
|
|
4127
|
+
},
|
|
4128
|
+
{
|
|
4129
|
+
if: rules_1.RULE_CONDITION_HOTFIX_BRANCH,
|
|
4130
|
+
when: "manual",
|
|
4131
|
+
},
|
|
4132
|
+
];
|
|
4133
|
+
const getGitlabReleaseJobs = (config, images,
|
|
4134
|
+
/**
|
|
4135
|
+
* names of the jobs that run automatically in main-branch pipelines
|
|
4136
|
+
* (manual jobs excluded: a needed-but-unplayed manual job would make
|
|
4137
|
+
* gitlab skip the release executor)
|
|
4138
|
+
*/
|
|
4139
|
+
mainBranchJobNames) => {
|
|
3996
4140
|
var _a;
|
|
3997
4141
|
const method = (0, release_1.getReleaseMethod)(config);
|
|
3998
4142
|
// NOTE: only the resolved image url is used, not the `need`: release
|
|
3999
|
-
// jobs have no `needs` on purpose —
|
|
4000
|
-
//
|
|
4001
|
-
//
|
|
4002
|
-
// longer wait for the build/deploy stages.
|
|
4143
|
+
// jobs have no `needs` on the whole pipeline on purpose — where they
|
|
4144
|
+
// must wait for it, the wait is expressed by enumerating the jobs
|
|
4145
|
+
// explicitly (see the executor below).
|
|
4003
4146
|
const releaseImage = images.resolveRef({
|
|
4004
4147
|
catladderImage: method.image,
|
|
4005
4148
|
}).image;
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
...baseReleaseRules,
|
|
4014
|
-
{
|
|
4015
|
-
if: rules_1.RULE_CONDITION_MAIN_BRANCH,
|
|
4016
|
-
when: ((_a = config.releases) === null || _a === void 0 ? void 0 : _a.when) === "auto" ? "on_success" : "manual",
|
|
4017
|
-
},
|
|
4018
|
-
{
|
|
4019
|
-
if: rules_1.RULE_CONDITION_HOTFIX_BRANCH,
|
|
4020
|
-
when: "manual",
|
|
4021
|
-
},
|
|
4022
|
-
],
|
|
4023
|
-
},
|
|
4149
|
+
const releaseJobBase = {
|
|
4150
|
+
stage: "release",
|
|
4151
|
+
image: releaseImage,
|
|
4152
|
+
script: [method.script],
|
|
4153
|
+
after_script: [EXPIRED_TOKEN_HELP],
|
|
4154
|
+
};
|
|
4155
|
+
const forceReleaseJob = {
|
|
4024
4156
|
["⚠️ force create release"]: {
|
|
4025
|
-
|
|
4026
|
-
image: releaseImage,
|
|
4027
|
-
script: [method.script],
|
|
4028
|
-
after_script: [EXPIRED_TOKEN_HELP],
|
|
4157
|
+
...releaseJobBase,
|
|
4029
4158
|
needs: [],
|
|
4159
|
+
allow_failure: true,
|
|
4030
4160
|
// force semantics of the method's script (e.g. changesets:
|
|
4031
4161
|
// release a patch bump even without pending changesets)
|
|
4032
4162
|
...(method.forceReleaseVariables
|
|
4033
4163
|
? { variables: method.forceReleaseVariables }
|
|
4034
4164
|
: {}),
|
|
4165
|
+
rules: manualReleaseRules,
|
|
4166
|
+
},
|
|
4167
|
+
};
|
|
4168
|
+
// informational MR check of the release method (e.g. the changeset
|
|
4169
|
+
// check): warns via allow_failure, the report lands in the MR
|
|
4170
|
+
// widget as an exposed artifact
|
|
4171
|
+
const checkJob = method.checkScript
|
|
4172
|
+
? {
|
|
4173
|
+
["🦋 changeset check"]: {
|
|
4174
|
+
stage: "test",
|
|
4175
|
+
image: releaseImage,
|
|
4176
|
+
script: [method.checkScript],
|
|
4177
|
+
allow_failure: true,
|
|
4178
|
+
artifacts: {
|
|
4179
|
+
paths: ["changeset-report.md"],
|
|
4180
|
+
expose_as: "changeset report",
|
|
4181
|
+
// the report must survive the warning exit
|
|
4182
|
+
when: "always",
|
|
4183
|
+
},
|
|
4184
|
+
rules: [
|
|
4185
|
+
rules_1.RULE_NEVER_ON_AGENT_TRIGGER,
|
|
4186
|
+
rules_1.RULE_NEVER_ON_SCHEDULE,
|
|
4187
|
+
rules_1.RULE_IS_MERGE_REQUEST,
|
|
4188
|
+
],
|
|
4189
|
+
},
|
|
4190
|
+
}
|
|
4191
|
+
: {};
|
|
4192
|
+
if (((_a = config.releases) === null || _a === void 0 ? void 0 : _a.when) === "auto") {
|
|
4193
|
+
return {
|
|
4194
|
+
[exports.RELEASE_BUTTON_JOB_NAME]: {
|
|
4195
|
+
...releaseJobBase,
|
|
4196
|
+
rules: [
|
|
4197
|
+
...baseReleaseRules,
|
|
4198
|
+
{
|
|
4199
|
+
if: rules_1.RULE_CONDITION_MAIN_BRANCH,
|
|
4200
|
+
when: "on_success",
|
|
4201
|
+
},
|
|
4202
|
+
{
|
|
4203
|
+
if: rules_1.RULE_CONDITION_HOTFIX_BRANCH,
|
|
4204
|
+
when: "manual",
|
|
4205
|
+
// per-rule: only the unclicked hotfix button must not
|
|
4206
|
+
// block — a failed automatic release stays loud
|
|
4207
|
+
allow_failure: true,
|
|
4208
|
+
},
|
|
4209
|
+
],
|
|
4210
|
+
},
|
|
4211
|
+
...forceReleaseJob,
|
|
4212
|
+
...checkJob,
|
|
4213
|
+
};
|
|
4214
|
+
}
|
|
4215
|
+
const executorNeeds = [
|
|
4216
|
+
{ job: exports.RELEASE_BUTTON_JOB_NAME },
|
|
4217
|
+
// optional: hotfix pipelines (and rules-filtered jobs) contain a
|
|
4218
|
+
// different job subset
|
|
4219
|
+
...mainBranchJobNames.map((name) => ({ job: name, optional: true })),
|
|
4220
|
+
];
|
|
4221
|
+
if (executorNeeds.length > GITLAB_MAX_NEEDS) {
|
|
4222
|
+
console.warn(`⚠️ the main-branch pipeline has more than ${GITLAB_MAX_NEEDS} jobs — ` +
|
|
4223
|
+
`the "${exports.RELEASE_BUTTON_JOB_NAME}" job falls back to being playable ` +
|
|
4224
|
+
`only once the pipeline finished (gitlab caps needs: at ${GITLAB_MAX_NEEDS})`);
|
|
4225
|
+
return {
|
|
4226
|
+
[exports.RELEASE_BUTTON_JOB_NAME]: {
|
|
4227
|
+
...releaseJobBase,
|
|
4228
|
+
allow_failure: true,
|
|
4229
|
+
rules: manualReleaseRules,
|
|
4230
|
+
},
|
|
4231
|
+
...forceReleaseJob,
|
|
4232
|
+
...checkJob,
|
|
4233
|
+
};
|
|
4234
|
+
}
|
|
4235
|
+
return {
|
|
4236
|
+
// the queue button: playable from the first second of the pipeline.
|
|
4237
|
+
// It only records the intent to release — the executor below does
|
|
4238
|
+
// the actual work once every other job succeeded. Clicking after the
|
|
4239
|
+
// pipeline finished works the same (the executor starts right away).
|
|
4240
|
+
[exports.RELEASE_BUTTON_JOB_NAME]: {
|
|
4241
|
+
stage: "release",
|
|
4242
|
+
image: releaseImage,
|
|
4243
|
+
script: [
|
|
4244
|
+
`echo "release queued — '${exports.RELEASE_EXECUTOR_JOB_NAME}' runs it as soon as every other job in this pipeline succeeded"`,
|
|
4245
|
+
],
|
|
4246
|
+
needs: [],
|
|
4247
|
+
// allow_failure keeps the unclicked button from blocking the
|
|
4248
|
+
// pipeline AND makes the executor's needs treat it as optional
|
|
4249
|
+
// (skipped executor instead of a forever-waiting pipeline)
|
|
4250
|
+
allow_failure: true,
|
|
4251
|
+
rules: manualReleaseRules,
|
|
4252
|
+
},
|
|
4253
|
+
// the executor: never played manually. Skipped when the button was
|
|
4254
|
+
// not clicked; otherwise starts automatically as soon as the button
|
|
4255
|
+
// and every other (non-manual) job of the pipeline succeeded, and
|
|
4256
|
+
// is skipped when any of them failed.
|
|
4257
|
+
[exports.RELEASE_EXECUTOR_JOB_NAME]: {
|
|
4258
|
+
...releaseJobBase,
|
|
4259
|
+
needs: executorNeeds,
|
|
4035
4260
|
rules: [
|
|
4036
4261
|
...baseReleaseRules,
|
|
4037
4262
|
{
|
|
4038
4263
|
if: rules_1.RULE_CONDITION_MAIN_BRANCH,
|
|
4039
|
-
when: "
|
|
4264
|
+
when: "on_success",
|
|
4040
4265
|
},
|
|
4041
4266
|
{
|
|
4042
4267
|
if: rules_1.RULE_CONDITION_HOTFIX_BRANCH,
|
|
4043
|
-
when: "
|
|
4268
|
+
when: "on_success",
|
|
4044
4269
|
},
|
|
4045
4270
|
],
|
|
4046
4271
|
},
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
// widget as an exposed artifact
|
|
4050
|
-
...(method.checkScript
|
|
4051
|
-
? {
|
|
4052
|
-
["🦋 changeset check"]: {
|
|
4053
|
-
stage: "test",
|
|
4054
|
-
image: releaseImage,
|
|
4055
|
-
script: [method.checkScript],
|
|
4056
|
-
allow_failure: true,
|
|
4057
|
-
artifacts: {
|
|
4058
|
-
paths: ["changeset-report.md"],
|
|
4059
|
-
expose_as: "changeset report",
|
|
4060
|
-
// the report must survive the warning exit
|
|
4061
|
-
when: "always",
|
|
4062
|
-
},
|
|
4063
|
-
rules: [
|
|
4064
|
-
rules_1.RULE_NEVER_ON_AGENT_TRIGGER,
|
|
4065
|
-
rules_1.RULE_NEVER_ON_SCHEDULE,
|
|
4066
|
-
rules_1.RULE_IS_MERGE_REQUEST,
|
|
4067
|
-
],
|
|
4068
|
-
},
|
|
4069
|
-
}
|
|
4070
|
-
: {}),
|
|
4272
|
+
...forceReleaseJob,
|
|
4273
|
+
...checkJob,
|
|
4071
4274
|
};
|
|
4072
4275
|
};
|
|
4073
4276
|
exports.getGitlabReleaseJobs = getGitlabReleaseJobs;
|