@catladder/cli 0.0.0-fix-changeset-hint-package-manager-20002c27 → 0.0.0-fix-github-gating-release-push-fbb576dc
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 +31 -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 +70 -0
- package/dist/apps/cli/src/apps/cli/commands/project/githubMergeGating.js +71 -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/setupGithub.d.ts +9 -7
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupGithub.js +77 -31
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupGithub.js.map +1 -1
- package/dist/apps/cli/src/release/changesetsReleaseJob.js +19 -1
- package/dist/apps/cli/src/release/changesetsReleaseJob.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 +1 -1
- package/dist/bundles/catenv/index.js +200 -8
- package/dist/bundles/cli/index.js +386 -48
- package/dist/bundles/skills/catladder-deploys/references/deploy-types.md +1 -0
- package/dist/bundles/skills/catladder-migrate-ci-backend/SKILL.md +11 -7
- package/dist/packages/pipeline/src/deploy/cloudRun/index.js +6 -1
- package/dist/packages/pipeline/src/deploy/cloudRun/index.js.map +1 -1
- package/dist/packages/pipeline/src/deploy/cloudRun/utils/getServiceName.d.ts +68 -0
- package/dist/packages/pipeline/src/deploy/cloudRun/utils/getServiceName.js +184 -3
- package/dist/packages/pipeline/src/deploy/cloudRun/utils/getServiceName.js.map +1 -1
- package/dist/packages/pipeline/src/store/index.d.ts +8 -0
- package/dist/packages/pipeline/src/store/index.js +9 -3
- package/dist/packages/pipeline/src/store/index.js.map +1 -1
- package/dist/skills/catladder-deploys/references/deploy-types.md +1 -0
- 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 +112 -0
- package/src/apps/cli/commands/project/doctor/checkGithub.ts +44 -8
- package/src/apps/cli/commands/project/githubMergeGating.ts +90 -0
- package/src/apps/cli/commands/project/setup/setupGithub.ts +105 -26
- package/src/release/changesetsReleaseJob.ts +19 -1
- package/src/utils/github.ts +1 -1
|
@@ -619,6 +619,7 @@ const pipeline_1 = __nccwpck_require__(53695);
|
|
|
619
619
|
const commandSecretsSyncGithub_1 = __nccwpck_require__(27565);
|
|
620
620
|
const concurrency_1 = __nccwpck_require__(59723);
|
|
621
621
|
const github_1 = __nccwpck_require__(41353);
|
|
622
|
+
const githubMergeGating_1 = __nccwpck_require__(14966);
|
|
622
623
|
/** marker for repo-level (environment-less) targets, see collectSecretTargets */
|
|
623
624
|
const REPO_LEVEL = "";
|
|
624
625
|
/**
|
|
@@ -722,10 +723,13 @@ const checkGithub = async (report, config) => {
|
|
|
722
723
|
exports.checkGithub = checkGithub;
|
|
723
724
|
/**
|
|
724
725
|
* verifies the merge gating `project setup` configures: auto-merge
|
|
725
|
-
* enabled and the
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
*
|
|
726
|
+
* enabled and the `catladder merge gating` ruleset requiring the
|
|
727
|
+
* generated `catladder ✅` aggregate check on the default branch (with
|
|
728
|
+
* the bypass that lets the release job push). Without the check a PR
|
|
729
|
+
* is mergeable while its checks are still running — gitlab ships this
|
|
730
|
+
* behavior built-in, github silently does not. The check required via
|
|
731
|
+
* classic branch protection instead is flagged: that setup rejects the
|
|
732
|
+
* release job's own push (GH006).
|
|
729
733
|
*/
|
|
730
734
|
const checkGithubMergeGating = async (report, repo) => {
|
|
731
735
|
var _a, _b;
|
|
@@ -744,17 +748,35 @@ const checkGithubMergeGating = async (report, repo) => {
|
|
|
744
748
|
report.fail("auto-merge disabled — the merge-when-pipeline-succeeds button cannot appear", "run: catladder project setup");
|
|
745
749
|
}
|
|
746
750
|
const branch = repoInfo.default_branch;
|
|
751
|
+
let rulesets;
|
|
752
|
+
try {
|
|
753
|
+
rulesets = await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets?per_page=100`);
|
|
754
|
+
}
|
|
755
|
+
catch (e) {
|
|
756
|
+
report.warn(`could not list rulesets of ${repo} (${e.message})`);
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
const named = rulesets.find((r) => r.name === githubMergeGating_1.MERGE_GATING_RULESET_NAME);
|
|
760
|
+
const ruleset = named
|
|
761
|
+
? await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets/${named.id}`).catch(() => null)
|
|
762
|
+
: null;
|
|
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}, release job can push`);
|
|
765
|
+
}
|
|
766
|
+
else if (ruleset) {
|
|
767
|
+
report.fail(`ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}' exists but is incomplete (inactive, check not required, or release-job bypass missing)`, "run: catladder project setup");
|
|
768
|
+
}
|
|
769
|
+
else {
|
|
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
|
+
}
|
|
747
772
|
const protection = await (0, github_1.ghApiJson)("GET", `repos/${repo}/branches/${branch}/protection`).catch(() => null);
|
|
748
773
|
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 : [];
|
|
749
774
|
if (checks.some((c) => c.context === pipeline_1.AGGREGATE_CHECK_JOB_NAME)) {
|
|
750
|
-
report.
|
|
751
|
-
}
|
|
752
|
-
else {
|
|
753
|
-
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");
|
|
775
|
+
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");
|
|
754
776
|
}
|
|
755
777
|
const stale = checks.filter((c) => c.context !== pipeline_1.AGGREGATE_CHECK_JOB_NAME);
|
|
756
778
|
if (stale.length > 0) {
|
|
757
|
-
report.warn(`${branch} requires ${stale.length} additional named check(s) (${stale
|
|
779
|
+
report.warn(`${branch} requires ${stale.length} additional named check(s) via classic branch protection (${stale
|
|
758
780
|
.map((c) => c.context)
|
|
759
781
|
.join(", ")}) — job names change with components; prefer only '${pipeline_1.AGGREGATE_CHECK_JOB_NAME}'`);
|
|
760
782
|
}
|
|
@@ -950,6 +972,84 @@ exports.doctorProject = doctorProject;
|
|
|
950
972
|
|
|
951
973
|
/***/ }),
|
|
952
974
|
|
|
975
|
+
/***/ 14966:
|
|
976
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
977
|
+
|
|
978
|
+
"use strict";
|
|
979
|
+
|
|
980
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
981
|
+
exports.rulesetProvidesMergeGating = exports.desiredMergeGatingRuleset = exports.MERGE_GATING_RULESET_NAME = exports.GITHUB_ACTIONS_APP_ID = void 0;
|
|
982
|
+
const pipeline_1 = __nccwpck_require__(53695);
|
|
983
|
+
/**
|
|
984
|
+
* github merge gating — shared between `project setup` (writes it) and
|
|
985
|
+
* `project doctor` (verifies it).
|
|
986
|
+
*
|
|
987
|
+
* The gating lives in a repository RULESET, not classic branch
|
|
988
|
+
* protection: only rulesets can carry bypass actors, and the release
|
|
989
|
+
* job needs one. It pushes the release commit and tag straight to the
|
|
990
|
+
* default branch with the workflow token — under classic protection
|
|
991
|
+
* the required `catladder ✅` check rejects that push (GH006), because
|
|
992
|
+
* the fresh release commit cannot have a passing check yet. The bypass
|
|
993
|
+
* covers the GitHub Actions app, i.e. pushes made by workflows, while
|
|
994
|
+
* PRs and humans stay gated. (Gitlab's counterpart is the
|
|
995
|
+
* maintainer-role project access token, which may push to protected
|
|
996
|
+
* branches by default — the same trade-off, made by the platform.)
|
|
997
|
+
*/
|
|
998
|
+
/** the app id of GitHub Actions — the actor workflow tokens act as */
|
|
999
|
+
exports.GITHUB_ACTIONS_APP_ID = 15368;
|
|
1000
|
+
exports.MERGE_GATING_RULESET_NAME = "catladder merge gating";
|
|
1001
|
+
/** the ruleset `project setup` creates (and restores on drift) */
|
|
1002
|
+
const desiredMergeGatingRuleset = () => ({
|
|
1003
|
+
name: exports.MERGE_GATING_RULESET_NAME,
|
|
1004
|
+
target: "branch",
|
|
1005
|
+
enforcement: "active",
|
|
1006
|
+
conditions: { ref_name: { include: ["~DEFAULT_BRANCH"], exclude: [] } },
|
|
1007
|
+
rules: [
|
|
1008
|
+
{
|
|
1009
|
+
type: "required_status_checks",
|
|
1010
|
+
parameters: {
|
|
1011
|
+
strict_required_status_checks_policy: false,
|
|
1012
|
+
do_not_enforce_on_create: false,
|
|
1013
|
+
required_status_checks: [
|
|
1014
|
+
{
|
|
1015
|
+
context: pipeline_1.AGGREGATE_CHECK_JOB_NAME,
|
|
1016
|
+
integration_id: exports.GITHUB_ACTIONS_APP_ID,
|
|
1017
|
+
},
|
|
1018
|
+
],
|
|
1019
|
+
},
|
|
1020
|
+
},
|
|
1021
|
+
],
|
|
1022
|
+
bypass_actors: [
|
|
1023
|
+
{
|
|
1024
|
+
actor_id: exports.GITHUB_ACTIONS_APP_ID,
|
|
1025
|
+
actor_type: "Integration",
|
|
1026
|
+
bypass_mode: "always",
|
|
1027
|
+
},
|
|
1028
|
+
],
|
|
1029
|
+
});
|
|
1030
|
+
exports.desiredMergeGatingRuleset = desiredMergeGatingRuleset;
|
|
1031
|
+
/**
|
|
1032
|
+
* whether a ruleset provides working merge gating: active, requires
|
|
1033
|
+
* the aggregate check, and lets the release job (GitHub Actions app)
|
|
1034
|
+
* bypass it. Extra rules or bypass actors someone added are fine.
|
|
1035
|
+
*/
|
|
1036
|
+
const rulesetProvidesMergeGating = (ruleset) => {
|
|
1037
|
+
var _a, _b;
|
|
1038
|
+
return ruleset.enforcement === "active" &&
|
|
1039
|
+
((_a = ruleset.rules) !== null && _a !== void 0 ? _a : []).some((rule) => {
|
|
1040
|
+
var _a, _b;
|
|
1041
|
+
return rule.type === "required_status_checks" &&
|
|
1042
|
+
((_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
|
+
}) &&
|
|
1044
|
+
((_b = ruleset.bypass_actors) !== null && _b !== void 0 ? _b : []).some((actor) => actor.actor_type === "Integration" &&
|
|
1045
|
+
actor.actor_id === exports.GITHUB_ACTIONS_APP_ID &&
|
|
1046
|
+
actor.bypass_mode === "always");
|
|
1047
|
+
};
|
|
1048
|
+
exports.rulesetProvidesMergeGating = rulesetProvidesMergeGating;
|
|
1049
|
+
//# sourceMappingURL=githubMergeGating.js.map
|
|
1050
|
+
|
|
1051
|
+
/***/ }),
|
|
1052
|
+
|
|
953
1053
|
/***/ 2231:
|
|
954
1054
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
955
1055
|
|
|
@@ -1436,6 +1536,7 @@ exports.setupGithub = void 0;
|
|
|
1436
1536
|
const pipeline_1 = __nccwpck_require__(53695);
|
|
1437
1537
|
const commandSecretsSyncGithub_1 = __nccwpck_require__(27565);
|
|
1438
1538
|
const github_1 = __nccwpck_require__(41353);
|
|
1539
|
+
const githubMergeGating_1 = __nccwpck_require__(14966);
|
|
1439
1540
|
/**
|
|
1440
1541
|
* configures github merge gating — the sane default gitlab ships
|
|
1441
1542
|
* built-in and a fresh github repository lacks entirely: without it a
|
|
@@ -1443,18 +1544,19 @@ const github_1 = __nccwpck_require__(41353);
|
|
|
1443
1544
|
* auto-merge button never appears.
|
|
1444
1545
|
*
|
|
1445
1546
|
* - repo settings: allow auto-merge, delete merged head branches
|
|
1446
|
-
* -
|
|
1547
|
+
* - a repository ruleset on the default branch requiring the generated
|
|
1447
1548
|
* `catladder ✅` aggregate check (the one stable context — individual
|
|
1448
|
-
* job names change with every component add/rename)
|
|
1549
|
+
* job names change with every component add/rename), with a bypass
|
|
1550
|
+
* for the GitHub Actions app so the release job can push the release
|
|
1551
|
+
* commit and tag (see githubMergeGating.ts for the full rationale)
|
|
1449
1552
|
*
|
|
1450
|
-
*
|
|
1451
|
-
*
|
|
1452
|
-
*
|
|
1453
|
-
*
|
|
1454
|
-
*
|
|
1553
|
+
* Earlier versions required the check via classic branch protection,
|
|
1554
|
+
* which has no bypass list — the release job's direct push to the
|
|
1555
|
+
* default branch bounced off catladder's own gating (GH006). Setup
|
|
1556
|
+
* migrates that away: the aggregate context is removed from an
|
|
1557
|
+
* existing classic rule, everything else in it is preserved.
|
|
1455
1558
|
*/
|
|
1456
1559
|
const setupGithub = async (instance, config) => {
|
|
1457
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
1458
1560
|
if (!(0, pipeline_1.getEnabledPipelineTypes)(config).includes("github")) {
|
|
1459
1561
|
return;
|
|
1460
1562
|
}
|
|
@@ -1479,33 +1581,75 @@ const setupGithub = async (instance, config) => {
|
|
|
1479
1581
|
instance.log("✅ auto-merge already enabled");
|
|
1480
1582
|
}
|
|
1481
1583
|
const branch = repoInfo.default_branch;
|
|
1482
|
-
const
|
|
1483
|
-
const
|
|
1484
|
-
if (
|
|
1485
|
-
|
|
1584
|
+
const rulesets = await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets?per_page=100`);
|
|
1585
|
+
const existing = rulesets.find((r) => r.name === githubMergeGating_1.MERGE_GATING_RULESET_NAME);
|
|
1586
|
+
if (!existing) {
|
|
1587
|
+
await (0, github_1.ghApiJson)("POST", `repos/${repo}/rulesets`, (0, githubMergeGating_1.desiredMergeGatingRuleset)());
|
|
1588
|
+
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`);
|
|
1589
|
+
}
|
|
1590
|
+
else {
|
|
1591
|
+
const detail = await (0, github_1.ghApiJson)("GET", `repos/${repo}/rulesets/${existing.id}`);
|
|
1592
|
+
if ((0, githubMergeGating_1.rulesetProvidesMergeGating)(detail)) {
|
|
1593
|
+
instance.log(`✅ ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}' already in place on ${branch}`);
|
|
1594
|
+
}
|
|
1595
|
+
else {
|
|
1596
|
+
await (0, github_1.ghApiJson)("PUT", `repos/${repo}/rulesets/${existing.id}`, (0, githubMergeGating_1.desiredMergeGatingRuleset)());
|
|
1597
|
+
instance.log(`✅ ruleset '${githubMergeGating_1.MERGE_GATING_RULESET_NAME}' restored — '${pipeline_1.AGGREGATE_CHECK_JOB_NAME}' required, release-job bypass in place`);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
await migrateAwayFromClassicProtection(instance, repo, branch);
|
|
1601
|
+
};
|
|
1602
|
+
exports.setupGithub = setupGithub;
|
|
1603
|
+
/**
|
|
1604
|
+
* removes the aggregate check from a classic branch protection rule
|
|
1605
|
+
* set up by earlier catladder versions — with the check now required
|
|
1606
|
+
* via the ruleset, the classic one would still reject the release
|
|
1607
|
+
* job's push. Everything else in the rule is preserved; the whole rule
|
|
1608
|
+
* is deleted when the check was all it carried.
|
|
1609
|
+
*/
|
|
1610
|
+
const migrateAwayFromClassicProtection = async (instance, repo, branch) => {
|
|
1611
|
+
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;
|
|
1612
|
+
const protection = await (0, github_1.ghApiJson)("GET", `repos/${repo}/branches/${branch}/protection`).catch(() => null); // 404: branch not protected
|
|
1613
|
+
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 : [];
|
|
1614
|
+
if (!checks.some((c) => c.context === pipeline_1.AGGREGATE_CHECK_JOB_NAME)) {
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1617
|
+
const remaining = checks.filter((c) => c.context !== pipeline_1.AGGREGATE_CHECK_JOB_NAME);
|
|
1618
|
+
const carriesAnythingElse = remaining.length > 0 ||
|
|
1619
|
+
((_c = protection === null || protection === void 0 ? void 0 : protection.enforce_admins) === null || _c === void 0 ? void 0 : _c.enabled) ||
|
|
1620
|
+
(protection === null || protection === void 0 ? void 0 : protection.required_pull_request_reviews) ||
|
|
1621
|
+
(protection === null || protection === void 0 ? void 0 : protection.restrictions) ||
|
|
1622
|
+
((_d = protection === null || protection === void 0 ? void 0 : protection.required_linear_history) === null || _d === void 0 ? void 0 : _d.enabled) ||
|
|
1623
|
+
((_e = protection === null || protection === void 0 ? void 0 : protection.required_conversation_resolution) === null || _e === void 0 ? void 0 : _e.enabled) ||
|
|
1624
|
+
((_f = protection === null || protection === void 0 ? void 0 : protection.required_signatures) === null || _f === void 0 ? void 0 : _f.enabled) ||
|
|
1625
|
+
((_g = protection === null || protection === void 0 ? void 0 : protection.lock_branch) === null || _g === void 0 ? void 0 : _g.enabled) ||
|
|
1626
|
+
((_h = protection === null || protection === void 0 ? void 0 : protection.allow_force_pushes) === null || _h === void 0 ? void 0 : _h.enabled) ||
|
|
1627
|
+
((_j = protection === null || protection === void 0 ? void 0 : protection.allow_deletions) === null || _j === void 0 ? void 0 : _j.enabled);
|
|
1628
|
+
if (!carriesAnythingElse) {
|
|
1629
|
+
await (0, github_1.ghApiJson)("DELETE", `repos/${repo}/branches/${branch}/protection`);
|
|
1630
|
+
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`);
|
|
1486
1631
|
return;
|
|
1487
1632
|
}
|
|
1488
|
-
//
|
|
1489
|
-
//
|
|
1633
|
+
// PUT replaces the whole rule, so every preserved setting must be
|
|
1634
|
+
// carried over explicitly
|
|
1490
1635
|
await (0, github_1.ghApiJson)("PUT", `repos/${repo}/branches/${branch}/protection`, {
|
|
1491
|
-
required_status_checks:
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1636
|
+
required_status_checks: remaining.length > 0
|
|
1637
|
+
? {
|
|
1638
|
+
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,
|
|
1639
|
+
checks: remaining.map(({ context, app_id }) => ({
|
|
1495
1640
|
context,
|
|
1496
1641
|
...(app_id !== undefined ? { app_id } : {}),
|
|
1497
1642
|
})),
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
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,
|
|
1643
|
+
}
|
|
1644
|
+
: null,
|
|
1645
|
+
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,
|
|
1502
1646
|
required_pull_request_reviews: (protection === null || protection === void 0 ? void 0 : protection.required_pull_request_reviews)
|
|
1503
1647
|
? {
|
|
1504
|
-
required_approving_review_count: (
|
|
1505
|
-
.required_approving_review_count) !== null &&
|
|
1506
|
-
dismiss_stale_reviews: (
|
|
1507
|
-
require_code_owner_reviews: (
|
|
1508
|
-
.require_code_owner_reviews) !== null &&
|
|
1648
|
+
required_approving_review_count: (_p = protection.required_pull_request_reviews
|
|
1649
|
+
.required_approving_review_count) !== null && _p !== void 0 ? _p : 0,
|
|
1650
|
+
dismiss_stale_reviews: (_q = protection.required_pull_request_reviews.dismiss_stale_reviews) !== null && _q !== void 0 ? _q : false,
|
|
1651
|
+
require_code_owner_reviews: (_r = protection.required_pull_request_reviews
|
|
1652
|
+
.require_code_owner_reviews) !== null && _r !== void 0 ? _r : false,
|
|
1509
1653
|
}
|
|
1510
1654
|
: null,
|
|
1511
1655
|
restrictions: (protection === null || protection === void 0 ? void 0 : protection.restrictions)
|
|
@@ -1515,12 +1659,14 @@ const setupGithub = async (instance, config) => {
|
|
|
1515
1659
|
apps: protection.restrictions.apps.map((a) => a.slug),
|
|
1516
1660
|
}
|
|
1517
1661
|
: null,
|
|
1518
|
-
|
|
1519
|
-
|
|
1662
|
+
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,
|
|
1663
|
+
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,
|
|
1664
|
+
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,
|
|
1665
|
+
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,
|
|
1666
|
+
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,
|
|
1520
1667
|
});
|
|
1521
|
-
instance.log(`✅ branch protection on ${branch}
|
|
1668
|
+
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`);
|
|
1522
1669
|
};
|
|
1523
|
-
exports.setupGithub = setupGithub;
|
|
1524
1670
|
//# sourceMappingURL=setupGithub.js.map
|
|
1525
1671
|
|
|
1526
1672
|
/***/ }),
|
|
@@ -15564,9 +15710,14 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
|
|
|
15564
15710
|
// generation time. For review envs the service name part still
|
|
15565
15711
|
// contains a runtime expression (the review slug), so the host stays
|
|
15566
15712
|
// a bash expression there; the suffix is always a literal.
|
|
15713
|
+
//
|
|
15714
|
+
// The service name has to come from getRawServiceNameForEnvContext,
|
|
15715
|
+
// not from fullName: it is shortened when the label would otherwise
|
|
15716
|
+
// exceed what cloud run serves deterministically, and the url must
|
|
15717
|
+
// name the service that is actually deployed.
|
|
15567
15718
|
const HOSTNAME_INTERNAL = deployConfigRaw && envType !== "local"
|
|
15568
15719
|
? (0, bash_1.joinBashExpressions)([
|
|
15569
|
-
|
|
15720
|
+
(0, getServiceName_1.getRawServiceNameForEnvContext)(ctx),
|
|
15570
15721
|
`${(0, store_1.getGcloudProjectNumber)(fullConfig, deployConfigRaw.projectId)}.${deployConfigRaw.region}.run.app`,
|
|
15571
15722
|
], "-").toLowerCase()
|
|
15572
15723
|
: undefined;
|
|
@@ -15828,16 +15979,197 @@ exports.getCloudRunServiceOrJobArgsArg = getCloudRunServiceOrJobArgsArg;
|
|
|
15828
15979
|
/***/ }),
|
|
15829
15980
|
|
|
15830
15981
|
/***/ 33102:
|
|
15831
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
15982
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
15832
15983
|
|
|
15833
15984
|
"use strict";
|
|
15834
15985
|
|
|
15835
15986
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
15836
|
-
exports.getServiceNameForEnvContext = exports.getServiceName = void 0;
|
|
15837
|
-
const
|
|
15987
|
+
exports.getRawServiceNameForEnvContext = exports.getServiceNameForEnvContext = exports.getServiceName = exports.resolveCloudRunComponentPart = exports.REVIEW_SLUG_LENGTH_BUDGET = exports.CLOUD_RUN_DNS_SEGMENT_LIMIT = void 0;
|
|
15988
|
+
const bash_1 = __nccwpck_require__(94143);
|
|
15989
|
+
const store_1 = __nccwpck_require__(2789);
|
|
15990
|
+
/**
|
|
15991
|
+
* cloud run only serves its deterministic url
|
|
15992
|
+
* `https://<service>-<projectNumber>.<region>.run.app` while that first dns
|
|
15993
|
+
* label stays within the 63 characters a dns label allows — the label holds
|
|
15994
|
+
* the service name, the project number and any traffic tag together.
|
|
15995
|
+
*
|
|
15996
|
+
* Beyond it cloud run silently switches to a legacy url built from a random
|
|
15997
|
+
* identifier that nothing can recompute. The url catladder generates would
|
|
15998
|
+
* then be a hostname that can never resolve, and everything consuming
|
|
15999
|
+
* ROOT_URL/ROOT_URL_INTERNAL (cloud tasks targets, service-to-service
|
|
16000
|
+
* calls) fails with a dns error instead of a helpful one — which is why the
|
|
16001
|
+
* component part is shortened to stay under the limit rather than left to
|
|
16002
|
+
* overflow.
|
|
16003
|
+
*
|
|
16004
|
+
* https://cloud.google.com/run/docs/triggering/https-request
|
|
16005
|
+
*/
|
|
16006
|
+
exports.CLOUD_RUN_DNS_SEGMENT_LIMIT = 63;
|
|
16007
|
+
/**
|
|
16008
|
+
* review environments resolve their slug at runtime (`mr<iid>` on gitlab,
|
|
16009
|
+
* `pr<number>` on github), so its exact length is unknown while generating.
|
|
16010
|
+
* Budget for a six digit number so that service names — and with them the
|
|
16011
|
+
* urls of already deployed services — do not start changing years later
|
|
16012
|
+
* just because a project's merge request numbers grew a digit.
|
|
16013
|
+
*/
|
|
16014
|
+
exports.REVIEW_SLUG_LENGTH_BUDGET = "mr123456".length;
|
|
16015
|
+
/**
|
|
16016
|
+
* a service name shortened past this point is no longer recognizable. When
|
|
16017
|
+
* even this does not fit, the fixed parts (customer name, app name, env,
|
|
16018
|
+
* project number) are what needs to shrink — only the user can do that.
|
|
16019
|
+
*/
|
|
16020
|
+
const MIN_COMPONENT_PART_LENGTH = 6;
|
|
16021
|
+
const quote = (name) => `"${name}"`;
|
|
16022
|
+
/**
|
|
16023
|
+
* a trailing dash would end up in the hostname as `...-foo-.run.app`
|
|
16024
|
+
*/
|
|
16025
|
+
const shortenTo = (name, maxLength) => name.slice(0, maxLength).replace(/-+$/, "");
|
|
16026
|
+
/**
|
|
16027
|
+
* the component-name part of a cloud run service name, shortened just
|
|
16028
|
+
* enough to keep the deterministic url resolvable.
|
|
16029
|
+
*
|
|
16030
|
+
* Only the component part is shortened: the env and review slug parts have
|
|
16031
|
+
* to stay intact (they are what makes the name unique per environment), the
|
|
16032
|
+
* project number is fixed, and customerName/appName are shared by every
|
|
16033
|
+
* service of the project.
|
|
16034
|
+
*/
|
|
16035
|
+
const resolveCloudRunComponentPart = ({ customerName, appName, env, isReviewEnv, componentName, projectNumber, otherComponentNames, }) => {
|
|
16036
|
+
const fixedParts = [
|
|
16037
|
+
customerName,
|
|
16038
|
+
appName,
|
|
16039
|
+
env,
|
|
16040
|
+
...(isReviewEnv ? ["_".repeat(exports.REVIEW_SLUG_LENGTH_BUDGET)] : []),
|
|
16041
|
+
projectNumber,
|
|
16042
|
+
];
|
|
16043
|
+
// + 1 for the dash that joins the component part to the rest
|
|
16044
|
+
const fixedLength = fixedParts.join("-").length + 1;
|
|
16045
|
+
const available = exports.CLOUD_RUN_DNS_SEGMENT_LIMIT - fixedLength;
|
|
16046
|
+
if (componentName.length <= available) {
|
|
16047
|
+
return {
|
|
16048
|
+
value: componentName,
|
|
16049
|
+
dropped: 0,
|
|
16050
|
+
dnsSegmentLength: fixedLength + componentName.length,
|
|
16051
|
+
};
|
|
16052
|
+
}
|
|
16053
|
+
if (available < MIN_COMPONENT_PART_LENGTH) {
|
|
16054
|
+
throw new Error(`Cannot build a resolvable cloud run url for component ${quote(componentName)} in env ${quote(env)}.\n` +
|
|
16055
|
+
`Everything but the component name already takes ${fixedLength} of the ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters ` +
|
|
16056
|
+
`a dns label allows (${fixedParts.join("-")}-<component>), leaving only ${available} for the component name.\n` +
|
|
16057
|
+
`Shorten appName (${quote(appName)}) or customerName (${quote(customerName)}) by at least ` +
|
|
16058
|
+
`${MIN_COMPONENT_PART_LENGTH - available} character(s).` +
|
|
16059
|
+
(isReviewEnv
|
|
16060
|
+
? `\nReview environments also carry a runtime slug, for which ${exports.REVIEW_SLUG_LENGTH_BUDGET} characters are reserved.`
|
|
16061
|
+
: ""));
|
|
16062
|
+
}
|
|
16063
|
+
const value = shortenTo(componentName, available);
|
|
16064
|
+
const colliding = otherComponentNames.filter((other) => shortenTo(other, available) === value);
|
|
16065
|
+
if (colliding.length > 0) {
|
|
16066
|
+
throw new Error(`Cloud run service names collide in env ${quote(env)}: ${quote(componentName)} and ` +
|
|
16067
|
+
`${colliding.map(quote).join(", ")} all shorten to ${quote(value)}, so they would deploy over each other.\n` +
|
|
16068
|
+
`The deterministic cloud run url allows ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters, which leaves ${available} ` +
|
|
16069
|
+
`for the component name here — rename the components so their first ${available} characters differ.`);
|
|
16070
|
+
}
|
|
16071
|
+
return {
|
|
16072
|
+
value,
|
|
16073
|
+
dropped: componentName.length - value.length,
|
|
16074
|
+
dnsSegmentLength: fixedLength + value.length,
|
|
16075
|
+
};
|
|
16076
|
+
};
|
|
16077
|
+
exports.resolveCloudRunComponentPart = resolveCloudRunComponentPart;
|
|
16078
|
+
/**
|
|
16079
|
+
* one note per shortened service name instead of one per generated job:
|
|
16080
|
+
* service names are resolved again for every job that references them
|
|
16081
|
+
*/
|
|
16082
|
+
const reportedTruncations = new Set();
|
|
16083
|
+
const reportTruncation = (env, componentName, { value, dnsSegmentLength }) => {
|
|
16084
|
+
const key = `${env}/${componentName}`;
|
|
16085
|
+
if (reportedTruncations.has(key)) {
|
|
16086
|
+
return;
|
|
16087
|
+
}
|
|
16088
|
+
reportedTruncations.add(key);
|
|
16089
|
+
console.warn(`ℹ️ component "${componentName}" deploys to cloud run as "...-${value}" in env "${env}": ` +
|
|
16090
|
+
`the full name would push the url past the ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters cloud run ` +
|
|
16091
|
+
`serves deterministically, so the component part is shortened ` +
|
|
16092
|
+
`(${dnsSegmentLength} of ${exports.CLOUD_RUN_DNS_SEGMENT_LIMIT} characters used).`);
|
|
16093
|
+
};
|
|
16094
|
+
/**
|
|
16095
|
+
* the cloud run service name before lowercasing, so that callers keep
|
|
16096
|
+
* lowercasing the whole expression exactly like they did before.
|
|
16097
|
+
*
|
|
16098
|
+
* Returns `fullName` unchanged unless the component part had to be
|
|
16099
|
+
* shortened — every project whose url already fits generates byte-identical
|
|
16100
|
+
* output.
|
|
16101
|
+
*
|
|
16102
|
+
* Note that the composition below has to match the one `fullName` is built
|
|
16103
|
+
* from in getEnvironmentContext; the tests pin that they agree.
|
|
16104
|
+
*/
|
|
16105
|
+
const getRawServiceName = ({ fullName, environmentSlugPrefix, componentName, env, isReviewEnv, deployConfig, config, }) => {
|
|
16106
|
+
const projectNumber = deployConfig
|
|
16107
|
+
? (0, store_1.readGcloudProjectNumber)(config, deployConfig.projectId)
|
|
16108
|
+
: null;
|
|
16109
|
+
if (!projectNumber) {
|
|
16110
|
+
// without the project number there is no deterministic url to keep
|
|
16111
|
+
// resolvable — generating the url itself fails with a store error that
|
|
16112
|
+
// says how to fix it, so don't second-guess the name here
|
|
16113
|
+
return fullName;
|
|
16114
|
+
}
|
|
16115
|
+
const componentPart = (0, exports.resolveCloudRunComponentPart)({
|
|
16116
|
+
customerName: config.customerName,
|
|
16117
|
+
appName: config.appName,
|
|
16118
|
+
env,
|
|
16119
|
+
isReviewEnv,
|
|
16120
|
+
componentName,
|
|
16121
|
+
projectNumber,
|
|
16122
|
+
otherComponentNames: Object.keys(config.components).filter((name) => name !== componentName),
|
|
16123
|
+
});
|
|
16124
|
+
if (componentPart.dropped === 0) {
|
|
16125
|
+
return fullName;
|
|
16126
|
+
}
|
|
16127
|
+
reportTruncation(env, componentName, componentPart);
|
|
16128
|
+
return (0, bash_1.joinBashExpressions)([
|
|
16129
|
+
config.customerName,
|
|
16130
|
+
config.appName,
|
|
16131
|
+
environmentSlugPrefix,
|
|
16132
|
+
componentPart.value,
|
|
16133
|
+
], "-");
|
|
16134
|
+
};
|
|
16135
|
+
const fromComponentContext = (context) => {
|
|
16136
|
+
var _a;
|
|
16137
|
+
const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
|
|
16138
|
+
return {
|
|
16139
|
+
fullName: context.environment.fullName,
|
|
16140
|
+
environmentSlugPrefix: context.environment.slugPrefix,
|
|
16141
|
+
componentName: context.name,
|
|
16142
|
+
env: context.env,
|
|
16143
|
+
isReviewEnv: context.environment.envType === "review",
|
|
16144
|
+
deployConfig: deployConfig && deployConfig.type === "google-cloudrun"
|
|
16145
|
+
? deployConfig
|
|
16146
|
+
: null,
|
|
16147
|
+
config: context.fullConfig,
|
|
16148
|
+
};
|
|
16149
|
+
};
|
|
16150
|
+
const fromEnvironmentContext = (context) => ({
|
|
16151
|
+
fullName: context.fullName,
|
|
16152
|
+
environmentSlugPrefix: context.environmentSlugPrefix,
|
|
16153
|
+
componentName: context.componentName,
|
|
16154
|
+
env: context.env,
|
|
16155
|
+
isReviewEnv: context.envType === "review",
|
|
16156
|
+
deployConfig: context.deployConfigRaw || null,
|
|
16157
|
+
config: context.fullConfig,
|
|
16158
|
+
});
|
|
16159
|
+
/**
|
|
16160
|
+
* the cloud run service name as it is passed to `gcloud run` — lowercased,
|
|
16161
|
+
* and shortened when the deterministic url would otherwise not fit.
|
|
16162
|
+
*/
|
|
16163
|
+
const getServiceName = (context) => getRawServiceName(fromComponentContext(context)).toLowerCase();
|
|
15838
16164
|
exports.getServiceName = getServiceName;
|
|
15839
|
-
const getServiceNameForEnvContext = (context) => context.
|
|
16165
|
+
const getServiceNameForEnvContext = (context) => getRawServiceName(fromEnvironmentContext(context)).toLowerCase();
|
|
15840
16166
|
exports.getServiceNameForEnvContext = getServiceNameForEnvContext;
|
|
16167
|
+
/**
|
|
16168
|
+
* the service name part of the deterministic url, still to be lowercased
|
|
16169
|
+
* together with the rest of the hostname by the caller.
|
|
16170
|
+
*/
|
|
16171
|
+
const getRawServiceNameForEnvContext = (context) => getRawServiceName(fromEnvironmentContext(context));
|
|
16172
|
+
exports.getRawServiceNameForEnvContext = getRawServiceNameForEnvContext;
|
|
15841
16173
|
//# sourceMappingURL=getServiceName.js.map
|
|
15842
16174
|
|
|
15843
16175
|
/***/ }),
|
|
@@ -18254,7 +18586,7 @@ exports.getRunnerImage = getRunnerImage;
|
|
|
18254
18586
|
"use strict";
|
|
18255
18587
|
|
|
18256
18588
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
18257
|
-
exports.getGcloudProjectNumber = exports.readCatladderStore = exports.getCatladderStorePath = exports.catladderStoreSchema = exports.CATLADDER_STORE_FILE = exports.CATLADDER_STORE_FILE_NAME = exports.CATLADDER_STORE_DIR = void 0;
|
|
18589
|
+
exports.getGcloudProjectNumber = exports.readGcloudProjectNumber = exports.readCatladderStore = exports.getCatladderStorePath = exports.catladderStoreSchema = exports.CATLADDER_STORE_FILE = exports.CATLADDER_STORE_FILE_NAME = exports.CATLADDER_STORE_DIR = void 0;
|
|
18258
18590
|
const fs_1 = __nccwpck_require__(79896);
|
|
18259
18591
|
const path_1 = __nccwpck_require__(16928);
|
|
18260
18592
|
const yaml_1 = __nccwpck_require__(99292);
|
|
@@ -18306,6 +18638,13 @@ const readCatladderStore = (directory = process.cwd()) => {
|
|
|
18306
18638
|
}
|
|
18307
18639
|
};
|
|
18308
18640
|
exports.readCatladderStore = readCatladderStore;
|
|
18641
|
+
/**
|
|
18642
|
+
* gcloud project number from the store, or null when it has not been
|
|
18643
|
+
* fetched yet. Use this where a missing number is not itself the problem —
|
|
18644
|
+
* `getGcloudProjectNumber` is the one that reports it.
|
|
18645
|
+
*/
|
|
18646
|
+
const readGcloudProjectNumber = (config, projectId) => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = config.store) === null || _a === void 0 ? void 0 : _a.gcloudProjects) === null || _b === void 0 ? void 0 : _b[projectId]) === null || _c === void 0 ? void 0 : _c.projectNumber) !== null && _d !== void 0 ? _d : null; };
|
|
18647
|
+
exports.readGcloudProjectNumber = readGcloudProjectNumber;
|
|
18309
18648
|
/**
|
|
18310
18649
|
* gcloud project number from the store — needed to compute deterministic
|
|
18311
18650
|
* cloud run urls (`<service>-<projectNumber>.<region>.run.app`) at
|
|
@@ -18315,8 +18654,7 @@ exports.readCatladderStore = readCatladderStore;
|
|
|
18315
18654
|
* catenv fail until `catladder project setup` has stored it.
|
|
18316
18655
|
*/
|
|
18317
18656
|
const getGcloudProjectNumber = (config, projectId) => {
|
|
18318
|
-
|
|
18319
|
-
const projectNumber = (_c = (_b = (_a = config.store) === null || _a === void 0 ? void 0 : _a.gcloudProjects) === null || _b === void 0 ? void 0 : _b[projectId]) === null || _c === void 0 ? void 0 : _c.projectNumber;
|
|
18657
|
+
const projectNumber = (0, exports.readGcloudProjectNumber)(config, projectId);
|
|
18320
18658
|
if (!projectNumber) {
|
|
18321
18659
|
throw new Error(`Missing gcloud project number for project "${projectId}" in ${exports.CATLADDER_STORE_FILE}.\n` +
|
|
18322
18660
|
`Run "catladder project setup" to fetch and store it.`);
|
|
@@ -46,6 +46,7 @@ resources with `yarn catladder project setup`; detect drift with
|
|
|
46
46
|
- `cloudSql?: DeployConfigCloudRunCloudSql | false` — `{ type: "unmanaged", instanceConnectionName, dbUser?, dbNamePrefix?, dbBaseName?, deleteDatabaseOnStop?, dbConnectionStringFormat? ("prisma" default | "rails" | "jdbc"), dbConnectionStringVariablesMode? ("embedded" default | "legacy"), dbAdditionalQueryParams? }`. Injects `DB_*` vars plus `DATABASE_URL`/`DATABASE_JDBC_URL`; in the default `"embedded"` mode the connection strings contain the component's final values (referenceable from other components, `vars.public` overrides of `DB_*` flow in). To share another component's database: `dbBaseName: "<owner>"` + `DB_PASSWORD: "${<owner>:DB_PASSWORD}"` in `vars.public`.
|
|
47
47
|
- `execute?: Record<string, DeployConfigCloudRunExecute | null>` — run a script / job / HTTP call at a lifecycle point (`when`: `preDeploy` | `postDeploy` | `preStop` | `postStop`) or on a `schedule`.
|
|
48
48
|
- `debug?: boolean`.
|
|
49
|
+
- Service name and url: the service deploys as `<customerName>-<appName>-<env>[-<reviewSlug>]-<componentName>`, and `ROOT_URL`/`ROOT_URL_INTERNAL` are cloud run's deterministic url `https://<service>-<projectNumber>.<region>.run.app`. That url only exists while its first dns label stays within 63 characters, so catladder **shortens the component part** of the service name when it would not fit — otherwise cloud run would serve a legacy url with a random identifier and the generated hostname would never resolve. Review environments carry a runtime slug on top, for which 8 characters are reserved, so a name can fit `dev`/`prod` and still be shortened for `review`. Generation fails instead of shortening when two components would end up with the same name, or when customerName/appName/env/project number already leave no room.
|
|
49
50
|
|
|
50
51
|
## `npmPackage`
|
|
51
52
|
|
|
@@ -260,13 +260,17 @@ now-wrong `gitRemote`, regenerate once more, and finish with
|
|
|
260
260
|
PR is mergeable the moment it opens, checks still running, and the
|
|
261
261
|
auto-merge button does not even appear. `yarn catladder project setup`
|
|
262
262
|
configures it: auto-merge + delete-merged-branches on the repo, and a
|
|
263
|
-
|
|
264
|
-
**`catladder ✅`** aggregate check
|
|
265
|
-
require individual job names, they
|
|
266
|
-
add/rename and a stale required name
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
263
|
+
repository **ruleset** (`catladder merge gating`) on the default
|
|
264
|
+
branch requiring the generated **`catladder ✅`** aggregate check
|
|
265
|
+
(the one stable context — never require individual job names, they
|
|
266
|
+
change with every component add/rename and a stale required name
|
|
267
|
+
blocks its own PR forever). The ruleset carries a bypass for the
|
|
268
|
+
GitHub Actions app: the release job pushes the release commit and
|
|
269
|
+
tag straight to the default branch with the workflow token, which a
|
|
270
|
+
required check would otherwise reject (GH006 — classic branch
|
|
271
|
+
protection has no bypass list, which is why setup uses a ruleset and
|
|
272
|
+
migrates old classic-protection gating away). `project doctor`
|
|
273
|
+
verifies all of it. Required reviews stay a human choice.
|
|
270
274
|
- Tell the team where the pipeline lives now and how manual actions
|
|
271
275
|
work there (on GitHub, manual jobs are dispatch workflows in the
|
|
272
276
|
Actions sidebar — `🚀 catladder create release`, `▶️ catladder deploy`,
|
|
@@ -65,9 +65,14 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
|
|
|
65
65
|
// generation time. For review envs the service name part still
|
|
66
66
|
// contains a runtime expression (the review slug), so the host stays
|
|
67
67
|
// a bash expression there; the suffix is always a literal.
|
|
68
|
+
//
|
|
69
|
+
// The service name has to come from getRawServiceNameForEnvContext,
|
|
70
|
+
// not from fullName: it is shortened when the label would otherwise
|
|
71
|
+
// exceed what cloud run serves deterministically, and the url must
|
|
72
|
+
// name the service that is actually deployed.
|
|
68
73
|
const HOSTNAME_INTERNAL = deployConfigRaw && envType !== "local"
|
|
69
74
|
? (0, bash_1.joinBashExpressions)([
|
|
70
|
-
|
|
75
|
+
(0, getServiceName_1.getRawServiceNameForEnvContext)(ctx),
|
|
71
76
|
`${(0, store_1.getGcloudProjectNumber)(fullConfig, deployConfigRaw.projectId)}.${deployConfigRaw.region}.run.app`,
|
|
72
77
|
], "-").toLowerCase()
|
|
73
78
|
: undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../packages/pipeline/src/deploy/cloudRun/index.ts"],"names":[],"mappings":";;;AACA,0CAAsD;AAEtD,2CAAiD;AACjD,uCAAqD;AAErD,+CAG4B;AAC5B,6CAAkD;AAClD,6CAA8D;AAC9D,uEAAwE;AACxE,+CAI0B;AAC1B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../packages/pipeline/src/deploy/cloudRun/index.ts"],"names":[],"mappings":"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"}
|