@catladder/cli 0.0.0-main-a6b45abe → 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 +48 -9
- 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 +83 -0
- package/dist/apps/cli/src/apps/cli/commands/project/githubMergeGating.js +80 -0
- package/dist/apps/cli/src/apps/cli/commands/project/githubMergeGating.js.map +1 -0
- 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 +12 -7
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupGithub.js +138 -31
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupGithub.js.map +1 -1
- package/dist/apps/cli/src/release/changesetsReleaseJob.js +64 -4
- 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/apps/cli/src/utils/github.d.ts +1 -1
- package/dist/apps/cli/src/utils/github.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 +282 -43
- package/dist/bundles/runner-images/changesets/Dockerfile +2 -1
- package/dist/bundles/skills/catladder-migrate-ci-backend/SKILL.md +15 -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 +15 -7
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/apps/cli/commands/project/__tests__/githubMergeGating.test.ts +123 -0
- package/src/apps/cli/commands/project/doctor/checkGithub.ts +74 -8
- package/src/apps/cli/commands/project/githubMergeGating.ts +101 -0
- package/src/apps/cli/commands/project/setup/index.ts +4 -3
- package/src/apps/cli/commands/project/setup/setupGithub.ts +190 -27
- package/src/release/changesetsReleaseJob.ts +81 -6
- package/src/release/releaseGit.ts +11 -0
- package/src/utils/github.ts +1 -1
|
@@ -5,6 +5,7 @@ const pipeline_1 = require("../../../../../../../../packages/pipeline/src/index.
|
|
|
5
5
|
const commandSecretsSyncGithub_1 = require("../../../../../commands/project/commandSecretsSyncGithub");
|
|
6
6
|
const concurrency_1 = require("../../../../../utils/concurrency");
|
|
7
7
|
const github_1 = require("../../../../../utils/github");
|
|
8
|
+
const githubMergeGating_1 = require("../githubMergeGating");
|
|
8
9
|
/** marker for repo-level (environment-less) targets, see collectSecretTargets */
|
|
9
10
|
const REPO_LEVEL = "";
|
|
10
11
|
/**
|
|
@@ -108,10 +109,13 @@ const checkGithub = async (report, config) => {
|
|
|
108
109
|
exports.checkGithub = checkGithub;
|
|
109
110
|
/**
|
|
110
111
|
* verifies the merge gating `project setup` configures: auto-merge
|
|
111
|
-
* enabled and the
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
112
|
+
* enabled and the `catladder merge gating` ruleset requiring the
|
|
113
|
+
* generated `catladder ✅` aggregate check on the default branch (with
|
|
114
|
+
* the bypass that lets the release job push). Without the check a PR
|
|
115
|
+
* is mergeable while its checks are still running — gitlab ships this
|
|
116
|
+
* behavior built-in, github silently does not. The check required via
|
|
117
|
+
* classic branch protection instead is flagged: that setup rejects the
|
|
118
|
+
* release job's own push (GH006).
|
|
115
119
|
*/
|
|
116
120
|
const checkGithubMergeGating = async (report, repo) => {
|
|
117
121
|
var _a, _b;
|
|
@@ -130,17 +134,52 @@ const checkGithubMergeGating = async (report, repo) => {
|
|
|
130
134
|
report.fail("auto-merge disabled — the merge-when-pipeline-succeeds button cannot appear", "run: catladder project setup");
|
|
131
135
|
}
|
|
132
136
|
const branch = repoInfo.default_branch;
|
|
137
|
+
let rulesets;
|
|
138
|
+
try {
|
|
139
|
+
rulesets = await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets?per_page=100`);
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
report.warn(`could not list rulesets of ${repo} (${e.message})`);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const named = rulesets.find((r) => r.name === githubMergeGating_1.MERGE_GATING_RULESET_NAME);
|
|
146
|
+
const ruleset = named
|
|
147
|
+
? await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets/${named.id}`).catch(() => null)
|
|
148
|
+
: null;
|
|
149
|
+
if (ruleset && (0, githubMergeGating_1.rulesetProvidesMergeGating)(ruleset)) {
|
|
150
|
+
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`);
|
|
151
|
+
}
|
|
152
|
+
else if (ruleset) {
|
|
153
|
+
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");
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
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");
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const [keys, secretNames] = await Promise.all([
|
|
160
|
+
(0, github_1.ghApiJson)("GET", `repos/${repo}/keys?per_page=100`),
|
|
161
|
+
(0, github_1.listGithubSecretNames)(repo),
|
|
162
|
+
]);
|
|
163
|
+
const key = keys.find((k) => k.title === githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE);
|
|
164
|
+
const hasSecret = secretNames.some((name) => name.toUpperCase() === githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET);
|
|
165
|
+
if (key && !key.read_only && hasSecret) {
|
|
166
|
+
report.ok(`release deploy key '${githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE}' + secret ${githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET} in place`);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
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");
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch (e) {
|
|
173
|
+
report.warn(`could not check the release deploy key (${e.message})`);
|
|
174
|
+
}
|
|
133
175
|
const protection = await (0, github_1.ghApiJson)("GET", `repos/${repo}/branches/${branch}/protection`).catch(() => null);
|
|
134
176
|
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 : [];
|
|
135
177
|
if (checks.some((c) => c.context === pipeline_1.AGGREGATE_CHECK_JOB_NAME)) {
|
|
136
|
-
report.
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
report.fail(`'${pipeline_1.AGGREGATE_CHECK_JOB_NAME}' is not a required check on ${branch} — PRs can merge while the pipeline is red or still running`, "run: catladder project setup");
|
|
178
|
+
report.fail(`'${pipeline_1.AGGREGATE_CHECK_JOB_NAME}' is still required via classic branch protection on ${branch} — that rejects the release job's push (GH006)`, "run: catladder project setup");
|
|
140
179
|
}
|
|
141
180
|
const stale = checks.filter((c) => c.context !== pipeline_1.AGGREGATE_CHECK_JOB_NAME);
|
|
142
181
|
if (stale.length > 0) {
|
|
143
|
-
report.warn(`${branch} requires ${stale.length} additional named check(s) (${stale
|
|
182
|
+
report.warn(`${branch} requires ${stale.length} additional named check(s) via classic branch protection (${stale
|
|
144
183
|
.map((c) => c.context)
|
|
145
184
|
.join(", ")}) — job names change with components; prefer only '${pipeline_1.AGGREGATE_CHECK_JOB_NAME}'`);
|
|
146
185
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkGithub.js","sourceRoot":"","sources":["../../../../../../../../../src/apps/cli/commands/project/doctor/checkGithub.ts"],"names":[],"mappings":";;;AACA,kDAI6B;AAC7B,uGAGkE;AAClE,kEAAsE;AACtE,wDAMqC;
|
|
1
|
+
{"version":3,"file":"checkGithub.js","sourceRoot":"","sources":["../../../../../../../../../src/apps/cli/commands/project/doctor/checkGithub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* github merge gating — shared between `project setup` (writes it) and
|
|
3
|
+
* `project doctor` (verifies it).
|
|
4
|
+
*
|
|
5
|
+
* The gating lives in a repository RULESET, not classic branch
|
|
6
|
+
* protection: only rulesets can carry bypass actors, and the release
|
|
7
|
+
* job needs one. It pushes the release commit and tag straight to the
|
|
8
|
+
* default branch — under classic protection the required `catladder ✅`
|
|
9
|
+
* check rejects that push (GH006), because the fresh release commit
|
|
10
|
+
* cannot have a passing check yet.
|
|
11
|
+
*
|
|
12
|
+
* The bypass actor is a DEPLOY KEY: github deliberately refuses the
|
|
13
|
+
* built-in GitHub Actions app on bypass lists (any collaborator could
|
|
14
|
+
* push anywhere by authoring a workflow), so the workflow token can
|
|
15
|
+
* never bypass. Instead `project setup` provisions a write deploy key
|
|
16
|
+
* (public half on the repo, private half as an actions secret) and the
|
|
17
|
+
* release job pushes over ssh with it. Deploy keys are repo-scoped,
|
|
18
|
+
* only admins can add them, and they never expire — gitlab's
|
|
19
|
+
* counterpart is the maintainer-role `GL_TOKEN`, which has to be
|
|
20
|
+
* renewed yearly.
|
|
21
|
+
*/
|
|
22
|
+
/** the app id of GitHub Actions — the integration reporting the check */
|
|
23
|
+
export declare const GITHUB_ACTIONS_APP_ID = 15368;
|
|
24
|
+
export declare const MERGE_GATING_RULESET_NAME = "catladder merge gating";
|
|
25
|
+
/** title of the deploy key `project setup` registers on the repo */
|
|
26
|
+
export declare const RELEASE_DEPLOY_KEY_TITLE = "catladder release";
|
|
27
|
+
/**
|
|
28
|
+
* actions secret holding the deploy key's private half; the generated
|
|
29
|
+
* release jobs pass it to catci, which pushes over ssh when it is set
|
|
30
|
+
*/
|
|
31
|
+
export declare const RELEASE_DEPLOY_KEY_SECRET = "CATLADDER_RELEASE_KEY";
|
|
32
|
+
export type GithubRuleset = {
|
|
33
|
+
id: number;
|
|
34
|
+
name: string;
|
|
35
|
+
enforcement: string;
|
|
36
|
+
rules?: Array<{
|
|
37
|
+
type: string;
|
|
38
|
+
parameters?: {
|
|
39
|
+
required_status_checks?: Array<{
|
|
40
|
+
context: string;
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
43
|
+
}>;
|
|
44
|
+
bypass_actors?: Array<{
|
|
45
|
+
actor_id?: number | null;
|
|
46
|
+
actor_type: string;
|
|
47
|
+
bypass_mode: string;
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
/** the ruleset `project setup` creates (and restores on drift) */
|
|
51
|
+
export declare const desiredMergeGatingRuleset: () => {
|
|
52
|
+
name: string;
|
|
53
|
+
target: string;
|
|
54
|
+
enforcement: string;
|
|
55
|
+
conditions: {
|
|
56
|
+
ref_name: {
|
|
57
|
+
include: string[];
|
|
58
|
+
exclude: any[];
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
rules: {
|
|
62
|
+
type: string;
|
|
63
|
+
parameters: {
|
|
64
|
+
strict_required_status_checks_policy: boolean;
|
|
65
|
+
do_not_enforce_on_create: boolean;
|
|
66
|
+
required_status_checks: {
|
|
67
|
+
context: string;
|
|
68
|
+
integration_id: number;
|
|
69
|
+
}[];
|
|
70
|
+
};
|
|
71
|
+
}[];
|
|
72
|
+
bypass_actors: {
|
|
73
|
+
actor_id: any;
|
|
74
|
+
actor_type: string;
|
|
75
|
+
bypass_mode: string;
|
|
76
|
+
}[];
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* whether a ruleset provides working merge gating: active, requires
|
|
80
|
+
* the aggregate check, and lets the release deploy key bypass it.
|
|
81
|
+
* Extra rules or bypass actors someone added are fine.
|
|
82
|
+
*/
|
|
83
|
+
export declare const rulesetProvidesMergeGating: (ruleset: GithubRuleset) => boolean;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
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;
|
|
4
|
+
const pipeline_1 = require("../../../../../../../packages/pipeline/src/index.js");
|
|
5
|
+
/**
|
|
6
|
+
* github merge gating — shared between `project setup` (writes it) and
|
|
7
|
+
* `project doctor` (verifies it).
|
|
8
|
+
*
|
|
9
|
+
* The gating lives in a repository RULESET, not classic branch
|
|
10
|
+
* protection: only rulesets can carry bypass actors, and the release
|
|
11
|
+
* job needs one. It pushes the release commit and tag straight to the
|
|
12
|
+
* default branch — under classic protection the required `catladder ✅`
|
|
13
|
+
* check rejects that push (GH006), because the fresh release commit
|
|
14
|
+
* cannot have a passing check yet.
|
|
15
|
+
*
|
|
16
|
+
* The bypass actor is a DEPLOY KEY: github deliberately refuses the
|
|
17
|
+
* built-in GitHub Actions app on bypass lists (any collaborator could
|
|
18
|
+
* push anywhere by authoring a workflow), so the workflow token can
|
|
19
|
+
* never bypass. Instead `project setup` provisions a write deploy key
|
|
20
|
+
* (public half on the repo, private half as an actions secret) and the
|
|
21
|
+
* release job pushes over ssh with it. Deploy keys are repo-scoped,
|
|
22
|
+
* only admins can add them, and they never expire — gitlab's
|
|
23
|
+
* counterpart is the maintainer-role `GL_TOKEN`, which has to be
|
|
24
|
+
* renewed yearly.
|
|
25
|
+
*/
|
|
26
|
+
/** the app id of GitHub Actions — the integration reporting the check */
|
|
27
|
+
exports.GITHUB_ACTIONS_APP_ID = 15368;
|
|
28
|
+
exports.MERGE_GATING_RULESET_NAME = "catladder merge gating";
|
|
29
|
+
/** title of the deploy key `project setup` registers on the repo */
|
|
30
|
+
exports.RELEASE_DEPLOY_KEY_TITLE = "catladder release";
|
|
31
|
+
/**
|
|
32
|
+
* actions secret holding the deploy key's private half; the generated
|
|
33
|
+
* release jobs pass it to catci, which pushes over ssh when it is set
|
|
34
|
+
*/
|
|
35
|
+
exports.RELEASE_DEPLOY_KEY_SECRET = "CATLADDER_RELEASE_KEY";
|
|
36
|
+
/** the ruleset `project setup` creates (and restores on drift) */
|
|
37
|
+
const desiredMergeGatingRuleset = () => ({
|
|
38
|
+
name: exports.MERGE_GATING_RULESET_NAME,
|
|
39
|
+
target: "branch",
|
|
40
|
+
enforcement: "active",
|
|
41
|
+
conditions: { ref_name: { include: ["~DEFAULT_BRANCH"], exclude: [] } },
|
|
42
|
+
rules: [
|
|
43
|
+
{
|
|
44
|
+
type: "required_status_checks",
|
|
45
|
+
parameters: {
|
|
46
|
+
strict_required_status_checks_policy: false,
|
|
47
|
+
do_not_enforce_on_create: false,
|
|
48
|
+
required_status_checks: [
|
|
49
|
+
{
|
|
50
|
+
context: pipeline_1.AGGREGATE_CHECK_JOB_NAME,
|
|
51
|
+
integration_id: exports.GITHUB_ACTIONS_APP_ID,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
bypass_actors: [
|
|
58
|
+
// deploy keys carry no id — the bypass covers every deploy key of
|
|
59
|
+
// the repository (adding one requires admin anyway)
|
|
60
|
+
{ actor_id: null, actor_type: "DeployKey", bypass_mode: "always" },
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
exports.desiredMergeGatingRuleset = desiredMergeGatingRuleset;
|
|
64
|
+
/**
|
|
65
|
+
* whether a ruleset provides working merge gating: active, requires
|
|
66
|
+
* the aggregate check, and lets the release deploy key bypass it.
|
|
67
|
+
* Extra rules or bypass actors someone added are fine.
|
|
68
|
+
*/
|
|
69
|
+
const rulesetProvidesMergeGating = (ruleset) => {
|
|
70
|
+
var _a, _b;
|
|
71
|
+
return ruleset.enforcement === "active" &&
|
|
72
|
+
((_a = ruleset.rules) !== null && _a !== void 0 ? _a : []).some((rule) => {
|
|
73
|
+
var _a, _b;
|
|
74
|
+
return rule.type === "required_status_checks" &&
|
|
75
|
+
((_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);
|
|
76
|
+
}) &&
|
|
77
|
+
((_b = ruleset.bypass_actors) !== null && _b !== void 0 ? _b : []).some((actor) => actor.actor_type === "DeployKey" && actor.bypass_mode === "always");
|
|
78
|
+
};
|
|
79
|
+
exports.rulesetProvidesMergeGating = rulesetProvidesMergeGating;
|
|
80
|
+
//# sourceMappingURL=githubMergeGating.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"githubMergeGating.js","sourceRoot":"","sources":["../../../../../../../../src/apps/cli/commands/project/githubMergeGating.ts"],"names":[],"mappings":";;;AAAA,kDAA+D;AAE/D;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,yEAAyE;AAC5D,QAAA,qBAAqB,GAAG,KAAK,CAAC;AAE9B,QAAA,yBAAyB,GAAG,wBAAwB,CAAC;AAElE,oEAAoE;AACvD,QAAA,wBAAwB,GAAG,mBAAmB,CAAC;AAE5D;;;GAGG;AACU,QAAA,yBAAyB,GAAG,uBAAuB,CAAC;AAmBjE,kEAAkE;AAC3D,MAAM,yBAAyB,GAAG,GAAG,EAAE,CAAC,CAAC;IAC9C,IAAI,EAAE,iCAAyB;IAC/B,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,QAAQ;IACrB,UAAU,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE;IACvE,KAAK,EAAE;QACL;YACE,IAAI,EAAE,wBAAwB;YAC9B,UAAU,EAAE;gBACV,oCAAoC,EAAE,KAAK;gBAC3C,wBAAwB,EAAE,KAAK;gBAC/B,sBAAsB,EAAE;oBACtB;wBACE,OAAO,EAAE,mCAAwB;wBACjC,cAAc,EAAE,6BAAqB;qBACtC;iBACF;aACF;SACF;KACF;IACD,aAAa,EAAE;QACb,kEAAkE;QAClE,oDAAoD;QACpD,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE;KACnE;CACF,CAAC,CAAC;AAzBU,QAAA,yBAAyB,6BAyBnC;AAEH;;;;GAIG;AACI,MAAM,0BAA0B,GAAG,CAAC,OAAsB,EAAW,EAAE;;IAC5E,OAAA,OAAO,CAAC,WAAW,KAAK,QAAQ;QAChC,CAAC,MAAA,OAAO,CAAC,KAAK,mCAAI,EAAE,CAAC,CAAC,IAAI,CACxB,CAAC,IAAI,EAAE,EAAE;;YACP,OAAA,IAAI,CAAC,IAAI,KAAK,wBAAwB;gBACtC,CAAC,MAAA,MAAA,IAAI,CAAC,UAAU,0CAAE,sBAAsB,mCAAI,EAAE,CAAC,CAAC,IAAI,CAClD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,mCAAwB,CACtD,CAAA;SAAA,CACJ;QACD,CAAC,MAAA,OAAO,CAAC,aAAa,mCAAI,EAAE,CAAC,CAAC,IAAI,CAChC,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,UAAU,KAAK,WAAW,IAAI,KAAK,CAAC,WAAW,KAAK,QAAQ,CACrE,CAAA;CAAA,CAAC;AAZS,QAAA,0BAA0B,8BAYnC"}
|
|
@@ -29,13 +29,14 @@ const setupProject = async (instance, onlyComponents) => {
|
|
|
29
29
|
});
|
|
30
30
|
const enabledPipelines = config ? (0, pipeline_1.getEnabledPipelineTypes)(config) : [];
|
|
31
31
|
await (0, logSection_1.logSection)(instance, "base setup", async () => {
|
|
32
|
-
// gitlab-specific provisioning (access token, agent webhooks
|
|
33
|
-
// meaningless (and failing) on a
|
|
32
|
+
// gitlab-specific provisioning (access token, agent webhooks, the
|
|
33
|
+
// `catladder` project topic) — meaningless (and failing) on a
|
|
34
|
+
// github-only project
|
|
34
35
|
if (enabledPipelines.includes("gitlab")) {
|
|
35
36
|
await (0, setupAccessTokens_1.setupAccessTokens)(instance);
|
|
36
37
|
await (0, setupAgents_1.setupAgents)(instance);
|
|
38
|
+
await (0, setupTopic_1.setupTopic)(instance);
|
|
37
39
|
}
|
|
38
|
-
await (0, setupTopic_1.setupTopic)(instance);
|
|
39
40
|
if (config) {
|
|
40
41
|
await (0, setupGithub_1.setupGithub)(instance, config);
|
|
41
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../../src/apps/cli/commands/project/setup/index.ts"],"names":[],"mappings":";;;AAAA,kDAI6B;AAE7B,6EAGgD;AAChD,2DAAwD;AACxD,iDAA8C;AAC9C,6CAA0C;AAC1C,+CAA4C;AAC5C,+CAA4C;AAC5C,6CAA0C;AAC1C,6EAA0E;AAEnE,MAAM,YAAY,GAAG,KAAK,EAC/B,QAAY,EACZ,cAAkC,EAClC,EAAE;IACF,uEAAuE;IACvE,0EAA0E;IAC1E,uEAAuE;IACvE,uEAAuE;IACvE,oEAAoE;IACpE,MAAM,MAAM,GAAG,MAAM,IAAA,mCAAgB,GAAE,CAAC;IACxC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,IAAA,8BAAmB,EAAC,IAAA,8BAAmB,EAAC,MAAM,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,gEAAgE;IAChE,MAAM,IAAA,uDAA0B,EAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,IAAA,yCAAsB,EAAC,cAAc,CAAC,CAAC;IAChE,QAAQ,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC3C,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,QAAQ,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,MAAM,CAAC,CAAC,CAAC,IAAA,kCAAuB,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,MAAM,IAAA,uBAAU,EAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,IAAI,EAAE;QAClD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../../src/apps/cli/commands/project/setup/index.ts"],"names":[],"mappings":";;;AAAA,kDAI6B;AAE7B,6EAGgD;AAChD,2DAAwD;AACxD,iDAA8C;AAC9C,6CAA0C;AAC1C,+CAA4C;AAC5C,+CAA4C;AAC5C,6CAA0C;AAC1C,6EAA0E;AAEnE,MAAM,YAAY,GAAG,KAAK,EAC/B,QAAY,EACZ,cAAkC,EAClC,EAAE;IACF,uEAAuE;IACvE,0EAA0E;IAC1E,uEAAuE;IACvE,uEAAuE;IACvE,oEAAoE;IACpE,MAAM,MAAM,GAAG,MAAM,IAAA,mCAAgB,GAAE,CAAC;IACxC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,IAAA,8BAAmB,EAAC,IAAA,8BAAmB,EAAC,MAAM,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,gEAAgE;IAChE,MAAM,IAAA,uDAA0B,EAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,IAAA,yCAAsB,EAAC,cAAc,CAAC,CAAC;IAChE,QAAQ,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC3C,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,QAAQ,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,MAAM,CAAC,CAAC,CAAC,IAAA,kCAAuB,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,MAAM,IAAA,uBAAU,EAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,IAAI,EAAE;QAClD,kEAAkE;QAClE,8DAA8D;QAC9D,sBAAsB;QACtB,IAAI,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxC,MAAM,IAAA,qCAAiB,EAAC,QAAQ,CAAC,CAAC;YAClC,MAAM,IAAA,yBAAW,EAAC,QAAQ,CAAC,CAAC;YAC5B,MAAM,IAAA,uBAAU,EAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAA,yBAAW,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;IACH,CAAC,CAAC,CAAC;IACH,KAAK,MAAM,OAAO,IAAI,UAAU,EAAE,CAAC;QACjC,MAAM,IAAA,2BAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,QAAQ,eAAe,CAAC,CAAC;IACzE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,QAAQ,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IACjD;QACE,kCAAkC;QAClC,2BAA2B;QAC3B,qDAAqD;QACrD,qBAAqB;QACrB,eAAe;KAChB,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;IAC9C,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC,CAAC;AArDW,QAAA,YAAY,gBAqDvB"}
|
|
@@ -7,14 +7,19 @@ import type { IO } from "../../../../../core/types";
|
|
|
7
7
|
* auto-merge button never appears.
|
|
8
8
|
*
|
|
9
9
|
* - repo settings: allow auto-merge, delete merged head branches
|
|
10
|
-
* -
|
|
10
|
+
* - the release deploy key: a write deploy key on the repo, its
|
|
11
|
+
* private half stored as the CATLADDER_RELEASE_KEY actions secret —
|
|
12
|
+
* the release job pushes the release commit and tag with it
|
|
13
|
+
* - a repository ruleset on the default branch requiring the generated
|
|
11
14
|
* `catladder ✅` aggregate check (the one stable context — individual
|
|
12
|
-
* job names change with every component add/rename)
|
|
15
|
+
* job names change with every component add/rename), with a deploy
|
|
16
|
+
* key bypass so the release push goes through (see
|
|
17
|
+
* githubMergeGating.ts for the full rationale)
|
|
13
18
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
+
* Earlier versions required the check via classic branch protection,
|
|
20
|
+
* which has no bypass list — the release job's direct push to the
|
|
21
|
+
* default branch bounced off catladder's own gating (GH006). Setup
|
|
22
|
+
* migrates that away: the aggregate context is removed from an
|
|
23
|
+
* existing classic rule, everything else in it is preserved.
|
|
19
24
|
*/
|
|
20
25
|
export declare const setupGithub: (instance: IO, config: Config) => Promise<void>;
|
|
@@ -2,8 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.setupGithub = void 0;
|
|
4
4
|
const pipeline_1 = require("../../../../../../../../packages/pipeline/src/index.js");
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const promises_1 = require("fs/promises");
|
|
7
|
+
const os_1 = require("os");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const util_1 = require("util");
|
|
5
10
|
const commandSecretsSyncGithub_1 = require("../../../../../commands/project/commandSecretsSyncGithub");
|
|
6
11
|
const github_1 = require("../../../../../utils/github");
|
|
12
|
+
const githubMergeGating_1 = require("../githubMergeGating");
|
|
13
|
+
const execFile = (0, util_1.promisify)(child_process_1.execFile);
|
|
7
14
|
/**
|
|
8
15
|
* configures github merge gating — the sane default gitlab ships
|
|
9
16
|
* built-in and a fresh github repository lacks entirely: without it a
|
|
@@ -11,18 +18,22 @@ const github_1 = require("../../../../../utils/github");
|
|
|
11
18
|
* auto-merge button never appears.
|
|
12
19
|
*
|
|
13
20
|
* - repo settings: allow auto-merge, delete merged head branches
|
|
14
|
-
* -
|
|
21
|
+
* - the release deploy key: a write deploy key on the repo, its
|
|
22
|
+
* private half stored as the CATLADDER_RELEASE_KEY actions secret —
|
|
23
|
+
* the release job pushes the release commit and tag with it
|
|
24
|
+
* - a repository ruleset on the default branch requiring the generated
|
|
15
25
|
* `catladder ✅` aggregate check (the one stable context — individual
|
|
16
|
-
* job names change with every component add/rename)
|
|
26
|
+
* job names change with every component add/rename), with a deploy
|
|
27
|
+
* key bypass so the release push goes through (see
|
|
28
|
+
* githubMergeGating.ts for the full rationale)
|
|
17
29
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
30
|
+
* Earlier versions required the check via classic branch protection,
|
|
31
|
+
* which has no bypass list — the release job's direct push to the
|
|
32
|
+
* default branch bounced off catladder's own gating (GH006). Setup
|
|
33
|
+
* migrates that away: the aggregate context is removed from an
|
|
34
|
+
* existing classic rule, everything else in it is preserved.
|
|
23
35
|
*/
|
|
24
36
|
const setupGithub = async (instance, config) => {
|
|
25
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
26
37
|
if (!(0, pipeline_1.getEnabledPipelineTypes)(config).includes("github")) {
|
|
27
38
|
return;
|
|
28
39
|
}
|
|
@@ -46,34 +57,128 @@ const setupGithub = async (instance, config) => {
|
|
|
46
57
|
else {
|
|
47
58
|
instance.log("✅ auto-merge already enabled");
|
|
48
59
|
}
|
|
60
|
+
await ensureReleaseDeployKey(instance, repo);
|
|
49
61
|
const branch = repoInfo.default_branch;
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
|
|
62
|
+
const rulesets = await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets?per_page=100`);
|
|
63
|
+
const existing = rulesets.find((r) => r.name === githubMergeGating_1.MERGE_GATING_RULESET_NAME);
|
|
64
|
+
if (!existing) {
|
|
65
|
+
await (0, github_1.ghApiJson)("POST", `repos/${repo}/rulesets`, (0, githubMergeGating_1.desiredMergeGatingRuleset)());
|
|
66
|
+
instance.log(`✅ ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}': '${pipeline_1.AGGREGATE_CHECK_JOB_NAME}' required on ${branch} — merges wait for the pipeline, the release job can push`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const detail = await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets/${existing.id}`);
|
|
70
|
+
if ((0, githubMergeGating_1.rulesetProvidesMergeGating)(detail)) {
|
|
71
|
+
instance.log(`✅ ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}' already in place on ${branch}`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
await (0, github_1.ghApiJson)("PUT", `repos/${repo}/rulesets/${existing.id}`, (0, githubMergeGating_1.desiredMergeGatingRuleset)());
|
|
75
|
+
instance.log(`✅ ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}' restored — '${pipeline_1.AGGREGATE_CHECK_JOB_NAME}' required, release-job bypass in place`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
await migrateAwayFromClassicProtection(instance, repo, branch);
|
|
79
|
+
};
|
|
80
|
+
exports.setupGithub = setupGithub;
|
|
81
|
+
/**
|
|
82
|
+
* provisions the release deploy key: an ed25519 keypair whose public
|
|
83
|
+
* half becomes a write deploy key on the repo and whose private half
|
|
84
|
+
* becomes the CATLADDER_RELEASE_KEY actions secret. The key and the
|
|
85
|
+
* secret only work as a pair, so when either half is missing the pair
|
|
86
|
+
* is rotated (github secrets are write-only — the private half can
|
|
87
|
+
* never be read back to check it matches).
|
|
88
|
+
*/
|
|
89
|
+
const ensureReleaseDeployKey = async (instance, repo) => {
|
|
90
|
+
const [keys, secretNames] = await Promise.all([
|
|
91
|
+
(0, github_1.ghApiJson)("GET", `repos/${repo}/keys?per_page=100`),
|
|
92
|
+
(0, github_1.listGithubSecretNames)(repo),
|
|
93
|
+
]);
|
|
94
|
+
const existingKey = keys.find((k) => k.title === githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE);
|
|
95
|
+
const hasSecret = secretNames.some((name) => name.toUpperCase() === githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET);
|
|
96
|
+
if (existingKey && !existingKey.read_only && hasSecret) {
|
|
97
|
+
instance.log(`✅ release deploy key '${githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE}' + secret ${githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET} in place`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (existingKey) {
|
|
101
|
+
await (0, github_1.ghApiJson)("DELETE", `repos/${repo}/keys/${existingKey.id}`);
|
|
102
|
+
instance.log(`♻️ release deploy key '${githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE}' rotated (${existingKey.read_only
|
|
103
|
+
? "was read-only"
|
|
104
|
+
: `secret ${githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET} missing`})`);
|
|
105
|
+
}
|
|
106
|
+
const dir = await (0, promises_1.mkdtemp)((0, path_1.join)((0, os_1.tmpdir)(), "catladder-release-key-"));
|
|
107
|
+
try {
|
|
108
|
+
const keyFile = (0, path_1.join)(dir, "id_ed25519");
|
|
109
|
+
await execFile("ssh-keygen", [
|
|
110
|
+
...["-t", "ed25519"],
|
|
111
|
+
...["-C", `${githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE} (${repo})`],
|
|
112
|
+
...["-N", ""],
|
|
113
|
+
...["-f", keyFile],
|
|
114
|
+
"-q",
|
|
115
|
+
]);
|
|
116
|
+
const [privateKey, publicKey] = await Promise.all([
|
|
117
|
+
(0, promises_1.readFile)(keyFile, "utf-8"),
|
|
118
|
+
(0, promises_1.readFile)(`${keyFile}.pub`, "utf-8"),
|
|
119
|
+
]);
|
|
120
|
+
await (0, github_1.ghApiJson)("POST", `repos/${repo}/keys`, {
|
|
121
|
+
title: githubMergeGating_1.RELEASE_DEPLOY_KEY_TITLE,
|
|
122
|
+
key: publicKey.trim(),
|
|
123
|
+
read_only: false,
|
|
124
|
+
});
|
|
125
|
+
await (0, github_1.setGithubSecret)(repo, githubMergeGating_1.RELEASE_DEPLOY_KEY_SECRET, privateKey);
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
await (0, promises_1.rm)(dir, { recursive: true, force: true });
|
|
129
|
+
}
|
|
130
|
+
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`);
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* removes the aggregate check from a classic branch protection rule
|
|
134
|
+
* set up by earlier catladder versions — with the check now required
|
|
135
|
+
* via the ruleset, the classic one would still reject the release
|
|
136
|
+
* job's push. Everything else in the rule is preserved; the whole rule
|
|
137
|
+
* is deleted when the check was all it carried.
|
|
138
|
+
*/
|
|
139
|
+
const migrateAwayFromClassicProtection = async (instance, repo, branch) => {
|
|
140
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
|
|
141
|
+
const protection = await (0, github_1.ghApiJson)("GET", `repos/${repo}/branches/${branch}/protection`).catch(() => null); // 404: branch not protected
|
|
142
|
+
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 : [];
|
|
143
|
+
if (!checks.some((c) => c.context === pipeline_1.AGGREGATE_CHECK_JOB_NAME)) {
|
|
54
144
|
return;
|
|
55
145
|
}
|
|
56
|
-
|
|
57
|
-
|
|
146
|
+
const remaining = checks.filter((c) => c.context !== pipeline_1.AGGREGATE_CHECK_JOB_NAME);
|
|
147
|
+
const carriesAnythingElse = remaining.length > 0 ||
|
|
148
|
+
((_c = protection === null || protection === void 0 ? void 0 : protection.enforce_admins) === null || _c === void 0 ? void 0 : _c.enabled) ||
|
|
149
|
+
(protection === null || protection === void 0 ? void 0 : protection.required_pull_request_reviews) ||
|
|
150
|
+
(protection === null || protection === void 0 ? void 0 : protection.restrictions) ||
|
|
151
|
+
((_d = protection === null || protection === void 0 ? void 0 : protection.required_linear_history) === null || _d === void 0 ? void 0 : _d.enabled) ||
|
|
152
|
+
((_e = protection === null || protection === void 0 ? void 0 : protection.required_conversation_resolution) === null || _e === void 0 ? void 0 : _e.enabled) ||
|
|
153
|
+
((_f = protection === null || protection === void 0 ? void 0 : protection.required_signatures) === null || _f === void 0 ? void 0 : _f.enabled) ||
|
|
154
|
+
((_g = protection === null || protection === void 0 ? void 0 : protection.lock_branch) === null || _g === void 0 ? void 0 : _g.enabled) ||
|
|
155
|
+
((_h = protection === null || protection === void 0 ? void 0 : protection.allow_force_pushes) === null || _h === void 0 ? void 0 : _h.enabled) ||
|
|
156
|
+
((_j = protection === null || protection === void 0 ? void 0 : protection.allow_deletions) === null || _j === void 0 ? void 0 : _j.enabled);
|
|
157
|
+
if (!carriesAnythingElse) {
|
|
158
|
+
await (0, github_1.ghApiJson)("DELETE", `repos/${repo}/branches/${branch}/protection`);
|
|
159
|
+
instance.log(`✅ classic branch protection on ${branch} removed — '${pipeline_1.AGGREGATE_CHECK_JOB_NAME}' was all it carried, and it is now required via the ruleset`);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// PUT replaces the whole rule, so every preserved setting must be
|
|
163
|
+
// carried over explicitly
|
|
58
164
|
await (0, github_1.ghApiJson)("PUT", `repos/${repo}/branches/${branch}/protection`, {
|
|
59
|
-
required_status_checks:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
165
|
+
required_status_checks: remaining.length > 0
|
|
166
|
+
? {
|
|
167
|
+
strict: (_l = (_k = protection === null || protection === void 0 ? void 0 : protection.required_status_checks) === null || _k === void 0 ? void 0 : _k.strict) !== null && _l !== void 0 ? _l : false,
|
|
168
|
+
checks: remaining.map(({ context, app_id }) => ({
|
|
63
169
|
context,
|
|
64
170
|
...(app_id !== undefined ? { app_id } : {}),
|
|
65
171
|
})),
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
enforce_admins: (_f = (_e = protection === null || protection === void 0 ? void 0 : protection.enforce_admins) === null || _e === void 0 ? void 0 : _e.enabled) !== null && _f !== void 0 ? _f : false,
|
|
172
|
+
}
|
|
173
|
+
: null,
|
|
174
|
+
enforce_admins: (_o = (_m = protection === null || protection === void 0 ? void 0 : protection.enforce_admins) === null || _m === void 0 ? void 0 : _m.enabled) !== null && _o !== void 0 ? _o : false,
|
|
70
175
|
required_pull_request_reviews: (protection === null || protection === void 0 ? void 0 : protection.required_pull_request_reviews)
|
|
71
176
|
? {
|
|
72
|
-
required_approving_review_count: (
|
|
73
|
-
.required_approving_review_count) !== null &&
|
|
74
|
-
dismiss_stale_reviews: (
|
|
75
|
-
require_code_owner_reviews: (
|
|
76
|
-
.require_code_owner_reviews) !== null &&
|
|
177
|
+
required_approving_review_count: (_p = protection.required_pull_request_reviews
|
|
178
|
+
.required_approving_review_count) !== null && _p !== void 0 ? _p : 0,
|
|
179
|
+
dismiss_stale_reviews: (_q = protection.required_pull_request_reviews.dismiss_stale_reviews) !== null && _q !== void 0 ? _q : false,
|
|
180
|
+
require_code_owner_reviews: (_r = protection.required_pull_request_reviews
|
|
181
|
+
.require_code_owner_reviews) !== null && _r !== void 0 ? _r : false,
|
|
77
182
|
}
|
|
78
183
|
: null,
|
|
79
184
|
restrictions: (protection === null || protection === void 0 ? void 0 : protection.restrictions)
|
|
@@ -83,10 +188,12 @@ const setupGithub = async (instance, config) => {
|
|
|
83
188
|
apps: protection.restrictions.apps.map((a) => a.slug),
|
|
84
189
|
}
|
|
85
190
|
: null,
|
|
86
|
-
|
|
87
|
-
|
|
191
|
+
required_linear_history: (_t = (_s = protection === null || protection === void 0 ? void 0 : protection.required_linear_history) === null || _s === void 0 ? void 0 : _s.enabled) !== null && _t !== void 0 ? _t : false,
|
|
192
|
+
required_conversation_resolution: (_v = (_u = protection === null || protection === void 0 ? void 0 : protection.required_conversation_resolution) === null || _u === void 0 ? void 0 : _u.enabled) !== null && _v !== void 0 ? _v : false,
|
|
193
|
+
lock_branch: (_x = (_w = protection === null || protection === void 0 ? void 0 : protection.lock_branch) === null || _w === void 0 ? void 0 : _w.enabled) !== null && _x !== void 0 ? _x : false,
|
|
194
|
+
allow_force_pushes: (_z = (_y = protection === null || protection === void 0 ? void 0 : protection.allow_force_pushes) === null || _y === void 0 ? void 0 : _y.enabled) !== null && _z !== void 0 ? _z : false,
|
|
195
|
+
allow_deletions: (_1 = (_0 = protection === null || protection === void 0 ? void 0 : protection.allow_deletions) === null || _0 === void 0 ? void 0 : _0.enabled) !== null && _1 !== void 0 ? _1 : false,
|
|
88
196
|
});
|
|
89
|
-
instance.log(`✅ branch protection on ${branch}
|
|
197
|
+
instance.log(`✅ '${pipeline_1.AGGREGATE_CHECK_JOB_NAME}' removed from classic branch protection on ${branch} — now required via the ruleset; the rest of the rule is preserved`);
|
|
90
198
|
};
|
|
91
|
-
exports.setupGithub = setupGithub;
|
|
92
199
|
//# sourceMappingURL=setupGithub.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupGithub.js","sourceRoot":"","sources":["../../../../../../../../../src/apps/cli/commands/project/setup/setupGithub.ts"],"names":[],"mappings":";;;AACA,kDAI6B;AAC7B,uGAAmG;AAEnG,
|
|
1
|
+
{"version":3,"file":"setupGithub.js","sourceRoot":"","sources":["../../../../../../../../../src/apps/cli/commands/project/setup/setupGithub.ts"],"names":[],"mappings":";;;AACA,kDAI6B;AAC7B,iDAAuD;AACvD,0CAAoD;AACpD,2BAA4B;AAC5B,+BAA4B;AAC5B,+BAAiC;AACjC,uGAAmG;AAEnG,wDAKqC;AAErC,4DAM8B;AAE9B,MAAM,QAAQ,GAAG,IAAA,gBAAS,EAAC,wBAAU,CAAC,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACI,MAAM,WAAW,GAAG,KAAK,EAAE,QAAY,EAAE,MAAc,EAAE,EAAE;IAChE,IAAI,CAAC,IAAA,kCAAuB,EAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxD,OAAO;IACT,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,IAAA,0BAAiB,GAAE,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,GAAG,CACV,gGAAgG,CACjG,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,IAAA,kDAAuB,GAAE,CAAC;IAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,QAAQ,CAAC,GAAG,CACV,yCAAyC,IAAA,+BAAoB,EAAC,MAAM,EAAE,QAAQ,CAAC,+CAA+C,CAC/H,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,IAAA,kBAAS,EAI7B,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC;IAE3B,IAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,sBAAsB,EAAE,CAAC;QACnE,MAAM,IAAA,kBAAS,EAAC,OAAO,EAAE,SAAS,IAAI,EAAE,EAAE;YACxC,gBAAgB,EAAE,IAAI;YACtB,sBAAsB,EAAE,IAAI;SAC7B,CAAC,CAAC;QACH,QAAQ,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAChE,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC;IACvC,MAAM,QAAQ,GAAG,MAAM,IAAA,kBAAS,EAC9B,KAAK,EACL,SAAS,IAAI,wBAAwB,CACtC,CAAC;IACF,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,6CAAyB,CAAC,CAAC;IAC5E,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAA,kBAAS,EACb,MAAM,EACN,SAAS,IAAI,WAAW,EACxB,IAAA,6CAAyB,GAAE,CAC5B,CAAC;QACF,QAAQ,CAAC,GAAG,CACV,cAAc,6CAAyB,OAAO,mCAAwB,iBAAiB,MAAM,2DAA2D,CACzJ,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,MAAM,IAAA,kBAAS,EAC5B,KAAK,EACL,SAAS,IAAI,aAAa,QAAQ,CAAC,EAAE,EAAE,CACxC,CAAC;QACF,IAAI,IAAA,8CAA0B,EAAC,MAAM,CAAC,EAAE,CAAC;YACvC,QAAQ,CAAC,GAAG,CACV,cAAc,6CAAyB,yBAAyB,MAAM,EAAE,CACzE,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,IAAA,kBAAS,EACb,KAAK,EACL,SAAS,IAAI,aAAa,QAAQ,CAAC,EAAE,EAAE,EACvC,IAAA,6CAAyB,GAAE,CAC5B,CAAC;YACF,QAAQ,CAAC,GAAG,CACV,cAAc,6CAAyB,iBAAiB,mCAAwB,yCAAyC,CAC1H,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,gCAAgC,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AACjE,CAAC,CAAC;AAzEW,QAAA,WAAW,eAyEtB;AAEF;;;;;;;GAOG;AACH,MAAM,sBAAsB,GAAG,KAAK,EAAE,QAAY,EAAE,IAAY,EAAE,EAAE;IAClE,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC5C,IAAA,kBAAS,EACP,KAAK,EACL,SAAS,IAAI,oBAAoB,CAClC;QACD,IAAA,8BAAqB,EAAC,IAAI,CAAC;KAC5B,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,4CAAwB,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAChC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,6CAAyB,CAC3D,CAAC;IACF,IAAI,WAAW,IAAI,CAAC,WAAW,CAAC,SAAS,IAAI,SAAS,EAAE,CAAC;QACvD,QAAQ,CAAC,GAAG,CACV,yBAAyB,4CAAwB,cAAc,6CAAyB,WAAW,CACpG,CAAC;QACF,OAAO;IACT,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,IAAA,kBAAS,EAAC,QAAQ,EAAE,SAAS,IAAI,SAAS,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;QAClE,QAAQ,CAAC,GAAG,CACV,0BAA0B,4CAAwB,cAChD,WAAW,CAAC,SAAS;YACnB,CAAC,CAAC,eAAe;YACjB,CAAC,CAAC,UAAU,6CAAyB,UACzC,GAAG,CACJ,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,IAAA,kBAAO,EAAC,IAAA,WAAI,EAAC,IAAA,WAAM,GAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;IACpE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAA,WAAI,EAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACxC,MAAM,QAAQ,CAAC,YAAY,EAAE;YAC3B,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC;YACpB,GAAG,CAAC,IAAI,EAAE,GAAG,4CAAwB,KAAK,IAAI,GAAG,CAAC;YAClD,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YACb,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC;YAClB,IAAI;SACL,CAAC,CAAC;QACH,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAChD,IAAA,mBAAQ,EAAC,OAAO,EAAE,OAAO,CAAC;YAC1B,IAAA,mBAAQ,EAAC,GAAG,OAAO,MAAM,EAAE,OAAO,CAAC;SACpC,CAAC,CAAC;QACH,MAAM,IAAA,kBAAS,EAAC,MAAM,EAAE,SAAS,IAAI,OAAO,EAAE;YAC5C,KAAK,EAAE,4CAAwB;YAC/B,GAAG,EAAE,SAAS,CAAC,IAAI,EAAE;YACrB,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;QACH,MAAM,IAAA,wBAAe,EAAC,IAAI,EAAE,6CAAyB,EAAE,UAAU,CAAC,CAAC;IACrE,CAAC;YAAS,CAAC;QACT,MAAM,IAAA,aAAE,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,QAAQ,CAAC,GAAG,CACV,yBAAyB,4CAAwB,+CAA+C,6CAAyB,mCAAmC,CAC7J,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,gCAAgC,GAAG,KAAK,EAC5C,QAAY,EACZ,IAAY,EACZ,MAAc,EACd,EAAE;;IACF,MAAM,UAAU,GAAG,MAAM,IAAA,kBAAS,EAChC,KAAK,EACL,SAAS,IAAI,aAAa,MAAM,aAAa,CAC9C,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,4BAA4B;IACjD,MAAM,MAAM,GACV,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,sBAAsB,0CAAE,MAAM,mCAAI,EAAE,CAAC;IACnD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,mCAAwB,CAAC,EAAE,CAAC;QAChE,OAAO;IACT,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,mCAAwB,CAC9C,CAAC;IACF,MAAM,mBAAmB,GACvB,SAAS,CAAC,MAAM,GAAG,CAAC;SACpB,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,cAAc,0CAAE,OAAO,CAAA;SACnC,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,6BAA6B,CAAA;SACzC,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,YAAY,CAAA;SACxB,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,uBAAuB,0CAAE,OAAO,CAAA;SAC5C,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,gCAAgC,0CAAE,OAAO,CAAA;SACrD,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,mBAAmB,0CAAE,OAAO,CAAA;SACxC,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,WAAW,0CAAE,OAAO,CAAA;SAChC,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,kBAAkB,0CAAE,OAAO,CAAA;SACvC,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,eAAe,0CAAE,OAAO,CAAA,CAAC;IACvC,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,MAAM,IAAA,kBAAS,EAAC,QAAQ,EAAE,SAAS,IAAI,aAAa,MAAM,aAAa,CAAC,CAAC;QACzE,QAAQ,CAAC,GAAG,CACV,kCAAkC,MAAM,eAAe,mCAAwB,8DAA8D,CAC9I,CAAC;QACF,OAAO;IACT,CAAC;IACD,kEAAkE;IAClE,0BAA0B;IAC1B,MAAM,IAAA,kBAAS,EAAC,KAAK,EAAE,SAAS,IAAI,aAAa,MAAM,aAAa,EAAE;QACpE,sBAAsB,EACpB,SAAS,CAAC,MAAM,GAAG,CAAC;YAClB,CAAC,CAAC;gBACE,MAAM,EAAE,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,sBAAsB,0CAAE,MAAM,mCAAI,KAAK;gBAC3D,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;oBAC9C,OAAO;oBACP,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC5C,CAAC,CAAC;aACJ;YACH,CAAC,CAAC,IAAI;QACV,cAAc,EAAE,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,cAAc,0CAAE,OAAO,mCAAI,KAAK;QAC5D,6BAA6B,EAAE,CAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,6BAA6B;YACtE,CAAC,CAAC;gBACE,+BAA+B,EAC7B,MAAA,UAAU,CAAC,6BAA6B;qBACrC,+BAA+B,mCAAI,CAAC;gBACzC,qBAAqB,EACnB,MAAA,UAAU,CAAC,6BAA6B,CAAC,qBAAqB,mCAC9D,KAAK;gBACP,0BAA0B,EACxB,MAAA,UAAU,CAAC,6BAA6B;qBACrC,0BAA0B,mCAAI,KAAK;aACzC;YACH,CAAC,CAAC,IAAI;QACR,YAAY,EAAE,CAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,YAAY;YACpC,CAAC,CAAC;gBACE,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;gBAC7D,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC5D,IAAI,EAAE,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAC3D;YACH,CAAC,CAAC,IAAI;QACR,uBAAuB,EACrB,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,uBAAuB,0CAAE,OAAO,mCAAI,KAAK;QACvD,gCAAgC,EAC9B,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,gCAAgC,0CAAE,OAAO,mCAAI,KAAK;QAChE,WAAW,EAAE,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,WAAW,0CAAE,OAAO,mCAAI,KAAK;QACtD,kBAAkB,EAAE,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,kBAAkB,0CAAE,OAAO,mCAAI,KAAK;QACpE,eAAe,EAAE,MAAA,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,eAAe,0CAAE,OAAO,mCAAI,KAAK;KAC/D,CAAC,CAAC;IACH,QAAQ,CAAC,GAAG,CACV,MAAM,mCAAwB,+CAA+C,MAAM,oEAAoE,CACxJ,CAAC;AACJ,CAAC,CAAC"}
|