@catladder/cli 0.0.0-main-bd7c0346 → 0.0.0-main-fd9c5f51
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/apps/cli/commands/project/doctor/checkGithub.js +19 -2
- package/dist/apps/cli/src/apps/cli/commands/project/doctor/checkGithub.js.map +1 -1
- package/dist/apps/cli/src/apps/cli/commands/project/githubMergeGating.d.ts +24 -11
- package/dist/apps/cli/src/apps/cli/commands/project/githubMergeGating.js +28 -19
- package/dist/apps/cli/src/apps/cli/commands/project/githubMergeGating.js.map +1 -1
- package/dist/apps/cli/src/apps/cli/commands/project/setup/index.js +4 -3
- package/dist/apps/cli/src/apps/cli/commands/project/setup/index.js.map +1 -1
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupGithub.d.ts +6 -3
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupGithub.js +64 -3
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupGithub.js.map +1 -1
- package/dist/apps/cli/src/release/changesetsReleaseJob.js +54 -12
- package/dist/apps/cli/src/release/changesetsReleaseJob.js.map +1 -1
- package/dist/apps/cli/src/release/releaseGit.d.ts +2 -0
- package/dist/apps/cli/src/release/releaseGit.js +9 -1
- package/dist/apps/cli/src/release/releaseGit.js.map +1 -1
- package/dist/bundles/catci/index.js +5 -5
- package/dist/bundles/catenv/index.js +5 -0
- package/dist/bundles/cli/index.js +121 -28
- package/dist/bundles/runner-images/changesets/Dockerfile +2 -1
- package/dist/bundles/skills/catladder-migrate-ci-backend/SKILL.md +11 -7
- package/dist/packages/pipeline/src/backends/github/githubReleaseJobs.js +5 -0
- package/dist/packages/pipeline/src/backends/github/githubReleaseJobs.js.map +1 -1
- package/dist/runner-images/changesets/Dockerfile +2 -1
- package/dist/skills/catladder-migrate-ci-backend/SKILL.md +11 -7
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/apps/cli/commands/project/__tests__/githubMergeGating.test.ts +19 -8
- package/src/apps/cli/commands/project/doctor/checkGithub.ts +32 -2
- package/src/apps/cli/commands/project/githubMergeGating.ts +29 -18
- package/src/apps/cli/commands/project/setup/index.ts +4 -3
- package/src/apps/cli/commands/project/setup/setupGithub.ts +88 -4
- package/src/release/changesetsReleaseJob.ts +71 -14
- package/src/release/releaseGit.ts +11 -0
|
@@ -3581,6 +3581,11 @@ const createReleaseJob = (config, images, options = {}) => {
|
|
|
3581
3581
|
...(allNeeds.length > 0 ? { needs: allNeeds } : {}),
|
|
3582
3582
|
env: {
|
|
3583
3583
|
GITHUB_TOKEN: "${{ github.token }}",
|
|
3584
|
+
// the release deploy key (provisioned by `project setup`): the
|
|
3585
|
+
// release push must bypass the merge-gating ruleset, which only
|
|
3586
|
+
// a deploy key can — empty when not provisioned, then the job
|
|
3587
|
+
// pushes with the workflow token (fine without gating)
|
|
3588
|
+
CATLADDER_RELEASE_KEY: "${{ secrets.CATLADDER_RELEASE_KEY }}",
|
|
3584
3589
|
...options.extraEnv,
|
|
3585
3590
|
},
|
|
3586
3591
|
steps: [
|
|
@@ -761,14 +761,31 @@ const checkGithubMergeGating = async (report, repo) => {
|
|
|
761
761
|
? await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets/${named.id}`).catch(() => null)
|
|
762
762
|
: null;
|
|
763
763
|
if (ruleset && (0, githubMergeGating_1.rulesetProvidesMergeGating)(ruleset)) {
|
|
764
|
-
report.ok(`ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}': '${pipeline_1.AGGREGATE_CHECK_JOB_NAME}' required on ${branch},
|
|
764
|
+
report.ok(`ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}': '${pipeline_1.AGGREGATE_CHECK_JOB_NAME}' required on ${branch}, deploy-key bypass for the release push`);
|
|
765
765
|
}
|
|
766
766
|
else if (ruleset) {
|
|
767
|
-
report.fail(`ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}' exists but is incomplete (inactive, check not required, or
|
|
767
|
+
report.fail(`ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}' exists but is incomplete (inactive, check not required, or deploy-key bypass missing)`, "run: catladder project setup");
|
|
768
768
|
}
|
|
769
769
|
else {
|
|
770
770
|
report.fail(`no '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}' ruleset on ${repo} — PRs can merge while the pipeline is red or still running`, "run: catladder project setup");
|
|
771
771
|
}
|
|
772
|
+
try {
|
|
773
|
+
const [keys, secretNames] = await Promise.all([
|
|
774
|
+
(0, github_1.ghApiJson)("GET", `repos/${repo}/keys?per_page=100`),
|
|
775
|
+
(0, github_1.listGithubSecretNames)(repo),
|
|
776
|
+
]);
|
|
777
|
+
const key = keys.find((k) => k.title === githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE);
|
|
778
|
+
const hasSecret = secretNames.some((name) => name.toUpperCase() === githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET);
|
|
779
|
+
if (key && !key.read_only && hasSecret) {
|
|
780
|
+
report.ok(`release deploy key '${githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE}' + secret ${githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET} in place`);
|
|
781
|
+
}
|
|
782
|
+
else {
|
|
783
|
+
report.fail(`release deploy key incomplete (key: ${key ? (key.read_only ? "read-only" : "ok") : "missing"}, secret ${githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET}: ${hasSecret ? "set" : "missing"}) — the release job cannot push past the merge gating`, "run: catladder project setup");
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
catch (e) {
|
|
787
|
+
report.warn(`could not check the release deploy key (${e.message})`);
|
|
788
|
+
}
|
|
772
789
|
const protection = await (0, github_1.ghApiJson)("GET", `repos/${repo}/branches/${branch}/protection`).catch(() => null);
|
|
773
790
|
const checks = (_b = (_a = protection === null || protection === void 0 ? void 0 : protection.required_status_checks) === null || _a === void 0 ? void 0 : _a.checks) !== null && _b !== void 0 ? _b : [];
|
|
774
791
|
if (checks.some((c) => c.context === pipeline_1.AGGREGATE_CHECK_JOB_NAME)) {
|
|
@@ -978,7 +995,7 @@ exports.doctorProject = doctorProject;
|
|
|
978
995
|
"use strict";
|
|
979
996
|
|
|
980
997
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
981
|
-
exports.rulesetProvidesMergeGating = exports.desiredMergeGatingRuleset = exports.MERGE_GATING_RULESET_NAME = exports.GITHUB_ACTIONS_APP_ID = void 0;
|
|
998
|
+
exports.rulesetProvidesMergeGating = exports.desiredMergeGatingRuleset = exports.RELEASE_DEPLOY_KEY_SECRET = exports.RELEASE_DEPLOY_KEY_TITLE = exports.MERGE_GATING_RULESET_NAME = exports.GITHUB_ACTIONS_APP_ID = void 0;
|
|
982
999
|
const pipeline_1 = __nccwpck_require__(53695);
|
|
983
1000
|
/**
|
|
984
1001
|
* github merge gating — shared between `project setup` (writes it) and
|
|
@@ -987,17 +1004,30 @@ const pipeline_1 = __nccwpck_require__(53695);
|
|
|
987
1004
|
* The gating lives in a repository RULESET, not classic branch
|
|
988
1005
|
* protection: only rulesets can carry bypass actors, and the release
|
|
989
1006
|
* job needs one. It pushes the release commit and tag straight to the
|
|
990
|
-
* default branch
|
|
991
|
-
*
|
|
992
|
-
*
|
|
993
|
-
*
|
|
994
|
-
*
|
|
995
|
-
*
|
|
996
|
-
*
|
|
997
|
-
|
|
998
|
-
|
|
1007
|
+
* default branch — under classic protection the required `catladder ✅`
|
|
1008
|
+
* check rejects that push (GH006), because the fresh release commit
|
|
1009
|
+
* cannot have a passing check yet.
|
|
1010
|
+
*
|
|
1011
|
+
* The bypass actor is a DEPLOY KEY: github deliberately refuses the
|
|
1012
|
+
* built-in GitHub Actions app on bypass lists (any collaborator could
|
|
1013
|
+
* push anywhere by authoring a workflow), so the workflow token can
|
|
1014
|
+
* never bypass. Instead `project setup` provisions a write deploy key
|
|
1015
|
+
* (public half on the repo, private half as an actions secret) and the
|
|
1016
|
+
* release job pushes over ssh with it. Deploy keys are repo-scoped,
|
|
1017
|
+
* only admins can add them, and they never expire — gitlab's
|
|
1018
|
+
* counterpart is the maintainer-role `GL_TOKEN`, which has to be
|
|
1019
|
+
* renewed yearly.
|
|
1020
|
+
*/
|
|
1021
|
+
/** the app id of GitHub Actions — the integration reporting the check */
|
|
999
1022
|
exports.GITHUB_ACTIONS_APP_ID = 15368;
|
|
1000
1023
|
exports.MERGE_GATING_RULESET_NAME = "catladder merge gating";
|
|
1024
|
+
/** title of the deploy key `project setup` registers on the repo */
|
|
1025
|
+
exports.RELEASE_DEPLOY_KEY_TITLE = "catladder release";
|
|
1026
|
+
/**
|
|
1027
|
+
* actions secret holding the deploy key's private half; the generated
|
|
1028
|
+
* release jobs pass it to catci, which pushes over ssh when it is set
|
|
1029
|
+
*/
|
|
1030
|
+
exports.RELEASE_DEPLOY_KEY_SECRET = "CATLADDER_RELEASE_KEY";
|
|
1001
1031
|
/** the ruleset `project setup` creates (and restores on drift) */
|
|
1002
1032
|
const desiredMergeGatingRuleset = () => ({
|
|
1003
1033
|
name: exports.MERGE_GATING_RULESET_NAME,
|
|
@@ -1020,18 +1050,16 @@ const desiredMergeGatingRuleset = () => ({
|
|
|
1020
1050
|
},
|
|
1021
1051
|
],
|
|
1022
1052
|
bypass_actors: [
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
bypass_mode: "always",
|
|
1027
|
-
},
|
|
1053
|
+
// deploy keys carry no id — the bypass covers every deploy key of
|
|
1054
|
+
// the repository (adding one requires admin anyway)
|
|
1055
|
+
{ actor_id: null, actor_type: "DeployKey", bypass_mode: "always" },
|
|
1028
1056
|
],
|
|
1029
1057
|
});
|
|
1030
1058
|
exports.desiredMergeGatingRuleset = desiredMergeGatingRuleset;
|
|
1031
1059
|
/**
|
|
1032
1060
|
* whether a ruleset provides working merge gating: active, requires
|
|
1033
|
-
* the aggregate check, and lets the release
|
|
1034
|
-
*
|
|
1061
|
+
* the aggregate check, and lets the release deploy key bypass it.
|
|
1062
|
+
* Extra rules or bypass actors someone added are fine.
|
|
1035
1063
|
*/
|
|
1036
1064
|
const rulesetProvidesMergeGating = (ruleset) => {
|
|
1037
1065
|
var _a, _b;
|
|
@@ -1041,9 +1069,7 @@ const rulesetProvidesMergeGating = (ruleset) => {
|
|
|
1041
1069
|
return rule.type === "required_status_checks" &&
|
|
1042
1070
|
((_b = (_a = rule.parameters) === null || _a === void 0 ? void 0 : _a.required_status_checks) !== null && _b !== void 0 ? _b : []).some((check) => check.context === pipeline_1.AGGREGATE_CHECK_JOB_NAME);
|
|
1043
1071
|
}) &&
|
|
1044
|
-
((_b = ruleset.bypass_actors) !== null && _b !== void 0 ? _b : []).some((actor) => actor.actor_type === "
|
|
1045
|
-
actor.actor_id === exports.GITHUB_ACTIONS_APP_ID &&
|
|
1046
|
-
actor.bypass_mode === "always");
|
|
1072
|
+
((_b = ruleset.bypass_actors) !== null && _b !== void 0 ? _b : []).some((actor) => actor.actor_type === "DeployKey" && actor.bypass_mode === "always");
|
|
1047
1073
|
};
|
|
1048
1074
|
exports.rulesetProvidesMergeGating = rulesetProvidesMergeGating;
|
|
1049
1075
|
//# sourceMappingURL=githubMergeGating.js.map
|
|
@@ -1145,13 +1171,14 @@ const setupProject = async (instance, onlyComponents) => {
|
|
|
1145
1171
|
});
|
|
1146
1172
|
const enabledPipelines = config ? (0, pipeline_1.getEnabledPipelineTypes)(config) : [];
|
|
1147
1173
|
await (0, logSection_1.logSection)(instance, "base setup", async () => {
|
|
1148
|
-
// gitlab-specific provisioning (access token, agent webhooks
|
|
1149
|
-
// meaningless (and failing) on a
|
|
1174
|
+
// gitlab-specific provisioning (access token, agent webhooks, the
|
|
1175
|
+
// `catladder` project topic) — meaningless (and failing) on a
|
|
1176
|
+
// github-only project
|
|
1150
1177
|
if (enabledPipelines.includes("gitlab")) {
|
|
1151
1178
|
await (0, setupAccessTokens_1.setupAccessTokens)(instance);
|
|
1152
1179
|
await (0, setupAgents_1.setupAgents)(instance);
|
|
1180
|
+
await (0, setupTopic_1.setupTopic)(instance);
|
|
1153
1181
|
}
|
|
1154
|
-
await (0, setupTopic_1.setupTopic)(instance);
|
|
1155
1182
|
if (config) {
|
|
1156
1183
|
await (0, setupGithub_1.setupGithub)(instance, config);
|
|
1157
1184
|
}
|
|
@@ -1534,9 +1561,15 @@ exports.setupContext = setupContext;
|
|
|
1534
1561
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1535
1562
|
exports.setupGithub = void 0;
|
|
1536
1563
|
const pipeline_1 = __nccwpck_require__(53695);
|
|
1564
|
+
const child_process_1 = __nccwpck_require__(35317);
|
|
1565
|
+
const promises_1 = __nccwpck_require__(91943);
|
|
1566
|
+
const os_1 = __nccwpck_require__(70857);
|
|
1567
|
+
const path_1 = __nccwpck_require__(16928);
|
|
1568
|
+
const util_1 = __nccwpck_require__(39023);
|
|
1537
1569
|
const commandSecretsSyncGithub_1 = __nccwpck_require__(27565);
|
|
1538
1570
|
const github_1 = __nccwpck_require__(41353);
|
|
1539
1571
|
const githubMergeGating_1 = __nccwpck_require__(14966);
|
|
1572
|
+
const execFile = (0, util_1.promisify)(child_process_1.execFile);
|
|
1540
1573
|
/**
|
|
1541
1574
|
* configures github merge gating — the sane default gitlab ships
|
|
1542
1575
|
* built-in and a fresh github repository lacks entirely: without it a
|
|
@@ -1544,11 +1577,14 @@ const githubMergeGating_1 = __nccwpck_require__(14966);
|
|
|
1544
1577
|
* auto-merge button never appears.
|
|
1545
1578
|
*
|
|
1546
1579
|
* - repo settings: allow auto-merge, delete merged head branches
|
|
1580
|
+
* - the release deploy key: a write deploy key on the repo, its
|
|
1581
|
+
* private half stored as the CATLADDER_RELEASE_KEY actions secret —
|
|
1582
|
+
* the release job pushes the release commit and tag with it
|
|
1547
1583
|
* - a repository ruleset on the default branch requiring the generated
|
|
1548
1584
|
* `catladder ✅` aggregate check (the one stable context — individual
|
|
1549
|
-
* job names change with every component add/rename), with a
|
|
1550
|
-
*
|
|
1551
|
-
*
|
|
1585
|
+
* job names change with every component add/rename), with a deploy
|
|
1586
|
+
* key bypass so the release push goes through (see
|
|
1587
|
+
* githubMergeGating.ts for the full rationale)
|
|
1552
1588
|
*
|
|
1553
1589
|
* Earlier versions required the check via classic branch protection,
|
|
1554
1590
|
* which has no bypass list — the release job's direct push to the
|
|
@@ -1580,6 +1616,7 @@ const setupGithub = async (instance, config) => {
|
|
|
1580
1616
|
else {
|
|
1581
1617
|
instance.log("✅ auto-merge already enabled");
|
|
1582
1618
|
}
|
|
1619
|
+
await ensureReleaseDeployKey(instance, repo);
|
|
1583
1620
|
const branch = repoInfo.default_branch;
|
|
1584
1621
|
const rulesets = await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets?per_page=100`);
|
|
1585
1622
|
const existing = rulesets.find((r) => r.name === githubMergeGating_1.MERGE_GATING_RULESET_NAME);
|
|
@@ -1600,6 +1637,57 @@ const setupGithub = async (instance, config) => {
|
|
|
1600
1637
|
await migrateAwayFromClassicProtection(instance, repo, branch);
|
|
1601
1638
|
};
|
|
1602
1639
|
exports.setupGithub = setupGithub;
|
|
1640
|
+
/**
|
|
1641
|
+
* provisions the release deploy key: an ed25519 keypair whose public
|
|
1642
|
+
* half becomes a write deploy key on the repo and whose private half
|
|
1643
|
+
* becomes the CATLADDER_RELEASE_KEY actions secret. The key and the
|
|
1644
|
+
* secret only work as a pair, so when either half is missing the pair
|
|
1645
|
+
* is rotated (github secrets are write-only — the private half can
|
|
1646
|
+
* never be read back to check it matches).
|
|
1647
|
+
*/
|
|
1648
|
+
const ensureReleaseDeployKey = async (instance, repo) => {
|
|
1649
|
+
const [keys, secretNames] = await Promise.all([
|
|
1650
|
+
(0, github_1.ghApiJson)("GET", `repos/${repo}/keys?per_page=100`),
|
|
1651
|
+
(0, github_1.listGithubSecretNames)(repo),
|
|
1652
|
+
]);
|
|
1653
|
+
const existingKey = keys.find((k) => k.title === githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE);
|
|
1654
|
+
const hasSecret = secretNames.some((name) => name.toUpperCase() === githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET);
|
|
1655
|
+
if (existingKey && !existingKey.read_only && hasSecret) {
|
|
1656
|
+
instance.log(`✅ release deploy key '${githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE}' + secret ${githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET} in place`);
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
if (existingKey) {
|
|
1660
|
+
await (0, github_1.ghApiJson)("DELETE", `repos/${repo}/keys/${existingKey.id}`);
|
|
1661
|
+
instance.log(`♻️ release deploy key '${githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE}' rotated (${existingKey.read_only
|
|
1662
|
+
? "was read-only"
|
|
1663
|
+
: `secret ${githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET} missing`})`);
|
|
1664
|
+
}
|
|
1665
|
+
const dir = await (0, promises_1.mkdtemp)((0, path_1.join)((0, os_1.tmpdir)(), "catladder-release-key-"));
|
|
1666
|
+
try {
|
|
1667
|
+
const keyFile = (0, path_1.join)(dir, "id_ed25519");
|
|
1668
|
+
await execFile("ssh-keygen", [
|
|
1669
|
+
...["-t", "ed25519"],
|
|
1670
|
+
...["-C", `${githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE} (${repo})`],
|
|
1671
|
+
...["-N", ""],
|
|
1672
|
+
...["-f", keyFile],
|
|
1673
|
+
"-q",
|
|
1674
|
+
]);
|
|
1675
|
+
const [privateKey, publicKey] = await Promise.all([
|
|
1676
|
+
(0, promises_1.readFile)(keyFile, "utf-8"),
|
|
1677
|
+
(0, promises_1.readFile)(`${keyFile}.pub`, "utf-8"),
|
|
1678
|
+
]);
|
|
1679
|
+
await (0, github_1.ghApiJson)("POST", `repos/${repo}/keys`, {
|
|
1680
|
+
title: githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE,
|
|
1681
|
+
key: publicKey.trim(),
|
|
1682
|
+
read_only: false,
|
|
1683
|
+
});
|
|
1684
|
+
await (0, github_1.setGithubSecret)(repo, githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET, privateKey);
|
|
1685
|
+
}
|
|
1686
|
+
finally {
|
|
1687
|
+
await (0, promises_1.rm)(dir, { recursive: true, force: true });
|
|
1688
|
+
}
|
|
1689
|
+
instance.log(`✅ release deploy key '${githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE}' registered, private half stored as secret ${githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET} — the release job pushes with it`);
|
|
1690
|
+
};
|
|
1603
1691
|
/**
|
|
1604
1692
|
* removes the aggregate check from a classic branch protection rule
|
|
1605
1693
|
* set up by earlier catladder versions — with the check now required
|
|
@@ -9659,6 +9747,11 @@ const createReleaseJob = (config, images, options = {}) => {
|
|
|
9659
9747
|
...(allNeeds.length > 0 ? { needs: allNeeds } : {}),
|
|
9660
9748
|
env: {
|
|
9661
9749
|
GITHUB_TOKEN: "${{ github.token }}",
|
|
9750
|
+
// the release deploy key (provisioned by `project setup`): the
|
|
9751
|
+
// release push must bypass the merge-gating ruleset, which only
|
|
9752
|
+
// a deploy key can — empty when not provisioned, then the job
|
|
9753
|
+
// pushes with the workflow token (fine without gating)
|
|
9754
|
+
CATLADDER_RELEASE_KEY: "${{ secrets.CATLADDER_RELEASE_KEY }}",
|
|
9662
9755
|
...options.extraEnv,
|
|
9663
9756
|
},
|
|
9664
9757
|
steps: [
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
FROM node:lts-alpine
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# openssh: the release job pushes with the release deploy key over ssh
|
|
4
|
+
RUN apk add --no-cache bash git git-lfs openssh-client
|
|
4
5
|
|
|
5
6
|
# no release tooling baked in: the changesets release logic lives in
|
|
6
7
|
# catci, which is materialized into the repository checkout
|
|
@@ -264,13 +264,17 @@ now-wrong `gitRemote`, regenerate once more, and finish with
|
|
|
264
264
|
branch requiring the generated **`catladder ✅`** aggregate check
|
|
265
265
|
(the one stable context — never require individual job names, they
|
|
266
266
|
change with every component add/rename and a stale required name
|
|
267
|
-
blocks its own PR forever). The ruleset carries a
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
267
|
+
blocks its own PR forever). The ruleset carries a **deploy-key
|
|
268
|
+
bypass**: the release job pushes the release commit and tag straight
|
|
269
|
+
to the default branch, which the required check would otherwise
|
|
270
|
+
reject (GH006) — and github deliberately never lets the workflow
|
|
271
|
+
token bypass rulesets, so setup provisions a write deploy key
|
|
272
|
+
("catladder release", private half in the `CATLADDER_RELEASE_KEY`
|
|
273
|
+
actions secret; deploy keys never expire) that the release job
|
|
274
|
+
pushes with over ssh. Classic branch protection has no bypass list
|
|
275
|
+
at all, which is why setup uses a ruleset and migrates old
|
|
276
|
+
classic-protection gating away. `project doctor` verifies all of it.
|
|
277
|
+
Required reviews stay a human choice.
|
|
274
278
|
- Tell the team where the pipeline lives now and how manual actions
|
|
275
279
|
work there (on GitHub, manual jobs are dispatch workflows in the
|
|
276
280
|
Actions sidebar — `🚀 catladder create release`, `▶️ catladder deploy`,
|
|
@@ -57,6 +57,11 @@ const createReleaseJob = (config, images, options = {}) => {
|
|
|
57
57
|
...(allNeeds.length > 0 ? { needs: allNeeds } : {}),
|
|
58
58
|
env: {
|
|
59
59
|
GITHUB_TOKEN: "${{ github.token }}",
|
|
60
|
+
// the release deploy key (provisioned by `project setup`): the
|
|
61
|
+
// release push must bypass the merge-gating ruleset, which only
|
|
62
|
+
// a deploy key can — empty when not provisioned, then the job
|
|
63
|
+
// pushes with the workflow token (fine without gating)
|
|
64
|
+
CATLADDER_RELEASE_KEY: "${{ secrets.CATLADDER_RELEASE_KEY }}",
|
|
60
65
|
...options.extraEnv,
|
|
61
66
|
},
|
|
62
67
|
steps: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"githubReleaseJobs.js","sourceRoot":"","sources":["../../../../../../../../packages/pipeline/src/backends/github/githubReleaseJobs.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"githubReleaseJobs.js","sourceRoot":"","sources":["../../../../../../../../packages/pipeline/src/backends/github/githubReleaseJobs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
FROM node:lts-alpine
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# openssh: the release job pushes with the release deploy key over ssh
|
|
4
|
+
RUN apk add --no-cache bash git git-lfs openssh-client
|
|
4
5
|
|
|
5
6
|
# no release tooling baked in: the changesets release logic lives in
|
|
6
7
|
# catci, which is materialized into the repository checkout
|
|
@@ -264,13 +264,17 @@ now-wrong `gitRemote`, regenerate once more, and finish with
|
|
|
264
264
|
branch requiring the generated **`catladder ✅`** aggregate check
|
|
265
265
|
(the one stable context — never require individual job names, they
|
|
266
266
|
change with every component add/rename and a stale required name
|
|
267
|
-
blocks its own PR forever). The ruleset carries a
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
267
|
+
blocks its own PR forever). The ruleset carries a **deploy-key
|
|
268
|
+
bypass**: the release job pushes the release commit and tag straight
|
|
269
|
+
to the default branch, which the required check would otherwise
|
|
270
|
+
reject (GH006) — and github deliberately never lets the workflow
|
|
271
|
+
token bypass rulesets, so setup provisions a write deploy key
|
|
272
|
+
("catladder release", private half in the `CATLADDER_RELEASE_KEY`
|
|
273
|
+
actions secret; deploy keys never expire) that the release job
|
|
274
|
+
pushes with over ssh. Classic branch protection has no bypass list
|
|
275
|
+
at all, which is why setup uses a ruleset and migrates old
|
|
276
|
+
classic-protection gating away. `project doctor` verifies all of it.
|
|
277
|
+
Required reviews stay a human choice.
|
|
274
278
|
- Tell the team where the pipeline lives now and how manual actions
|
|
275
279
|
work there (on GitHub, manual jobs are dispatch workflows in the
|
|
276
280
|
Actions sidebar — `🚀 catladder create release`, `▶️ catladder deploy`,
|