@catladder/cli 5.0.1 → 5.1.1
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 +3 -3
- package/dist/apps/cli/src/apps/cli/commands/project/doctor/checkGithub.js.map +1 -1
- package/dist/apps/cli/src/apps/cli/commands/project/doctor/checkGithubImageCasing.d.ts +15 -0
- package/dist/apps/cli/src/apps/cli/commands/project/doctor/checkGithubImageCasing.js +60 -0
- package/dist/apps/cli/src/apps/cli/commands/project/doctor/checkGithubImageCasing.js.map +1 -0
- package/dist/apps/cli/src/apps/cli/commands/project/doctor/index.js +2 -0
- package/dist/apps/cli/src/apps/cli/commands/project/doctor/index.js.map +1 -1
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupAccessTokens.js +2 -2
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupAccessTokens.js.map +1 -1
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupGithub.js +2 -2
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupGithub.js.map +1 -1
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupKubernetes.js +23 -7
- package/dist/apps/cli/src/apps/cli/commands/project/setup/setupKubernetes.js.map +1 -1
- package/dist/apps/cli/src/commands/index.d.ts +1 -0
- package/dist/apps/cli/src/commands/index.js +4 -1
- package/dist/apps/cli/src/commands/index.js.map +1 -1
- package/dist/apps/cli/src/commands/project/commandConfigSecrets.js +2 -1
- package/dist/apps/cli/src/commands/project/commandConfigSecrets.js.map +1 -1
- package/dist/apps/cli/src/commands/project/commandMrPin.d.ts +21 -0
- package/dist/apps/cli/src/commands/project/commandMrPin.js +119 -0
- package/dist/apps/cli/src/commands/project/commandMrPin.js.map +1 -0
- package/dist/apps/cli/src/commands/project/commandSecretsSyncGithub.d.ts +1 -42
- package/dist/apps/cli/src/commands/project/commandSecretsSyncGithub.js +5 -124
- package/dist/apps/cli/src/commands/project/commandSecretsSyncGithub.js.map +1 -1
- package/dist/apps/cli/src/commands/project/secrets/commandSecretsPush.js +2 -1
- package/dist/apps/cli/src/commands/project/secrets/commandSecretsPush.js.map +1 -1
- package/dist/apps/cli/src/commands/project/secrets/commandSecretsSet.js +2 -2
- package/dist/apps/cli/src/commands/project/secrets/commandSecretsSet.js.map +1 -1
- package/dist/apps/cli/src/commands/project/secrets/document.d.ts +1 -12
- package/dist/apps/cli/src/commands/project/secrets/document.js +1 -79
- package/dist/apps/cli/src/commands/project/secrets/document.js.map +1 -1
- package/dist/apps/cli/src/gcloud/serviceAccounts.js +15 -4
- package/dist/apps/cli/src/gcloud/serviceAccounts.js.map +1 -1
- package/dist/apps/cli/src/secrets/github.d.ts +41 -0
- package/dist/apps/cli/src/secrets/github.js +127 -0
- package/dist/apps/cli/src/secrets/github.js.map +1 -0
- package/dist/apps/cli/src/secrets/index.d.ts +2 -0
- package/dist/apps/cli/src/secrets/index.js +19 -0
- package/dist/apps/cli/src/secrets/index.js.map +1 -0
- package/dist/apps/cli/src/secrets/writeSecrets.d.ts +18 -0
- package/dist/apps/cli/src/secrets/writeSecrets.js +88 -0
- package/dist/apps/cli/src/secrets/writeSecrets.js.map +1 -0
- package/dist/apps/cli/src/utils/github.js +2 -2
- package/dist/apps/cli/src/utils/github.js.map +1 -1
- package/dist/apps/cli/src/utils/gitlab.d.ts +10 -0
- package/dist/apps/cli/src/utils/gitlab.js +30 -5
- package/dist/apps/cli/src/utils/gitlab.js.map +1 -1
- package/dist/apps/cli/src/vault/BitwardenVault.d.ts +6 -0
- package/dist/apps/cli/src/vault/BitwardenVault.js +11 -1
- package/dist/apps/cli/src/vault/BitwardenVault.js.map +1 -1
- package/dist/apps/cli/src/vault/GitlabVault.d.ts +2 -2
- package/dist/apps/cli/src/vault/GitlabVault.js +3 -2
- package/dist/apps/cli/src/vault/GitlabVault.js.map +1 -1
- package/dist/apps/cli/src/vault/VaultManager.d.ts +2 -2
- package/dist/apps/cli/src/vault/VaultManager.js +2 -2
- package/dist/apps/cli/src/vault/VaultManager.js.map +1 -1
- package/dist/apps/cli/src/vault/types.d.ts +16 -2
- package/dist/bundles/catenv/index.js +265 -28
- package/dist/bundles/cli/index.js +851 -329
- package/dist/bundles/skills/catladder-cli/references/commands.md +13 -0
- package/dist/bundles/skills/catladder-config/SKILL.md +3 -1
- package/dist/bundles/skills/catladder-deploys/SKILL.md +7 -0
- package/dist/bundles/skills/catladder-migrate-ci-backend/SKILL.md +18 -2
- package/dist/bundles/skills/catladder-pipelines/SKILL.md +51 -1
- package/dist/bundles/skills/catladder-secrets/SKILL.md +16 -0
- package/dist/packages/pipeline/src/autoStop.d.ts +22 -0
- package/dist/packages/pipeline/src/autoStop.js +30 -0
- package/dist/packages/pipeline/src/autoStop.js.map +1 -0
- package/dist/packages/pipeline/src/backends/github/GithubBackend.js +11 -5
- package/dist/packages/pipeline/src/backends/github/GithubBackend.js.map +1 -1
- package/dist/packages/pipeline/src/backends/github/ciVariables.d.ts +13 -2
- package/dist/packages/pipeline/src/backends/github/ciVariables.js +18 -5
- package/dist/packages/pipeline/src/backends/github/ciVariables.js.map +1 -1
- package/dist/packages/pipeline/src/backends/github/createGithubJobs.js +1 -1
- package/dist/packages/pipeline/src/backends/github/createGithubJobs.js.map +1 -1
- package/dist/packages/pipeline/src/backends/github/ghcr.d.ts +29 -0
- package/dist/packages/pipeline/src/backends/github/ghcr.js +40 -0
- package/dist/packages/pipeline/src/backends/github/ghcr.js.map +1 -0
- package/dist/packages/pipeline/src/backends/github/index.d.ts +2 -0
- package/dist/packages/pipeline/src/backends/github/index.js +2 -0
- package/dist/packages/pipeline/src/backends/github/index.js.map +1 -1
- package/dist/packages/pipeline/src/backends/github/registryImage.d.ts +20 -0
- package/dist/packages/pipeline/src/backends/github/registryImage.js +49 -0
- package/dist/packages/pipeline/src/backends/github/registryImage.js.map +1 -0
- package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js +2 -0
- package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
- package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.d.ts +4 -1
- package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.js +21 -1
- package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.js.map +1 -1
- package/dist/packages/pipeline/src/customImages/jobImagesPlan.d.ts +15 -3
- package/dist/packages/pipeline/src/customImages/jobImagesPlan.js +14 -3
- package/dist/packages/pipeline/src/customImages/jobImagesPlan.js.map +1 -1
- package/dist/packages/pipeline/src/deploy/base/deploy.js +8 -2
- package/dist/packages/pipeline/src/deploy/base/deploy.js.map +1 -1
- package/dist/packages/pipeline/src/index.d.ts +1 -0
- package/dist/packages/pipeline/src/index.js +1 -0
- package/dist/packages/pipeline/src/index.js.map +1 -1
- package/dist/packages/pipeline/src/types/config.d.ts +44 -0
- package/dist/skills/catladder-cli/references/commands.md +13 -0
- package/dist/skills/catladder-config/SKILL.md +3 -1
- package/dist/skills/catladder-deploys/SKILL.md +7 -0
- package/dist/skills/catladder-migrate-ci-backend/SKILL.md +18 -2
- package/dist/skills/catladder-pipelines/SKILL.md +51 -1
- package/dist/skills/catladder-secrets/SKILL.md +16 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/apps/cli/commands/project/doctor/checkGithub.ts +1 -1
- package/src/apps/cli/commands/project/doctor/checkGithubImageCasing.ts +87 -0
- package/src/apps/cli/commands/project/doctor/index.ts +2 -0
- package/src/apps/cli/commands/project/setup/setupAccessTokens.ts +3 -2
- package/src/apps/cli/commands/project/setup/setupGithub.ts +1 -1
- package/src/apps/cli/commands/project/setup/setupKubernetes.ts +31 -20
- package/src/commands/index.ts +1 -0
- package/src/commands/project/commandConfigSecrets.ts +1 -1
- package/src/commands/project/commandMrPin.ts +184 -0
- package/src/commands/project/commandSecretsSyncGithub.ts +7 -154
- package/src/commands/project/secrets/commandSecretsPush.ts +2 -5
- package/src/commands/project/secrets/commandSecretsSet.ts +2 -2
- package/src/commands/project/secrets/document.ts +2 -127
- package/src/gcloud/serviceAccounts.ts +16 -7
- package/src/secrets/__tests__/writeSecrets.test.ts +147 -0
- package/src/secrets/github.ts +157 -0
- package/src/secrets/index.ts +2 -0
- package/src/secrets/writeSecrets.ts +138 -0
- package/src/utils/github.ts +2 -4
- package/src/utils/gitlab.ts +34 -7
- package/src/vault/BitwardenVault.ts +10 -1
- package/src/vault/GitlabVault.ts +9 -2
- package/src/vault/VaultManager.ts +3 -2
- package/src/vault/__tests__/BitwardenVault.test.ts +88 -0
- package/src/vault/types.ts +17 -1
|
@@ -616,7 +616,7 @@ exports.checkCloudRun = checkCloudRun;
|
|
|
616
616
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
617
617
|
exports.checkGithub = void 0;
|
|
618
618
|
const pipeline_1 = __nccwpck_require__(53695);
|
|
619
|
-
const
|
|
619
|
+
const secrets_1 = __nccwpck_require__(85200);
|
|
620
620
|
const concurrency_1 = __nccwpck_require__(59723);
|
|
621
621
|
const github_1 = __nccwpck_require__(41353);
|
|
622
622
|
const githubMergeGating_1 = __nccwpck_require__(14966);
|
|
@@ -637,14 +637,14 @@ const checkGithub = async (report, config) => {
|
|
|
637
637
|
report.warn("github cli (gh) not authenticated — github checks skipped", "run: gh auth login");
|
|
638
638
|
return;
|
|
639
639
|
}
|
|
640
|
-
const repo = await (0,
|
|
640
|
+
const repo = await (0, secrets_1.getConfiguredGithubRepo)();
|
|
641
641
|
if (!repo) {
|
|
642
642
|
report.fail(`no github repository found on the '${(0, pipeline_1.getPipelineGitRemote)(config, "github")}' remote`);
|
|
643
643
|
return;
|
|
644
644
|
}
|
|
645
645
|
let targets;
|
|
646
646
|
try {
|
|
647
|
-
targets = await (0,
|
|
647
|
+
targets = await (0, secrets_1.collectSecretTargets)(config);
|
|
648
648
|
}
|
|
649
649
|
catch (e) {
|
|
650
650
|
report.warn(`could not generate the github workflows to derive secret references (${e.message})`);
|
|
@@ -802,6 +802,73 @@ const checkGithubMergeGating = async (report, repo) => {
|
|
|
802
802
|
|
|
803
803
|
/***/ }),
|
|
804
804
|
|
|
805
|
+
/***/ 12668:
|
|
806
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
807
|
+
|
|
808
|
+
"use strict";
|
|
809
|
+
|
|
810
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
811
|
+
exports.checkGithubImageCasing = void 0;
|
|
812
|
+
const promises_1 = __nccwpck_require__(91943);
|
|
813
|
+
const path_1 = __nccwpck_require__(16928);
|
|
814
|
+
const pipeline_1 = __nccwpck_require__(53695);
|
|
815
|
+
const secrets_1 = __nccwpck_require__(85200);
|
|
816
|
+
const WORKFLOWS_FOLDER = ".github/workflows";
|
|
817
|
+
const GENERATED_FILE_PREFIX = "catladder-";
|
|
818
|
+
/**
|
|
819
|
+
* the generated workflow files, or an empty list when none exist yet
|
|
820
|
+
*/
|
|
821
|
+
const readGeneratedWorkflows = async () => {
|
|
822
|
+
const entries = await (0, promises_1.readdir)(WORKFLOWS_FOLDER).catch(() => []);
|
|
823
|
+
return Promise.all(entries
|
|
824
|
+
.filter((file) => file.startsWith(GENERATED_FILE_PREFIX))
|
|
825
|
+
.map((file) => (0, promises_1.readFile)((0, path_1.join)(WORKFLOWS_FOLDER, file), "utf8")));
|
|
826
|
+
};
|
|
827
|
+
/**
|
|
828
|
+
* ghcr image paths must be lowercase, but `${{ github.repository }}`
|
|
829
|
+
* interpolates github's display casing — so a repository whose owner or
|
|
830
|
+
* name contains an uppercase character needs a lowercased literal in the
|
|
831
|
+
* generated workflows. Generation bakes that in, which means committed
|
|
832
|
+
* workflows generated by an older catladder (or hand-edited ones) still
|
|
833
|
+
* carry the expression and fail every docker job with
|
|
834
|
+
* `repository name must be lowercase`.
|
|
835
|
+
*
|
|
836
|
+
* Unlike the rest of the github checks this needs no `gh` login — only
|
|
837
|
+
* the git remote and the committed files.
|
|
838
|
+
*/
|
|
839
|
+
const checkGithubImageCasing = async (report, config) => {
|
|
840
|
+
if (!(0, pipeline_1.getEnabledPipelineTypes)(config).includes("github"))
|
|
841
|
+
return;
|
|
842
|
+
const repo = await (0, secrets_1.getConfiguredGithubRepo)();
|
|
843
|
+
if (!repo || repo === repo.toLowerCase()) {
|
|
844
|
+
// an all-lowercase repository keeps the expression on purpose (it
|
|
845
|
+
// stays correct in forks), and an unresolvable remote is reported
|
|
846
|
+
// by checkGithub already
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
report.section("github image names");
|
|
850
|
+
const workflows = await readGeneratedWorkflows();
|
|
851
|
+
if (workflows.length === 0) {
|
|
852
|
+
report.warn(`no generated workflows in ${WORKFLOWS_FOLDER} to check`, "run: catenv");
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
const stale = workflows.filter((content) => content.includes(pipeline_1.GHCR_REPOSITORY_EXPRESSION));
|
|
856
|
+
if (stale.length > 0) {
|
|
857
|
+
report.fail(`'${repo}' is mixed-case, but ${stale.length}/${workflows.length} generated workflows still use ${pipeline_1.GHCR_REPOSITORY_EXPRESSION} — ghcr rejects uppercase image paths, so every docker job fails with "repository name must be lowercase"`, "run: catenv (and commit the regenerated workflows)");
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
const uppercase = workflows.flatMap((content) => [...content.matchAll(/ghcr\.io\/\S*[A-Z]\S*/g)].map(([match]) => match));
|
|
861
|
+
if (uppercase.length > 0) {
|
|
862
|
+
report.fail(`uppercase ghcr image paths in the generated workflows: ${[...new Set(uppercase)].join(", ")}`, `run: catenv — if it persists, set pipelines.github.repository (the '${(0, pipeline_1.getPipelineGitRemote)(config, "github")}' remote resolves to '${repo}')`);
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
report.ok(`ghcr image paths lowercased for '${repo}'`);
|
|
866
|
+
};
|
|
867
|
+
exports.checkGithubImageCasing = checkGithubImageCasing;
|
|
868
|
+
//# sourceMappingURL=checkGithubImageCasing.js.map
|
|
869
|
+
|
|
870
|
+
/***/ }),
|
|
871
|
+
|
|
805
872
|
/***/ 26904:
|
|
806
873
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
807
874
|
|
|
@@ -946,6 +1013,7 @@ const pipeline_1 = __nccwpck_require__(53695);
|
|
|
946
1013
|
const getProjectConfig_1 = __nccwpck_require__(70478);
|
|
947
1014
|
const checkCloudRun_1 = __nccwpck_require__(55869);
|
|
948
1015
|
const checkGithub_1 = __nccwpck_require__(88480);
|
|
1016
|
+
const checkGithubImageCasing_1 = __nccwpck_require__(12668);
|
|
949
1017
|
const checkGitlab_1 = __nccwpck_require__(26904);
|
|
950
1018
|
const checkStore_1 = __nccwpck_require__(62878);
|
|
951
1019
|
const DoctorReport_1 = __nccwpck_require__(87354);
|
|
@@ -981,6 +1049,7 @@ const doctorProject = async (instance, onlyComponents) => {
|
|
|
981
1049
|
await (0, checkGitlab_1.checkGitlab)(instance, report, contexts);
|
|
982
1050
|
}
|
|
983
1051
|
await (0, checkCloudRun_1.checkCloudRun)(report, contexts);
|
|
1052
|
+
await (0, checkGithubImageCasing_1.checkGithubImageCasing)(report, config);
|
|
984
1053
|
await (0, checkGithub_1.checkGithub)(report, config);
|
|
985
1054
|
report.summarize();
|
|
986
1055
|
};
|
|
@@ -1260,10 +1329,10 @@ const setupAccessTokens = async (instance) => {
|
|
|
1260
1329
|
await (0, gitlab_1.doGitlabRequest)(instance, `projects/${projectId}/variables/GL_TOKEN`, { value: newToken.token }, "PUT");
|
|
1261
1330
|
}
|
|
1262
1331
|
catch (e) {
|
|
1263
|
-
if (e
|
|
1332
|
+
if (!(e instanceof gitlab_1.GitlabNotFoundError)) {
|
|
1264
1333
|
throw e;
|
|
1265
1334
|
}
|
|
1266
|
-
// not
|
|
1335
|
+
// the variable does not exist yet: create it
|
|
1267
1336
|
await (0, gitlab_1.doGitlabRequest)(instance, `projects/${projectId}/variables`, {
|
|
1268
1337
|
key: "GL_TOKEN",
|
|
1269
1338
|
value: newToken.token,
|
|
@@ -1566,7 +1635,7 @@ const promises_1 = __nccwpck_require__(91943);
|
|
|
1566
1635
|
const os_1 = __nccwpck_require__(70857);
|
|
1567
1636
|
const path_1 = __nccwpck_require__(16928);
|
|
1568
1637
|
const util_1 = __nccwpck_require__(39023);
|
|
1569
|
-
const
|
|
1638
|
+
const secrets_1 = __nccwpck_require__(85200);
|
|
1570
1639
|
const github_1 = __nccwpck_require__(41353);
|
|
1571
1640
|
const githubMergeGating_1 = __nccwpck_require__(14966);
|
|
1572
1641
|
const execFile = (0, util_1.promisify)(child_process_1.execFile);
|
|
@@ -1600,7 +1669,7 @@ const setupGithub = async (instance, config) => {
|
|
|
1600
1669
|
instance.log("⚠️ github cli (gh) not authenticated — skipping github merge-gating setup (run: gh auth login)");
|
|
1601
1670
|
return;
|
|
1602
1671
|
}
|
|
1603
|
-
const repo = await (0,
|
|
1672
|
+
const repo = await (0, secrets_1.getConfiguredGithubRepo)();
|
|
1604
1673
|
if (!repo) {
|
|
1605
1674
|
instance.log(`⚠️ no github repository found on the '${(0, pipeline_1.getPipelineGitRemote)(config, "github")}' remote — skipping github merge-gating setup`);
|
|
1606
1675
|
return;
|
|
@@ -1770,15 +1839,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
1770
1839
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1771
1840
|
exports.setupKubernetes = void 0;
|
|
1772
1841
|
const pipeline_1 = __nccwpck_require__(53695);
|
|
1842
|
+
const getProjectConfig_1 = __nccwpck_require__(70478);
|
|
1773
1843
|
const child_process_promise_1 = __nccwpck_require__(11542);
|
|
1844
|
+
const secrets_1 = __nccwpck_require__(85200);
|
|
1774
1845
|
const cluster_1 = __nccwpck_require__(8034);
|
|
1775
1846
|
const gitlab_1 = __nccwpck_require__(17697);
|
|
1776
1847
|
const ensureNamespace_1 = __importDefault(__nccwpck_require__(308));
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1848
|
+
/**
|
|
1849
|
+
* the cluster pulls the images from the gitlab container registry, and
|
|
1850
|
+
* a deploy token is how it authenticates there. Nothing to do when the
|
|
1851
|
+
* project has no gitlab pipeline (the images live elsewhere then).
|
|
1852
|
+
*/
|
|
1853
|
+
const ensureGitlabDeployToken = async (instance, config) => {
|
|
1854
|
+
if (!config || !(0, pipeline_1.getEnabledPipelineTypes)(config).includes("gitlab")) {
|
|
1855
|
+
return;
|
|
1782
1856
|
}
|
|
1783
1857
|
const { id: projectId } = await (0, gitlab_1.getProjectInfo)(instance);
|
|
1784
1858
|
const deploy_tokens = await (0, gitlab_1.doGitlabRequest)(instance, `projects/${projectId}/deploy_tokens`);
|
|
@@ -1790,6 +1864,14 @@ const setupKubernetes = async (instance, context) => {
|
|
|
1790
1864
|
scopes: ["read_registry"],
|
|
1791
1865
|
}, "POST");
|
|
1792
1866
|
}
|
|
1867
|
+
};
|
|
1868
|
+
const setupKubernetes = async (instance, context) => {
|
|
1869
|
+
var _a;
|
|
1870
|
+
const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
|
|
1871
|
+
if (!(0, pipeline_1.isOfDeployType)(deployConfig, "kubernetes")) {
|
|
1872
|
+
throw new Error("cannot run setupKubernetes on non-kubernetes deployments");
|
|
1873
|
+
}
|
|
1874
|
+
await ensureGitlabDeployToken(instance, await (0, getProjectConfig_1.getProjectConfig)());
|
|
1793
1875
|
const fullName = (0, pipeline_1.getFullKubernetesClusterName)(deployConfig.cluster);
|
|
1794
1876
|
instance.log(`cluster: ${fullName}`);
|
|
1795
1877
|
await (0, cluster_1.connectToCluster)(fullName);
|
|
@@ -1872,8 +1954,11 @@ EOF
|
|
|
1872
1954
|
}
|
|
1873
1955
|
instance.log("service accounts created / updated!");
|
|
1874
1956
|
instance.log("");
|
|
1875
|
-
instance.log("
|
|
1876
|
-
await (0,
|
|
1957
|
+
instance.log("storing the cluster credentials...");
|
|
1958
|
+
await (0, secrets_1.writeSecretsAndMirror)(instance, [{ env: context.env, componentName: context.name, secrets: vars }],
|
|
1959
|
+
// the service account token is recreated on every run — the
|
|
1960
|
+
// previous one is worth nothing
|
|
1961
|
+
{ backup: false });
|
|
1877
1962
|
instance.log("done!");
|
|
1878
1963
|
};
|
|
1879
1964
|
exports.setupKubernetes = setupKubernetes;
|
|
@@ -2719,7 +2804,7 @@ exports.commandKubeStopPortforward = (0, defineCommand_1.defineCommand)({
|
|
|
2719
2804
|
"use strict";
|
|
2720
2805
|
|
|
2721
2806
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2722
|
-
exports.commandStarwars = exports.commandDadjoke = exports.commandSecurityAuditCreate = exports.commandSecurityAuditEvaluate = exports.commandSecurityAuditCiJob = exports.commandRestoreDb = exports.commandMongoDestroyMember = exports.commandMongoPortForward = exports.commandMongoGetShell = exports.commandTriggerCronjobProject = exports.commandDeleteProject = exports.commandPauseProject = exports.commandDeletePods = exports.commandGetShell = exports.commandListPods = exports.commandNamespace = exports.commandSecurityEvaluate = exports.commandProjectRestoreDb = exports.commandCiJobLog = exports.commandCiJobOpen = exports.commandDoctor = exports.commandSetup = exports.commandGetMyTotalWorktime = exports.commandRenewToken = exports.commandTriggerCronjobGeneral = exports.commandOpenLogs = exports.commandSecretsSyncGithub = exports.commandSecretsClearBackups = exports.commandSecretsList = exports.commandSecretsSet = exports.commandSecretsPush = exports.commandSecretsPull = exports.commandConfigSecrets = exports.commandCloudSqlProxy = exports.commandOpenGit = exports.commandOpenEnv = exports.commandPortForward = exports.commandEnvVars = exports.commandKubePortForward = exports.commandKubeGetShell = exports.commandKubeStopPortforward = exports.commandKubeListPods = exports.commandKubeListSecrets = exports.commandKubeListNamespaces = exports.commandKubeCurrentContext = void 0;
|
|
2807
|
+
exports.commandStarwars = exports.commandDadjoke = exports.commandSecurityAuditCreate = exports.commandSecurityAuditEvaluate = exports.commandSecurityAuditCiJob = exports.commandRestoreDb = exports.commandMongoDestroyMember = exports.commandMongoPortForward = exports.commandMongoGetShell = exports.commandTriggerCronjobProject = exports.commandDeleteProject = exports.commandPauseProject = exports.commandDeletePods = exports.commandGetShell = exports.commandListPods = exports.commandNamespace = exports.commandMrUnpin = exports.commandMrPin = exports.commandSecurityEvaluate = exports.commandProjectRestoreDb = exports.commandCiJobLog = exports.commandCiJobOpen = exports.commandDoctor = exports.commandSetup = exports.commandGetMyTotalWorktime = exports.commandRenewToken = exports.commandTriggerCronjobGeneral = exports.commandOpenLogs = exports.commandSecretsSyncGithub = exports.commandSecretsClearBackups = exports.commandSecretsList = exports.commandSecretsSet = exports.commandSecretsPush = exports.commandSecretsPull = exports.commandConfigSecrets = exports.commandCloudSqlProxy = exports.commandOpenGit = exports.commandOpenEnv = exports.commandPortForward = exports.commandEnvVars = exports.commandKubePortForward = exports.commandKubeGetShell = exports.commandKubeStopPortforward = exports.commandKubeListPods = exports.commandKubeListSecrets = exports.commandKubeListNamespaces = exports.commandKubeCurrentContext = void 0;
|
|
2723
2808
|
// General commands
|
|
2724
2809
|
var commandKubeCurrentContext_1 = __nccwpck_require__(78034);
|
|
2725
2810
|
Object.defineProperty(exports, "commandKubeCurrentContext", ({ enumerable: true, get: function () { return commandKubeCurrentContext_1.commandKubeCurrentContext; } }));
|
|
@@ -2779,6 +2864,9 @@ var commandProjectRestoreDb_1 = __nccwpck_require__(69233);
|
|
|
2779
2864
|
Object.defineProperty(exports, "commandProjectRestoreDb", ({ enumerable: true, get: function () { return commandProjectRestoreDb_1.commandProjectRestoreDb; } }));
|
|
2780
2865
|
var commandSecurityEvaluate_1 = __nccwpck_require__(86851);
|
|
2781
2866
|
Object.defineProperty(exports, "commandSecurityEvaluate", ({ enumerable: true, get: function () { return commandSecurityEvaluate_1.commandSecurityEvaluate; } }));
|
|
2867
|
+
var commandMrPin_1 = __nccwpck_require__(31318);
|
|
2868
|
+
Object.defineProperty(exports, "commandMrPin", ({ enumerable: true, get: function () { return commandMrPin_1.commandMrPin; } }));
|
|
2869
|
+
Object.defineProperty(exports, "commandMrUnpin", ({ enumerable: true, get: function () { return commandMrPin_1.commandMrUnpin; } }));
|
|
2782
2870
|
// Project k8s commands
|
|
2783
2871
|
var commandNamespace_1 = __nccwpck_require__(25918);
|
|
2784
2872
|
Object.defineProperty(exports, "commandNamespace", ({ enumerable: true, get: function () { return commandNamespace_1.commandNamespace; } }));
|
|
@@ -3175,6 +3263,7 @@ const common_tags_1 = __nccwpck_require__(110);
|
|
|
3175
3263
|
const defineCommand_1 = __nccwpck_require__(19096);
|
|
3176
3264
|
const editAsFile_1 = __nccwpck_require__(3072);
|
|
3177
3265
|
const promise_1 = __nccwpck_require__(23161);
|
|
3266
|
+
const secrets_1 = __nccwpck_require__(85200);
|
|
3178
3267
|
const document_1 = __nccwpck_require__(96716);
|
|
3179
3268
|
const scope_1 = __nccwpck_require__(8513);
|
|
3180
3269
|
const parseKeysInput_1 = __nccwpck_require__(93560);
|
|
@@ -3237,7 +3326,7 @@ exports.commandConfigSecrets = (0, defineCommand_1.defineCommand)({
|
|
|
3237
3326
|
ctx.log("⏭️ these secrets are still unset and will not be written:");
|
|
3238
3327
|
skipped.forEach((entry) => ctx.log(` - ${entry}`));
|
|
3239
3328
|
}
|
|
3240
|
-
await (0,
|
|
3329
|
+
await (0, secrets_1.writeSecretsAndMirror)(ctx, writes);
|
|
3241
3330
|
ctx.log("done! 😻");
|
|
3242
3331
|
ctx.log("");
|
|
3243
3332
|
},
|
|
@@ -3442,6 +3531,132 @@ exports.commandCiJobLog = (0, defineCommand_1.defineCommand)({
|
|
|
3442
3531
|
|
|
3443
3532
|
/***/ }),
|
|
3444
3533
|
|
|
3534
|
+
/***/ 31318:
|
|
3535
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
3536
|
+
|
|
3537
|
+
"use strict";
|
|
3538
|
+
|
|
3539
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3540
|
+
exports.commandMrUnpin = exports.commandMrPin = void 0;
|
|
3541
|
+
const child_process_promise_1 = __nccwpck_require__(11542);
|
|
3542
|
+
const pipeline_1 = __nccwpck_require__(53695);
|
|
3543
|
+
const getProjectConfig_1 = __nccwpck_require__(70478);
|
|
3544
|
+
const defineCommand_1 = __nccwpck_require__(19096);
|
|
3545
|
+
const gitlab_1 = __nccwpck_require__(17697);
|
|
3546
|
+
const PIN_LABEL_COLOR = "#428fdc";
|
|
3547
|
+
/**
|
|
3548
|
+
* the configured pin label — errors when the project cannot pin
|
|
3549
|
+
* (github-only, or pinning disabled)
|
|
3550
|
+
*/
|
|
3551
|
+
const getPinLabel = async () => {
|
|
3552
|
+
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
3553
|
+
if (!config) {
|
|
3554
|
+
throw new Error("no catladder config found");
|
|
3555
|
+
}
|
|
3556
|
+
if (!(0, pipeline_1.getEnabledPipelineTypes)(config).includes("gitlab")) {
|
|
3557
|
+
throw new Error("pinning review apps needs the gitlab pipeline — github has no auto-stop, review apps live until the pull request is closed");
|
|
3558
|
+
}
|
|
3559
|
+
const { pinLabel } = (0, pipeline_1.getAutoStopConfig)(config);
|
|
3560
|
+
if (pinLabel === false) {
|
|
3561
|
+
throw new Error("review-app pinning is disabled in this project (autoStop.pinLabel: false)");
|
|
3562
|
+
}
|
|
3563
|
+
return pinLabel;
|
|
3564
|
+
};
|
|
3565
|
+
const findMr = async (io, projectId, mrIid) => {
|
|
3566
|
+
if (mrIid) {
|
|
3567
|
+
return (0, gitlab_1.doGitlabRequest)(io, `projects/${projectId}/merge_requests/${mrIid}`);
|
|
3568
|
+
}
|
|
3569
|
+
const branch = (await (0, child_process_promise_1.exec)("git rev-parse --abbrev-ref HEAD")).stdout.trim();
|
|
3570
|
+
const mrs = await (0, gitlab_1.doGitlabRequest)(io, `projects/${projectId}/merge_requests?state=opened&source_branch=${encodeURIComponent(branch)}`);
|
|
3571
|
+
if (!(mrs === null || mrs === void 0 ? void 0 : mrs.length)) {
|
|
3572
|
+
throw new Error(`no open merge request found for branch '${branch}' — pass one with --mr <iid>`);
|
|
3573
|
+
}
|
|
3574
|
+
return mrs[0];
|
|
3575
|
+
};
|
|
3576
|
+
const ensurePinLabelExists = async (io, projectId, pinLabel) => {
|
|
3577
|
+
const existing = await (0, gitlab_1.doGitlabRequest)(io, `projects/${projectId}/labels?search=${encodeURIComponent(pinLabel)}`);
|
|
3578
|
+
if (existing === null || existing === void 0 ? void 0 : existing.some((label) => label.name === pinLabel)) {
|
|
3579
|
+
return;
|
|
3580
|
+
}
|
|
3581
|
+
await (0, gitlab_1.doGitlabRequest)(io, `projects/${projectId}/labels`, {
|
|
3582
|
+
name: pinLabel,
|
|
3583
|
+
color: PIN_LABEL_COLOR,
|
|
3584
|
+
description: "review apps of this MR are pinned — deploys use auto_stop_in: never (managed by catladder)",
|
|
3585
|
+
}, "POST");
|
|
3586
|
+
io.log(`created the '${pinLabel}' label in the project`);
|
|
3587
|
+
};
|
|
3588
|
+
exports.commandMrPin = (0, defineCommand_1.defineCommand)({
|
|
3589
|
+
name: "mr pin",
|
|
3590
|
+
description: "pin the review apps of a merge request (disable their auto-stop) by adding the pin label; merging or closing the MR still stops them",
|
|
3591
|
+
group: "mr",
|
|
3592
|
+
inputs: {
|
|
3593
|
+
mr: {
|
|
3594
|
+
type: "number",
|
|
3595
|
+
message: "merge request IID (defaults to the open MR of the current branch)",
|
|
3596
|
+
positional: true,
|
|
3597
|
+
required: false,
|
|
3598
|
+
},
|
|
3599
|
+
pipeline: {
|
|
3600
|
+
type: "boolean",
|
|
3601
|
+
message: "trigger a merge-request pipeline so the pin takes effect immediately",
|
|
3602
|
+
required: false,
|
|
3603
|
+
},
|
|
3604
|
+
},
|
|
3605
|
+
execute: async (ctx) => {
|
|
3606
|
+
var _a, _b;
|
|
3607
|
+
const pinLabel = await getPinLabel();
|
|
3608
|
+
const { id: projectId } = await (0, gitlab_1.getProjectInfo)(ctx);
|
|
3609
|
+
const mr = await findMr(ctx, projectId, await ctx.get("mr"));
|
|
3610
|
+
await ensurePinLabelExists(ctx, projectId, pinLabel);
|
|
3611
|
+
if ((_a = mr.labels) === null || _a === void 0 ? void 0 : _a.includes(pinLabel)) {
|
|
3612
|
+
ctx.log(`already pinned: mr!${mr.iid} carries the '${pinLabel}' label`);
|
|
3613
|
+
}
|
|
3614
|
+
else {
|
|
3615
|
+
await (0, gitlab_1.doGitlabRequest)(ctx, `projects/${projectId}/merge_requests/${mr.iid}`, { add_labels: pinLabel }, "PUT");
|
|
3616
|
+
ctx.log(`📌 pinned mr!${mr.iid} "${mr.title}" — label '${pinLabel}' added`);
|
|
3617
|
+
}
|
|
3618
|
+
// the label only affects pipelines created after it was set, so
|
|
3619
|
+
// trigger one — otherwise the currently deployed review apps keep
|
|
3620
|
+
// their old auto-stop timer until the next push
|
|
3621
|
+
if ((_b = (await ctx.get("pipeline"))) !== null && _b !== void 0 ? _b : true) {
|
|
3622
|
+
const pipeline = await (0, gitlab_1.doGitlabRequest)(ctx, `projects/${projectId}/merge_requests/${mr.iid}/pipelines`, {}, "POST");
|
|
3623
|
+
ctx.log(`🚀 triggered a pipeline so the pin takes effect now: ${pipeline.web_url}`);
|
|
3624
|
+
}
|
|
3625
|
+
else {
|
|
3626
|
+
ctx.log("the pin takes effect with the next pipeline of the MR");
|
|
3627
|
+
}
|
|
3628
|
+
},
|
|
3629
|
+
});
|
|
3630
|
+
exports.commandMrUnpin = (0, defineCommand_1.defineCommand)({
|
|
3631
|
+
name: "mr unpin",
|
|
3632
|
+
description: "unpin the review apps of a merge request — the auto-stop timer re-arms with the next deploy",
|
|
3633
|
+
group: "mr",
|
|
3634
|
+
inputs: {
|
|
3635
|
+
mr: {
|
|
3636
|
+
type: "number",
|
|
3637
|
+
message: "merge request IID (defaults to the open MR of the current branch)",
|
|
3638
|
+
positional: true,
|
|
3639
|
+
required: false,
|
|
3640
|
+
},
|
|
3641
|
+
},
|
|
3642
|
+
execute: async (ctx) => {
|
|
3643
|
+
var _a;
|
|
3644
|
+
const pinLabel = await getPinLabel();
|
|
3645
|
+
const { id: projectId } = await (0, gitlab_1.getProjectInfo)(ctx);
|
|
3646
|
+
const mr = await findMr(ctx, projectId, await ctx.get("mr"));
|
|
3647
|
+
if (!((_a = mr.labels) === null || _a === void 0 ? void 0 : _a.includes(pinLabel))) {
|
|
3648
|
+
ctx.log(`mr!${mr.iid} is not pinned (no '${pinLabel}' label)`);
|
|
3649
|
+
return;
|
|
3650
|
+
}
|
|
3651
|
+
await (0, gitlab_1.doGitlabRequest)(ctx, `projects/${projectId}/merge_requests/${mr.iid}`, { remove_labels: pinLabel }, "PUT");
|
|
3652
|
+
ctx.log(`unpinned mr!${mr.iid} — label '${pinLabel}' removed`);
|
|
3653
|
+
ctx.log("the deployed review apps stay pinned until the next deploy re-arms their auto-stop timer");
|
|
3654
|
+
},
|
|
3655
|
+
});
|
|
3656
|
+
//# sourceMappingURL=commandMrPin.js.map
|
|
3657
|
+
|
|
3658
|
+
/***/ }),
|
|
3659
|
+
|
|
3445
3660
|
/***/ 30119:
|
|
3446
3661
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
3447
3662
|
|
|
@@ -3874,131 +4089,12 @@ exports.commandSecretsClearBackups = (0, defineCommand_1.defineCommand)({
|
|
|
3874
4089
|
"use strict";
|
|
3875
4090
|
|
|
3876
4091
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3877
|
-
exports.commandSecretsSyncGithub =
|
|
4092
|
+
exports.commandSecretsSyncGithub = void 0;
|
|
3878
4093
|
const pipeline_1 = __nccwpck_require__(53695);
|
|
3879
4094
|
const getProjectConfig_1 = __nccwpck_require__(70478);
|
|
3880
4095
|
const defineCommand_1 = __nccwpck_require__(19096);
|
|
4096
|
+
const secrets_1 = __nccwpck_require__(85200);
|
|
3881
4097
|
const github_1 = __nccwpck_require__(41353);
|
|
3882
|
-
/**
|
|
3883
|
-
* all secrets declared in the config, with their values read from the
|
|
3884
|
-
* vault (github secrets are write-only and can never act as a source)
|
|
3885
|
-
*/
|
|
3886
|
-
const collectSecretsFromVault = async (io, envFilter) => {
|
|
3887
|
-
const envAndComponents = await (0, getProjectConfig_1.getAllComponentsWithAllEnvsHierarchical)();
|
|
3888
|
-
const kinds = new Map();
|
|
3889
|
-
for (const [componentName, envs] of Object.entries(envAndComponents)) {
|
|
3890
|
-
for (const env of envs) {
|
|
3891
|
-
if (envFilter && !envFilter.includes(env)) {
|
|
3892
|
-
continue;
|
|
3893
|
-
}
|
|
3894
|
-
const { secretEnvVarKeys, jobOnlyVars } = await (0, getProjectConfig_1.getEnvironment)(env, componentName);
|
|
3895
|
-
const keys = [
|
|
3896
|
-
...secretEnvVarKeys,
|
|
3897
|
-
...jobOnlyVars.build.secretEnvVarKeys,
|
|
3898
|
-
...jobOnlyVars.deploy.secretEnvVarKeys,
|
|
3899
|
-
];
|
|
3900
|
-
keys.forEach(({ key, kind }) => kinds.set((0, pipeline_1.getSecretVarName)(env, componentName, key), kind !== null && kind !== void 0 ? kind : "secret"));
|
|
3901
|
-
}
|
|
3902
|
-
}
|
|
3903
|
-
const names = [...kinds.keys()];
|
|
3904
|
-
const values = await (await io.getVaultManager()).readSecrets(names, io);
|
|
3905
|
-
const secrets = names
|
|
3906
|
-
.filter((name) => values[name] !== undefined)
|
|
3907
|
-
.map((name) => {
|
|
3908
|
-
var _a;
|
|
3909
|
-
return ({
|
|
3910
|
-
name,
|
|
3911
|
-
value: values[name],
|
|
3912
|
-
kind: (_a = kinds.get(name)) !== null && _a !== void 0 ? _a : "secret",
|
|
3913
|
-
});
|
|
3914
|
-
});
|
|
3915
|
-
const missing = names.filter((name) => values[name] === undefined);
|
|
3916
|
-
return { secrets, missing };
|
|
3917
|
-
};
|
|
3918
|
-
exports.collectSecretsFromVault = collectSecretsFromVault;
|
|
3919
|
-
/** marker for repo-level (environment-less) targets */
|
|
3920
|
-
const REPO_LEVEL = "";
|
|
3921
|
-
/**
|
|
3922
|
-
* derives which github environment(s) each secret/variable must live in
|
|
3923
|
-
* by scanning the GENERATED workflows: a `${{ secrets.X }}` / `${{
|
|
3924
|
-
* vars.X }}` reference in a job's env targets that job's environment
|
|
3925
|
-
* (or the repo level when the job has none). Deriving from the real
|
|
3926
|
-
* output means the sync can never drift from what the workflows expect.
|
|
3927
|
-
*
|
|
3928
|
-
* Environment secrets are the answer to github's cap of 100 secrets
|
|
3929
|
-
* per REPO (a multi-env project easily exceeds it): the cap applies
|
|
3930
|
-
* per environment instead.
|
|
3931
|
-
*/
|
|
3932
|
-
const collectSecretTargets = async (config) => {
|
|
3933
|
-
var _a;
|
|
3934
|
-
const workflows = await new pipeline_1.GithubBackend().createWorkflows(config);
|
|
3935
|
-
const targets = new Map();
|
|
3936
|
-
for (const workflow of Object.values(workflows)) {
|
|
3937
|
-
for (const job of Object.values(workflow.jobs)) {
|
|
3938
|
-
const environment = typeof job.environment === "object"
|
|
3939
|
-
? job.environment.name
|
|
3940
|
-
: job.environment;
|
|
3941
|
-
for (const value of Object.values((_a = job.env) !== null && _a !== void 0 ? _a : {})) {
|
|
3942
|
-
if (typeof value !== "string")
|
|
3943
|
-
continue;
|
|
3944
|
-
for (const match of value.matchAll(/\$\{\{\s*(?:secrets|vars)\.([A-Za-z0-9_]+)\s*\}\}/g)) {
|
|
3945
|
-
const name = match[1];
|
|
3946
|
-
if (!targets.has(name)) {
|
|
3947
|
-
targets.set(name, new Set());
|
|
3948
|
-
}
|
|
3949
|
-
targets.get(name).add(environment !== null && environment !== void 0 ? environment : REPO_LEVEL);
|
|
3950
|
-
}
|
|
3951
|
-
}
|
|
3952
|
-
}
|
|
3953
|
-
}
|
|
3954
|
-
return targets;
|
|
3955
|
-
};
|
|
3956
|
-
exports.collectSecretTargets = collectSecretTargets;
|
|
3957
|
-
/**
|
|
3958
|
-
* pushes vault values to github via the gh cli: sensitive ones as
|
|
3959
|
-
* secrets (masked), "variable"-kind ones as variables (plain) — each
|
|
3960
|
-
* into the environment(s) whose jobs reference them
|
|
3961
|
-
*/
|
|
3962
|
-
const pushSecretsToGithub = async (io, repo, secrets, targets) => {
|
|
3963
|
-
const environments = [
|
|
3964
|
-
...new Set([...targets.values()].flatMap((envs) => [...envs].filter((env) => env !== REPO_LEVEL))),
|
|
3965
|
-
];
|
|
3966
|
-
for (const environment of environments) {
|
|
3967
|
-
await (0, github_1.ensureGithubEnvironment)(repo, environment);
|
|
3968
|
-
io.log(`🌍 environment ${environment}`);
|
|
3969
|
-
}
|
|
3970
|
-
for (const { name, value, kind } of secrets) {
|
|
3971
|
-
const envs = targets.get(name);
|
|
3972
|
-
if (!envs) {
|
|
3973
|
-
io.log(`⏭️ ${name} (not referenced by any generated workflow)`);
|
|
3974
|
-
continue;
|
|
3975
|
-
}
|
|
3976
|
-
for (const environment of envs) {
|
|
3977
|
-
const suffix = environment === REPO_LEVEL ? "" : ` → ${environment}`;
|
|
3978
|
-
if (kind === "variable") {
|
|
3979
|
-
await (0, github_1.setGithubVariable)(repo, name, value, environment || undefined);
|
|
3980
|
-
io.log(`📖 ${name} (variable)${suffix}`);
|
|
3981
|
-
}
|
|
3982
|
-
else {
|
|
3983
|
-
await (0, github_1.setGithubSecret)(repo, name, value, environment || undefined);
|
|
3984
|
-
io.log(`✅ ${name}${suffix}`);
|
|
3985
|
-
}
|
|
3986
|
-
}
|
|
3987
|
-
}
|
|
3988
|
-
};
|
|
3989
|
-
exports.pushSecretsToGithub = pushSecretsToGithub;
|
|
3990
|
-
/**
|
|
3991
|
-
* resolves the github repository from the configured git remote
|
|
3992
|
-
* (`pipelines.github.gitRemote`, defaults to origin)
|
|
3993
|
-
*/
|
|
3994
|
-
const getConfiguredGithubRepo = async () => {
|
|
3995
|
-
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
3996
|
-
if (!config) {
|
|
3997
|
-
return undefined;
|
|
3998
|
-
}
|
|
3999
|
-
return (0, github_1.getGithubRepoFromRemote)((0, pipeline_1.getPipelineGitRemote)(config, "github"));
|
|
4000
|
-
};
|
|
4001
|
-
exports.getConfiguredGithubRepo = getConfiguredGithubRepo;
|
|
4002
4098
|
/**
|
|
4003
4099
|
* copies the catladder secrets from the vault to github actions
|
|
4004
4100
|
* repository secrets, keeping the exact same names, so the github
|
|
@@ -4035,12 +4131,12 @@ exports.commandSecretsSyncGithub = (0, defineCommand_1.defineCommand)({
|
|
|
4035
4131
|
if (!(await (0, github_1.isGhAuthenticated)())) {
|
|
4036
4132
|
throw new Error("the github cli (gh) is not installed or not authenticated — run `gh auth login` first");
|
|
4037
4133
|
}
|
|
4038
|
-
const repo = (_a = (await ctx.get("repo"))) !== null && _a !== void 0 ? _a : (await (0,
|
|
4134
|
+
const repo = (_a = (await ctx.get("repo"))) !== null && _a !== void 0 ? _a : (await (0, secrets_1.getConfiguredGithubRepo)());
|
|
4039
4135
|
if (!repo) {
|
|
4040
4136
|
throw new Error(`no github repository found on the '${(0, pipeline_1.getPipelineGitRemote)(config, "github")}' remote — pass it as owner/name or configure pipelines.github.gitRemote`);
|
|
4041
4137
|
}
|
|
4042
4138
|
const envFilter = (_b = (await ctx.get("env"))) === null || _b === void 0 ? void 0 : _b.split(",").map((e) => e.trim());
|
|
4043
|
-
const { secrets, missing } = await (0,
|
|
4139
|
+
const { secrets, missing } = await (0, secrets_1.collectSecretsFromVault)(ctx, envFilter);
|
|
4044
4140
|
if (missing.length > 0) {
|
|
4045
4141
|
ctx.log(`⚠️ ${missing.length} secrets are not set in the vault and will be skipped:`);
|
|
4046
4142
|
missing.forEach((name) => ctx.log(` - ${name}`));
|
|
@@ -4057,7 +4153,7 @@ exports.commandSecretsSyncGithub = (0, defineCommand_1.defineCommand)({
|
|
|
4057
4153
|
if (!confirmed) {
|
|
4058
4154
|
throw new Error("abort");
|
|
4059
4155
|
}
|
|
4060
|
-
await (0,
|
|
4156
|
+
await (0, secrets_1.pushSecretsToGithub)(ctx, repo, secrets, await (0, secrets_1.collectSecretTargets)(config));
|
|
4061
4157
|
ctx.log("");
|
|
4062
4158
|
ctx.log("done! 😻 the github pipeline can use them as ${{ secrets.<NAME> }}");
|
|
4063
4159
|
},
|
|
@@ -4621,6 +4717,7 @@ const fs_extra_1 = __nccwpck_require__(20925);
|
|
|
4621
4717
|
const yaml_1 = __nccwpck_require__(99292);
|
|
4622
4718
|
const defineCommand_1 = __nccwpck_require__(19096);
|
|
4623
4719
|
const readStdin_1 = __nccwpck_require__(89973);
|
|
4720
|
+
const secrets_1 = __nccwpck_require__(85200);
|
|
4624
4721
|
const document_1 = __nccwpck_require__(96716);
|
|
4625
4722
|
const scope_1 = __nccwpck_require__(8513);
|
|
4626
4723
|
const parseKeysInput_1 = __nccwpck_require__(93560);
|
|
@@ -4683,7 +4780,7 @@ exports.commandSecretsPush = (0, defineCommand_1.defineCommand)({
|
|
|
4683
4780
|
if (!confirmed) {
|
|
4684
4781
|
throw new Error("abort");
|
|
4685
4782
|
}
|
|
4686
|
-
await (0,
|
|
4783
|
+
await (0, secrets_1.writeSecretsAndMirror)(ctx, writes);
|
|
4687
4784
|
ctx.log("done! 😻");
|
|
4688
4785
|
},
|
|
4689
4786
|
});
|
|
@@ -4701,7 +4798,7 @@ exports.commandSecretsSet = void 0;
|
|
|
4701
4798
|
const fs_extra_1 = __nccwpck_require__(20925);
|
|
4702
4799
|
const defineCommand_1 = __nccwpck_require__(19096);
|
|
4703
4800
|
const readStdin_1 = __nccwpck_require__(89973);
|
|
4704
|
-
const
|
|
4801
|
+
const secrets_1 = __nccwpck_require__(85200);
|
|
4705
4802
|
const scope_1 = __nccwpck_require__(8513);
|
|
4706
4803
|
const resolveValue = async (io, value, valueFile) => {
|
|
4707
4804
|
if (valueFile) {
|
|
@@ -4772,7 +4869,7 @@ exports.commandSecretsSet = (0, defineCommand_1.defineCommand)({
|
|
|
4772
4869
|
componentName,
|
|
4773
4870
|
secrets: { [key]: value },
|
|
4774
4871
|
}));
|
|
4775
|
-
await (0,
|
|
4872
|
+
await (0, secrets_1.writeSecretsAndMirror)(ctx, writes);
|
|
4776
4873
|
ctx.log("done! 😻");
|
|
4777
4874
|
},
|
|
4778
4875
|
});
|
|
@@ -4786,12 +4883,8 @@ exports.commandSecretsSet = (0, defineCommand_1.defineCommand)({
|
|
|
4786
4883
|
"use strict";
|
|
4787
4884
|
|
|
4788
4885
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4789
|
-
exports.
|
|
4886
|
+
exports.collectSecretsWrites = exports.checkSecretsDocument = exports.buildSecretsDocument = exports.FILL_ME = void 0;
|
|
4790
4887
|
const pipeline_1 = __nccwpck_require__(53695);
|
|
4791
|
-
const getProjectConfig_1 = __nccwpck_require__(70478);
|
|
4792
|
-
const github_1 = __nccwpck_require__(41353);
|
|
4793
|
-
const gitlab_1 = __nccwpck_require__(17697);
|
|
4794
|
-
const commandSecretsSyncGithub_1 = __nccwpck_require__(27565);
|
|
4795
4888
|
/** placeholder for secrets that have no value in the vault yet */
|
|
4796
4889
|
exports.FILL_ME = "🚨 FILL ME";
|
|
4797
4890
|
/* for convenience, parse json values. that makes it easier to edit secrets that are objects */
|
|
@@ -4889,80 +4982,6 @@ const collectSecretsWrites = (document, scoped) => {
|
|
|
4889
4982
|
return { writes, skipped };
|
|
4890
4983
|
};
|
|
4891
4984
|
exports.collectSecretsWrites = collectSecretsWrites;
|
|
4892
|
-
/**
|
|
4893
|
-
* writes secrets to the vault (the source of truth) and mirrors them
|
|
4894
|
-
* to every enabled CI backend — which backends exist is invisible to
|
|
4895
|
-
* the caller
|
|
4896
|
-
*/
|
|
4897
|
-
const writeSecretsAndMirror = async (io, writes) => {
|
|
4898
|
-
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
4899
|
-
if (!config) {
|
|
4900
|
-
throw new Error("no catladder config found");
|
|
4901
|
-
}
|
|
4902
|
-
io.log("");
|
|
4903
|
-
io.log("writing secrets to the vault, please wait...");
|
|
4904
|
-
io.log("");
|
|
4905
|
-
for (const { env, componentName, secrets } of writes) {
|
|
4906
|
-
io.log("writing " + env + ":" + componentName + "...\n");
|
|
4907
|
-
await (await io.getVaultManager()).writeSecrets(env, componentName, secrets);
|
|
4908
|
-
io.log("");
|
|
4909
|
-
io.log("✅ " + env + ":" + componentName);
|
|
4910
|
-
io.log("--------------------------------\n");
|
|
4911
|
-
}
|
|
4912
|
-
await mirrorSecretsToCiBackends(io, config, writes);
|
|
4913
|
-
};
|
|
4914
|
-
exports.writeSecretsAndMirror = writeSecretsAndMirror;
|
|
4915
|
-
/**
|
|
4916
|
-
* the vault is the source of truth; every enabled CI backend receives
|
|
4917
|
-
* a mirrored copy of the written secrets (gitlab variables, github
|
|
4918
|
-
* secrets), so all CI systems stay in sync
|
|
4919
|
-
*/
|
|
4920
|
-
const mirrorSecretsToCiBackends = async (io, config, writes) => {
|
|
4921
|
-
const enabled = (0, pipeline_1.getEnabledPipelineTypes)(config);
|
|
4922
|
-
// gitlab mirror (unless gitlab is the vault itself, then it is
|
|
4923
|
-
// already written)
|
|
4924
|
-
if ((0, pipeline_1.getVaultConfig)(config).type !== "gitlab" && enabled.includes("gitlab")) {
|
|
4925
|
-
for (const { env, componentName, secrets } of writes) {
|
|
4926
|
-
await (0, gitlab_1.upsertAllVariables)(io, secrets, env, componentName);
|
|
4927
|
-
}
|
|
4928
|
-
io.log("✅ mirrored to gitlab");
|
|
4929
|
-
}
|
|
4930
|
-
if (!enabled.includes("github")) {
|
|
4931
|
-
return;
|
|
4932
|
-
}
|
|
4933
|
-
const kinds = new Map();
|
|
4934
|
-
for (const { env, componentName } of writes) {
|
|
4935
|
-
const { secretEnvVarKeys, jobOnlyVars } = await (0, getProjectConfig_1.getEnvironment)(env, componentName);
|
|
4936
|
-
[
|
|
4937
|
-
...secretEnvVarKeys,
|
|
4938
|
-
...jobOnlyVars.build.secretEnvVarKeys,
|
|
4939
|
-
...jobOnlyVars.deploy.secretEnvVarKeys,
|
|
4940
|
-
].forEach(({ key, kind }) => kinds.set((0, pipeline_1.getSecretVarName)(env, componentName, key), kind !== null && kind !== void 0 ? kind : "secret"));
|
|
4941
|
-
}
|
|
4942
|
-
const secrets = writes.flatMap(({ env, componentName, secrets }) => Object.entries(secrets).map(([key, value]) => {
|
|
4943
|
-
var _a;
|
|
4944
|
-
const name = (0, pipeline_1.getSecretVarName)(env, componentName, key);
|
|
4945
|
-
return {
|
|
4946
|
-
name,
|
|
4947
|
-
value: typeof value === "string" ? value : JSON.stringify(value !== null && value !== void 0 ? value : ""),
|
|
4948
|
-
kind: (_a = kinds.get(name)) !== null && _a !== void 0 ? _a : "secret",
|
|
4949
|
-
};
|
|
4950
|
-
}));
|
|
4951
|
-
if (secrets.length === 0) {
|
|
4952
|
-
return;
|
|
4953
|
-
}
|
|
4954
|
-
if (!(await (0, github_1.isGhAuthenticated)())) {
|
|
4955
|
-
io.log("⚠️ github pipeline is enabled, but the github cli (gh) is not authenticated — run `project secrets-sync-github` later to mirror the secrets");
|
|
4956
|
-
return;
|
|
4957
|
-
}
|
|
4958
|
-
const repo = await (0, commandSecretsSyncGithub_1.getConfiguredGithubRepo)();
|
|
4959
|
-
if (!repo) {
|
|
4960
|
-
io.log("⚠️ github pipeline is enabled, but no github repository was found — run `project secrets-sync-github` later to mirror the secrets");
|
|
4961
|
-
return;
|
|
4962
|
-
}
|
|
4963
|
-
io.log(`mirroring ${secrets.length} secrets to github ('${repo}')...`);
|
|
4964
|
-
await (0, commandSecretsSyncGithub_1.pushSecretsToGithub)(io, repo, secrets, await (0, commandSecretsSyncGithub_1.collectSecretTargets)(config));
|
|
4965
|
-
};
|
|
4966
4985
|
//# sourceMappingURL=document.js.map
|
|
4967
4986
|
|
|
4968
4987
|
/***/ }),
|
|
@@ -6060,7 +6079,7 @@ const hash = (str, length) => {
|
|
|
6060
6079
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6061
6080
|
exports.upsertGcloudServiceAccountAndSaveSecret = exports.accountExists = void 0;
|
|
6062
6081
|
const child_process_promise_1 = __nccwpck_require__(11542);
|
|
6063
|
-
const
|
|
6082
|
+
const secrets_1 = __nccwpck_require__(85200);
|
|
6064
6083
|
const serviceAccountNames_1 = __nccwpck_require__(67851);
|
|
6065
6084
|
const accountExists = async (fullIdentifier) => {
|
|
6066
6085
|
try {
|
|
@@ -6097,9 +6116,20 @@ const upsertGcloudServiceAccount = async (context, account) => {
|
|
|
6097
6116
|
const upsertGcloudServiceAccountAndSaveSecret = async (instance, context, account, secretName) => {
|
|
6098
6117
|
instance.log("upserting service account " + account.name + "...");
|
|
6099
6118
|
const key = await upsertGcloudServiceAccount(context, account);
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6119
|
+
// through the vault (and from there to every enabled ci backend) —
|
|
6120
|
+
// the key is a secret like any other, the deploy jobs read it under
|
|
6121
|
+
// its declared name. Writing it to gitlab directly would break every
|
|
6122
|
+
// project that has no gitlab.
|
|
6123
|
+
await (0, secrets_1.writeSecretsAndMirror)(instance, [
|
|
6124
|
+
{
|
|
6125
|
+
env: context.env,
|
|
6126
|
+
componentName: context.name,
|
|
6127
|
+
secrets: { [secretName]: key },
|
|
6128
|
+
},
|
|
6129
|
+
],
|
|
6130
|
+
// a fresh key is created on every run, the previous one is deleted
|
|
6131
|
+
// at google — a backup copy of it would only be a dead secret
|
|
6132
|
+
{ backup: false });
|
|
6103
6133
|
instance.log("done!");
|
|
6104
6134
|
};
|
|
6105
6135
|
exports.upsertGcloudServiceAccountAndSaveSecret = upsertGcloudServiceAccountAndSaveSecret;
|
|
@@ -6279,97 +6309,352 @@ const getProjectPvcs = async (envComponent) => {
|
|
|
6279
6309
|
const res = await k8sApi.listNamespacedPersistentVolumeClaim(namespace);
|
|
6280
6310
|
return res.body.items;
|
|
6281
6311
|
};
|
|
6282
|
-
exports.getProjectPvcs = getProjectPvcs;
|
|
6283
|
-
const getProjectPodNames = async (envComponent) => {
|
|
6284
|
-
const pods = await (0, exports.getProjectPods)(envComponent);
|
|
6285
|
-
return pods.map((n) => n.metadata.name);
|
|
6312
|
+
exports.getProjectPvcs = getProjectPvcs;
|
|
6313
|
+
const getProjectPodNames = async (envComponent) => {
|
|
6314
|
+
const pods = await (0, exports.getProjectPods)(envComponent);
|
|
6315
|
+
return pods.map((n) => n.metadata.name);
|
|
6316
|
+
};
|
|
6317
|
+
exports.getProjectPodNames = getProjectPodNames;
|
|
6318
|
+
//# sourceMappingURL=index.js.map
|
|
6319
|
+
|
|
6320
|
+
/***/ }),
|
|
6321
|
+
|
|
6322
|
+
/***/ 14178:
|
|
6323
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6324
|
+
|
|
6325
|
+
"use strict";
|
|
6326
|
+
|
|
6327
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6328
|
+
exports.openGoogleCloudKubernetesDashboard = exports.openGoogleCloudLogs = void 0;
|
|
6329
|
+
const pipeline_1 = __nccwpck_require__(53695);
|
|
6330
|
+
const openDashboard_1 = __nccwpck_require__(74241);
|
|
6331
|
+
const openGoogleCloudLogs = async (instance, context) => {
|
|
6332
|
+
var _a;
|
|
6333
|
+
const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
|
|
6334
|
+
if (!(0, pipeline_1.isOfDeployType)(deployConfig, "kubernetes")) {
|
|
6335
|
+
throw new Error("context is not of type kubernetes");
|
|
6336
|
+
}
|
|
6337
|
+
if (!deployConfig.cluster || deployConfig.cluster.type !== "gcloud") {
|
|
6338
|
+
throw new Error("no gcloud custer configured");
|
|
6339
|
+
}
|
|
6340
|
+
const namespace = context.environment.envVars.KUBE_NAMESPACE;
|
|
6341
|
+
const cluster = deployConfig.cluster;
|
|
6342
|
+
const resource = `k8s_container/cluster_name/${cluster.name}${namespace ? `/namespace_name/${namespace}` : ""}`;
|
|
6343
|
+
await (0, openDashboard_1.openGoogleCloudDashboard)(instance, "logs/viewer", {
|
|
6344
|
+
project: cluster.projectId,
|
|
6345
|
+
resource: resource,
|
|
6346
|
+
});
|
|
6347
|
+
};
|
|
6348
|
+
exports.openGoogleCloudLogs = openGoogleCloudLogs;
|
|
6349
|
+
const openGoogleCloudKubernetesDashboard = async (instance, context) => {
|
|
6350
|
+
var _a;
|
|
6351
|
+
const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
|
|
6352
|
+
if (!(0, pipeline_1.isOfDeployType)(deployConfig, "kubernetes")) {
|
|
6353
|
+
throw new Error("context is not of type kubernetes");
|
|
6354
|
+
}
|
|
6355
|
+
if (!deployConfig.cluster || deployConfig.cluster.type !== "gcloud") {
|
|
6356
|
+
throw new Error("no gcloud custer configured");
|
|
6357
|
+
}
|
|
6358
|
+
const namespace = context.environment.envVars.KUBE_NAMESPACE;
|
|
6359
|
+
const cluster = deployConfig.cluster;
|
|
6360
|
+
const pageState = `("savedViews":("c":["gke/${cluster.region}/${cluster.name}"],"n":["${namespace}"],"i":"4e42e0b9cd6147f8a4fba7516752ec48"))`;
|
|
6361
|
+
await (0, openDashboard_1.openGoogleCloudDashboard)(instance, "kubernetes/workload", {
|
|
6362
|
+
project: cluster.projectId,
|
|
6363
|
+
pageState: pageState,
|
|
6364
|
+
});
|
|
6365
|
+
};
|
|
6366
|
+
exports.openGoogleCloudKubernetesDashboard = openGoogleCloudKubernetesDashboard;
|
|
6367
|
+
//# sourceMappingURL=openKubernetesDashboards.js.map
|
|
6368
|
+
|
|
6369
|
+
/***/ }),
|
|
6370
|
+
|
|
6371
|
+
/***/ 76775:
|
|
6372
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6373
|
+
|
|
6374
|
+
"use strict";
|
|
6375
|
+
|
|
6376
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6377
|
+
exports.startKubePortForward = void 0;
|
|
6378
|
+
const portForwards_1 = __nccwpck_require__(5368);
|
|
6379
|
+
const startKubePortForward = async (podname, localPort, remotePort, namespace) => {
|
|
6380
|
+
const name = `kube/${namespace}/${podname}/${localPort}:${remotePort}`;
|
|
6381
|
+
await (0, portForwards_1.startPortForwardCommand)(name, `kubectl port-forward ${podname} ${localPort}:${remotePort} -n ${namespace}`);
|
|
6382
|
+
};
|
|
6383
|
+
exports.startKubePortForward = startKubePortForward;
|
|
6384
|
+
//# sourceMappingURL=portForward.js.map
|
|
6385
|
+
|
|
6386
|
+
/***/ }),
|
|
6387
|
+
|
|
6388
|
+
/***/ 55689:
|
|
6389
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
6390
|
+
|
|
6391
|
+
"use strict";
|
|
6392
|
+
|
|
6393
|
+
// we can't import the package.json directly, because the bundling process will inline it
|
|
6394
|
+
// but the version is only set during deployement, when its already bundled
|
|
6395
|
+
// instead we need to use require.main.path to get the path of the main module, which is actually the file in the bin
|
|
6396
|
+
// this will point to the root package.json
|
|
6397
|
+
var _a;
|
|
6398
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6399
|
+
const path = ((_a = require.main) === null || _a === void 0 ? void 0 : _a.path) + "/../package.json";
|
|
6400
|
+
const ownPkg = require(path);
|
|
6401
|
+
exports["default"] = ownPkg;
|
|
6402
|
+
//# sourceMappingURL=packageInfos.js.map
|
|
6403
|
+
|
|
6404
|
+
/***/ }),
|
|
6405
|
+
|
|
6406
|
+
/***/ 97245:
|
|
6407
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6408
|
+
|
|
6409
|
+
"use strict";
|
|
6410
|
+
|
|
6411
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6412
|
+
exports.getConfiguredGithubRepo = exports.pushSecretsToGithub = exports.collectSecretTargets = exports.collectSecretsFromVault = void 0;
|
|
6413
|
+
const pipeline_1 = __nccwpck_require__(53695);
|
|
6414
|
+
const getProjectConfig_1 = __nccwpck_require__(70478);
|
|
6415
|
+
const github_1 = __nccwpck_require__(41353);
|
|
6416
|
+
/**
|
|
6417
|
+
* all secrets declared in the config, with their values read from the
|
|
6418
|
+
* vault (github secrets are write-only and can never act as a source)
|
|
6419
|
+
*/
|
|
6420
|
+
const collectSecretsFromVault = async (io, envFilter) => {
|
|
6421
|
+
const envAndComponents = await (0, getProjectConfig_1.getAllComponentsWithAllEnvsHierarchical)();
|
|
6422
|
+
const kinds = new Map();
|
|
6423
|
+
for (const [componentName, envs] of Object.entries(envAndComponents)) {
|
|
6424
|
+
for (const env of envs) {
|
|
6425
|
+
if (envFilter && !envFilter.includes(env)) {
|
|
6426
|
+
continue;
|
|
6427
|
+
}
|
|
6428
|
+
const { secretEnvVarKeys, jobOnlyVars } = await (0, getProjectConfig_1.getEnvironment)(env, componentName);
|
|
6429
|
+
const keys = [
|
|
6430
|
+
...secretEnvVarKeys,
|
|
6431
|
+
...jobOnlyVars.build.secretEnvVarKeys,
|
|
6432
|
+
...jobOnlyVars.deploy.secretEnvVarKeys,
|
|
6433
|
+
];
|
|
6434
|
+
keys.forEach(({ key, kind }) => kinds.set((0, pipeline_1.getSecretVarName)(env, componentName, key), kind !== null && kind !== void 0 ? kind : "secret"));
|
|
6435
|
+
}
|
|
6436
|
+
}
|
|
6437
|
+
const names = [...kinds.keys()];
|
|
6438
|
+
const values = await (await io.getVaultManager()).readSecrets(names, io);
|
|
6439
|
+
const secrets = names
|
|
6440
|
+
.filter((name) => values[name] !== undefined)
|
|
6441
|
+
.map((name) => {
|
|
6442
|
+
var _a;
|
|
6443
|
+
return ({
|
|
6444
|
+
name,
|
|
6445
|
+
value: values[name],
|
|
6446
|
+
kind: (_a = kinds.get(name)) !== null && _a !== void 0 ? _a : "secret",
|
|
6447
|
+
});
|
|
6448
|
+
});
|
|
6449
|
+
const missing = names.filter((name) => values[name] === undefined);
|
|
6450
|
+
return { secrets, missing };
|
|
6451
|
+
};
|
|
6452
|
+
exports.collectSecretsFromVault = collectSecretsFromVault;
|
|
6453
|
+
/** marker for repo-level (environment-less) targets */
|
|
6454
|
+
const REPO_LEVEL = "";
|
|
6455
|
+
/**
|
|
6456
|
+
* derives which github environment(s) each secret/variable must live in
|
|
6457
|
+
* by scanning the GENERATED workflows: a `${{ secrets.X }}` / `${{
|
|
6458
|
+
* vars.X }}` reference in a job's env targets that job's environment
|
|
6459
|
+
* (or the repo level when the job has none). Deriving from the real
|
|
6460
|
+
* output means the sync can never drift from what the workflows expect.
|
|
6461
|
+
*
|
|
6462
|
+
* Environment secrets are the answer to github's cap of 100 secrets
|
|
6463
|
+
* per REPO (a multi-env project easily exceeds it): the cap applies
|
|
6464
|
+
* per environment instead.
|
|
6465
|
+
*/
|
|
6466
|
+
const collectSecretTargets = async (config) => {
|
|
6467
|
+
var _a;
|
|
6468
|
+
const workflows = await new pipeline_1.GithubBackend().createWorkflows(config);
|
|
6469
|
+
const targets = new Map();
|
|
6470
|
+
for (const workflow of Object.values(workflows)) {
|
|
6471
|
+
for (const job of Object.values(workflow.jobs)) {
|
|
6472
|
+
const environment = typeof job.environment === "object"
|
|
6473
|
+
? job.environment.name
|
|
6474
|
+
: job.environment;
|
|
6475
|
+
for (const value of Object.values((_a = job.env) !== null && _a !== void 0 ? _a : {})) {
|
|
6476
|
+
if (typeof value !== "string")
|
|
6477
|
+
continue;
|
|
6478
|
+
for (const match of value.matchAll(/\$\{\{\s*(?:secrets|vars)\.([A-Za-z0-9_]+)\s*\}\}/g)) {
|
|
6479
|
+
const name = match[1];
|
|
6480
|
+
if (!targets.has(name)) {
|
|
6481
|
+
targets.set(name, new Set());
|
|
6482
|
+
}
|
|
6483
|
+
targets.get(name).add(environment !== null && environment !== void 0 ? environment : REPO_LEVEL);
|
|
6484
|
+
}
|
|
6485
|
+
}
|
|
6486
|
+
}
|
|
6487
|
+
}
|
|
6488
|
+
return targets;
|
|
6489
|
+
};
|
|
6490
|
+
exports.collectSecretTargets = collectSecretTargets;
|
|
6491
|
+
/**
|
|
6492
|
+
* pushes vault values to github via the gh cli: sensitive ones as
|
|
6493
|
+
* secrets (masked), "variable"-kind ones as variables (plain) — each
|
|
6494
|
+
* into the environment(s) whose jobs reference them
|
|
6495
|
+
*/
|
|
6496
|
+
const pushSecretsToGithub = async (io, repo, secrets, targets) => {
|
|
6497
|
+
const environments = [
|
|
6498
|
+
...new Set([...targets.values()].flatMap((envs) => [...envs].filter((env) => env !== REPO_LEVEL))),
|
|
6499
|
+
];
|
|
6500
|
+
for (const environment of environments) {
|
|
6501
|
+
await (0, github_1.ensureGithubEnvironment)(repo, environment);
|
|
6502
|
+
io.log(`🌍 environment ${environment}`);
|
|
6503
|
+
}
|
|
6504
|
+
for (const { name, value, kind } of secrets) {
|
|
6505
|
+
const envs = targets.get(name);
|
|
6506
|
+
if (!envs) {
|
|
6507
|
+
io.log(`⏭️ ${name} (not referenced by any generated workflow)`);
|
|
6508
|
+
continue;
|
|
6509
|
+
}
|
|
6510
|
+
for (const environment of envs) {
|
|
6511
|
+
const suffix = environment === REPO_LEVEL ? "" : ` → ${environment}`;
|
|
6512
|
+
if (kind === "variable") {
|
|
6513
|
+
await (0, github_1.setGithubVariable)(repo, name, value, environment || undefined);
|
|
6514
|
+
io.log(`📖 ${name} (variable)${suffix}`);
|
|
6515
|
+
}
|
|
6516
|
+
else {
|
|
6517
|
+
await (0, github_1.setGithubSecret)(repo, name, value, environment || undefined);
|
|
6518
|
+
io.log(`✅ ${name}${suffix}`);
|
|
6519
|
+
}
|
|
6520
|
+
}
|
|
6521
|
+
}
|
|
6522
|
+
};
|
|
6523
|
+
exports.pushSecretsToGithub = pushSecretsToGithub;
|
|
6524
|
+
/**
|
|
6525
|
+
* resolves the github repository from the configured git remote
|
|
6526
|
+
* (`pipelines.github.gitRemote`, defaults to origin)
|
|
6527
|
+
*/
|
|
6528
|
+
const getConfiguredGithubRepo = async () => {
|
|
6529
|
+
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
6530
|
+
if (!config) {
|
|
6531
|
+
return undefined;
|
|
6532
|
+
}
|
|
6533
|
+
return (0, github_1.getGithubRepoFromRemote)((0, pipeline_1.getPipelineGitRemote)(config, "github"));
|
|
6534
|
+
};
|
|
6535
|
+
exports.getConfiguredGithubRepo = getConfiguredGithubRepo;
|
|
6536
|
+
//# sourceMappingURL=github.js.map
|
|
6537
|
+
|
|
6538
|
+
/***/ }),
|
|
6539
|
+
|
|
6540
|
+
/***/ 85200:
|
|
6541
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
6542
|
+
|
|
6543
|
+
"use strict";
|
|
6544
|
+
|
|
6545
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6546
|
+
if (k2 === undefined) k2 = k;
|
|
6547
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6548
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6549
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
6550
|
+
}
|
|
6551
|
+
Object.defineProperty(o, k2, desc);
|
|
6552
|
+
}) : (function(o, m, k, k2) {
|
|
6553
|
+
if (k2 === undefined) k2 = k;
|
|
6554
|
+
o[k2] = m[k];
|
|
6555
|
+
}));
|
|
6556
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
6557
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
6286
6558
|
};
|
|
6287
|
-
exports
|
|
6559
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6560
|
+
__exportStar(__nccwpck_require__(97245), exports);
|
|
6561
|
+
__exportStar(__nccwpck_require__(31298), exports);
|
|
6288
6562
|
//# sourceMappingURL=index.js.map
|
|
6289
6563
|
|
|
6290
6564
|
/***/ }),
|
|
6291
6565
|
|
|
6292
|
-
/***/
|
|
6566
|
+
/***/ 31298:
|
|
6293
6567
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6294
6568
|
|
|
6295
6569
|
"use strict";
|
|
6296
6570
|
|
|
6297
6571
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6298
|
-
exports.
|
|
6572
|
+
exports.writeSecretsAndMirror = void 0;
|
|
6299
6573
|
const pipeline_1 = __nccwpck_require__(53695);
|
|
6300
|
-
const
|
|
6301
|
-
const
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6574
|
+
const getProjectConfig_1 = __nccwpck_require__(70478);
|
|
6575
|
+
const github_1 = __nccwpck_require__(41353);
|
|
6576
|
+
const gitlab_1 = __nccwpck_require__(17697);
|
|
6577
|
+
const github_2 = __nccwpck_require__(97245);
|
|
6578
|
+
/**
|
|
6579
|
+
* the one door for writing secret values: they go into the vault (the
|
|
6580
|
+
* source of truth) and are mirrored to every enabled CI backend —
|
|
6581
|
+
* which vault and which backends exist is invisible to the caller.
|
|
6582
|
+
*
|
|
6583
|
+
* Everything that produces a secret value must come through here: the
|
|
6584
|
+
* secrets commands, but also the credentials `project setup`
|
|
6585
|
+
* provisions (gcloud service account keys, kubernetes tokens).
|
|
6586
|
+
*/
|
|
6587
|
+
const writeSecretsAndMirror = async (io, writes, options = {}) => {
|
|
6588
|
+
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
6589
|
+
if (!config) {
|
|
6590
|
+
throw new Error("no catladder config found");
|
|
6306
6591
|
}
|
|
6307
|
-
|
|
6308
|
-
|
|
6592
|
+
io.log("");
|
|
6593
|
+
io.log("writing secrets to the vault, please wait...");
|
|
6594
|
+
io.log("");
|
|
6595
|
+
for (const { env, componentName, secrets } of writes) {
|
|
6596
|
+
io.log("writing " + env + ":" + componentName + "...\n");
|
|
6597
|
+
await (await io.getVaultManager()).writeSecrets(env, componentName, secrets, io, options);
|
|
6598
|
+
io.log("");
|
|
6599
|
+
io.log("✅ " + env + ":" + componentName);
|
|
6600
|
+
io.log("--------------------------------\n");
|
|
6309
6601
|
}
|
|
6310
|
-
|
|
6311
|
-
const cluster = deployConfig.cluster;
|
|
6312
|
-
const resource = `k8s_container/cluster_name/${cluster.name}${namespace ? `/namespace_name/${namespace}` : ""}`;
|
|
6313
|
-
await (0, openDashboard_1.openGoogleCloudDashboard)(instance, "logs/viewer", {
|
|
6314
|
-
project: cluster.projectId,
|
|
6315
|
-
resource: resource,
|
|
6316
|
-
});
|
|
6602
|
+
await mirrorSecretsToCiBackends(io, config, writes, options);
|
|
6317
6603
|
};
|
|
6318
|
-
exports.
|
|
6319
|
-
|
|
6604
|
+
exports.writeSecretsAndMirror = writeSecretsAndMirror;
|
|
6605
|
+
/**
|
|
6606
|
+
* the vault is the source of truth; every enabled CI backend receives
|
|
6607
|
+
* a mirrored copy of the written secrets (gitlab variables, github
|
|
6608
|
+
* secrets), so all CI systems stay in sync
|
|
6609
|
+
*/
|
|
6610
|
+
const mirrorSecretsToCiBackends = async (io, config, writes, options) => {
|
|
6320
6611
|
var _a;
|
|
6321
|
-
const
|
|
6322
|
-
|
|
6323
|
-
|
|
6612
|
+
const enabled = (0, pipeline_1.getEnabledPipelineTypes)(config);
|
|
6613
|
+
// gitlab mirror (unless gitlab is the vault itself, then it is
|
|
6614
|
+
// already written)
|
|
6615
|
+
if ((0, pipeline_1.getVaultConfig)(config).type !== "gitlab" && enabled.includes("gitlab")) {
|
|
6616
|
+
for (const { env, componentName, secrets } of writes) {
|
|
6617
|
+
await (0, gitlab_1.upsertAllVariables)(io, secrets, env, componentName, (_a = options.backup) !== null && _a !== void 0 ? _a : true);
|
|
6618
|
+
}
|
|
6619
|
+
io.log("✅ mirrored to gitlab");
|
|
6324
6620
|
}
|
|
6325
|
-
if (!
|
|
6326
|
-
|
|
6621
|
+
if (!enabled.includes("github")) {
|
|
6622
|
+
return;
|
|
6327
6623
|
}
|
|
6328
|
-
const
|
|
6329
|
-
const
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
};
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6624
|
+
const kinds = new Map();
|
|
6625
|
+
for (const { env, componentName } of writes) {
|
|
6626
|
+
const { secretEnvVarKeys, jobOnlyVars } = await (0, getProjectConfig_1.getEnvironment)(env, componentName);
|
|
6627
|
+
[
|
|
6628
|
+
...secretEnvVarKeys,
|
|
6629
|
+
...jobOnlyVars.build.secretEnvVarKeys,
|
|
6630
|
+
...jobOnlyVars.deploy.secretEnvVarKeys,
|
|
6631
|
+
].forEach(({ key, kind }) => kinds.set((0, pipeline_1.getSecretVarName)(env, componentName, key), kind !== null && kind !== void 0 ? kind : "secret"));
|
|
6632
|
+
}
|
|
6633
|
+
const secrets = writes.flatMap(({ env, componentName, secrets }) => Object.entries(secrets).map(([key, value]) => {
|
|
6634
|
+
var _a;
|
|
6635
|
+
const name = (0, pipeline_1.getSecretVarName)(env, componentName, key);
|
|
6636
|
+
return {
|
|
6637
|
+
name,
|
|
6638
|
+
value: typeof value === "string" ? value : JSON.stringify(value !== null && value !== void 0 ? value : ""),
|
|
6639
|
+
kind: (_a = kinds.get(name)) !== null && _a !== void 0 ? _a : "secret",
|
|
6640
|
+
};
|
|
6641
|
+
}));
|
|
6642
|
+
if (secrets.length === 0) {
|
|
6643
|
+
return;
|
|
6644
|
+
}
|
|
6645
|
+
if (!(await (0, github_1.isGhAuthenticated)())) {
|
|
6646
|
+
io.log("⚠️ github pipeline is enabled, but the github cli (gh) is not authenticated — run `project secrets-sync-github` later to mirror the secrets");
|
|
6647
|
+
return;
|
|
6648
|
+
}
|
|
6649
|
+
const repo = await (0, github_2.getConfiguredGithubRepo)();
|
|
6650
|
+
if (!repo) {
|
|
6651
|
+
io.log("⚠️ github pipeline is enabled, but no github repository was found — run `project secrets-sync-github` later to mirror the secrets");
|
|
6652
|
+
return;
|
|
6653
|
+
}
|
|
6654
|
+
io.log(`mirroring ${secrets.length} secrets to github ('${repo}')...`);
|
|
6655
|
+
await (0, github_2.pushSecretsToGithub)(io, repo, secrets, await (0, github_2.collectSecretTargets)(config));
|
|
6352
6656
|
};
|
|
6353
|
-
|
|
6354
|
-
//# sourceMappingURL=portForward.js.map
|
|
6355
|
-
|
|
6356
|
-
/***/ }),
|
|
6357
|
-
|
|
6358
|
-
/***/ 55689:
|
|
6359
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
6360
|
-
|
|
6361
|
-
"use strict";
|
|
6362
|
-
|
|
6363
|
-
// we can't import the package.json directly, because the bundling process will inline it
|
|
6364
|
-
// but the version is only set during deployement, when its already bundled
|
|
6365
|
-
// instead we need to use require.main.path to get the path of the main module, which is actually the file in the bin
|
|
6366
|
-
// this will point to the root package.json
|
|
6367
|
-
var _a;
|
|
6368
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6369
|
-
const path = ((_a = require.main) === null || _a === void 0 ? void 0 : _a.path) + "/../package.json";
|
|
6370
|
-
const ownPkg = require(path);
|
|
6371
|
-
exports["default"] = ownPkg;
|
|
6372
|
-
//# sourceMappingURL=packageInfos.js.map
|
|
6657
|
+
//# sourceMappingURL=writeSecrets.js.map
|
|
6373
6658
|
|
|
6374
6659
|
/***/ }),
|
|
6375
6660
|
|
|
@@ -6766,6 +7051,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
6766
7051
|
exports.ghApiJson = exports.ensureGithubEnvironment = exports.setGithubVariable = exports.setGithubSecret = exports.listGithubVariableNames = exports.listGithubSecretNames = exports.listGithubEnvironments = exports.getGithubRepoFromRemote = exports.isGhAuthenticated = void 0;
|
|
6767
7052
|
const child_process_1 = __nccwpck_require__(35317);
|
|
6768
7053
|
const util_1 = __nccwpck_require__(39023);
|
|
7054
|
+
const pipeline_1 = __nccwpck_require__(53695);
|
|
6769
7055
|
const execFile = (0, util_1.promisify)(child_process_1.execFile);
|
|
6770
7056
|
/**
|
|
6771
7057
|
* whether the github cli (gh) is installed and authenticated
|
|
@@ -6788,8 +7074,7 @@ exports.isGhAuthenticated = isGhAuthenticated;
|
|
|
6788
7074
|
const getGithubRepoFromRemote = async (remoteName) => {
|
|
6789
7075
|
try {
|
|
6790
7076
|
const { stdout } = await execFile("git", ["remote", "get-url", remoteName]);
|
|
6791
|
-
|
|
6792
|
-
return match === null || match === void 0 ? void 0 : match[1];
|
|
7077
|
+
return (0, pipeline_1.parseGithubRepoFromRemoteUrl)(stdout);
|
|
6793
7078
|
}
|
|
6794
7079
|
catch (_a) {
|
|
6795
7080
|
return undefined;
|
|
@@ -6910,7 +7195,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6910
7195
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6911
7196
|
};
|
|
6912
7197
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6913
|
-
exports.upsertAllVariables = exports.clearBackups = exports.getVariableValueByRawName = exports.getAllVariables = exports.getProjectInfo = exports.doGitlabRequestAllPages = exports.doGitlabRequest = exports.getGitlabToken = exports.setupGitlabToken = exports.hasGitlabToken = void 0;
|
|
7198
|
+
exports.upsertAllVariables = exports.clearBackups = exports.getVariableValueByRawName = exports.getAllVariables = exports.getProjectInfo = exports.doGitlabRequestAllPages = exports.doGitlabRequest = exports.GitlabNotFoundError = exports.getGitlabToken = exports.setupGitlabToken = exports.hasGitlabToken = void 0;
|
|
6914
7199
|
const pipeline_1 = __nccwpck_require__(53695);
|
|
6915
7200
|
const lodash_es_1 = __nccwpck_require__(50210);
|
|
6916
7201
|
const memoizee_1 = __importDefault(__nccwpck_require__(6575));
|
|
@@ -6962,6 +7247,20 @@ const getGitlabToken = async (io) => {
|
|
|
6962
7247
|
return (0, preferences_1.getPreference)(TOKEN_KEY);
|
|
6963
7248
|
};
|
|
6964
7249
|
exports.getGitlabToken = getGitlabToken;
|
|
7250
|
+
/**
|
|
7251
|
+
* a gitlab api call that came back 404. Carries the path so a caller
|
|
7252
|
+
* that wants to treat "does not exist yet" as normal can say so
|
|
7253
|
+
* (`instanceof`) instead of matching on a message.
|
|
7254
|
+
*/
|
|
7255
|
+
class GitlabNotFoundError extends Error {
|
|
7256
|
+
constructor(path, host) {
|
|
7257
|
+
super(`gitlab api: ${path} not found on ${host}`);
|
|
7258
|
+
this.path = path;
|
|
7259
|
+
this.host = host;
|
|
7260
|
+
this.name = "GitlabNotFoundError";
|
|
7261
|
+
}
|
|
7262
|
+
}
|
|
7263
|
+
exports.GitlabNotFoundError = GitlabNotFoundError;
|
|
6965
7264
|
const doGitlabRequest = async (io, path, data = undefined, method = "GET") => {
|
|
6966
7265
|
const [rootToken, { gitRemoteHost }] = await Promise.all([
|
|
6967
7266
|
(0, exports.getGitlabToken)(io),
|
|
@@ -6983,7 +7282,7 @@ const doGitlabRequest = async (io, path, data = undefined, method = "GET") => {
|
|
|
6983
7282
|
return null;
|
|
6984
7283
|
}
|
|
6985
7284
|
if (result.status === 404) {
|
|
6986
|
-
throw new
|
|
7285
|
+
throw new GitlabNotFoundError(path, gitRemoteHost);
|
|
6987
7286
|
}
|
|
6988
7287
|
throw new Error(`Could not send request to gitlab api ${path}: ${result.status} "${result.statusText}".\nResponse: ${JSON.stringify(await result.json(), null, 2)}`);
|
|
6989
7288
|
};
|
|
@@ -7009,9 +7308,20 @@ const doGitlabRequestAllPages = async (io, path) => {
|
|
|
7009
7308
|
};
|
|
7010
7309
|
exports.doGitlabRequestAllPages = doGitlabRequestAllPages;
|
|
7011
7310
|
const getProjectInfo = async (io) => {
|
|
7012
|
-
const { gitRemotePath } = await (0, gitProjectInformation_1.getGitRemoteHostAndPath)();
|
|
7013
|
-
|
|
7014
|
-
|
|
7311
|
+
const { gitRemoteHost, gitRemotePath } = await (0, gitProjectInformation_1.getGitRemoteHostAndPath)();
|
|
7312
|
+
try {
|
|
7313
|
+
return await (0, exports.doGitlabRequest)(io, `projects/${encodeURIComponent(gitRemotePath)}`);
|
|
7314
|
+
}
|
|
7315
|
+
catch (e) {
|
|
7316
|
+
if (e instanceof GitlabNotFoundError) {
|
|
7317
|
+
// the classic: the remote is not a gitlab at all (a github one,
|
|
7318
|
+
// say), so the request goes to a host without /api/v4 and every
|
|
7319
|
+
// path answers 404
|
|
7320
|
+
throw new Error(`no gitlab project '${gitRemotePath}' on '${gitRemoteHost}'. ` +
|
|
7321
|
+
"Check the git remote and `pipelines` in catladder.ts — this command talks to the gitlab api.");
|
|
7322
|
+
}
|
|
7323
|
+
throw e;
|
|
7324
|
+
}
|
|
7015
7325
|
};
|
|
7016
7326
|
exports.getProjectInfo = getProjectInfo;
|
|
7017
7327
|
exports.getAllVariables = (0, memoizee_1.default)(async (io, n = 5) => {
|
|
@@ -7566,7 +7876,14 @@ class BitwardenVault {
|
|
|
7566
7876
|
}
|
|
7567
7877
|
return secrets;
|
|
7568
7878
|
}
|
|
7879
|
+
/**
|
|
7880
|
+
* upserts into the item's yaml note. The note is rewritten as a
|
|
7881
|
+
* whole, so the values that are not part of this write have to be
|
|
7882
|
+
* carried over — a single-key write (`secrets-set`, a credential
|
|
7883
|
+
* provisioned by `project setup`) must not drop the rest.
|
|
7884
|
+
*/
|
|
7569
7885
|
async writeSecrets(io, env, componentName, secrets) {
|
|
7886
|
+
var _a;
|
|
7570
7887
|
const { config, collectionName } = this;
|
|
7571
7888
|
const bwSession = await this.session(io);
|
|
7572
7889
|
const collection = await findCollection(bwSession, collectionName);
|
|
@@ -7579,7 +7896,10 @@ class BitwardenVault {
|
|
|
7579
7896
|
"--search",
|
|
7580
7897
|
name,
|
|
7581
7898
|
])).find((item) => item.name === name);
|
|
7582
|
-
const
|
|
7899
|
+
const previous = (existing === null || existing === void 0 ? void 0 : existing.notes)
|
|
7900
|
+
? ((_a = (0, yaml_1.parse)(existing.notes)) !== null && _a !== void 0 ? _a : {})
|
|
7901
|
+
: {};
|
|
7902
|
+
const notes = (0, yaml_1.stringify)({ ...previous, ...secrets });
|
|
7583
7903
|
if (existing) {
|
|
7584
7904
|
await (0, bw_1.runBw)(bwSession, [
|
|
7585
7905
|
"edit",
|
|
@@ -7633,8 +7953,9 @@ class GitlabVault {
|
|
|
7633
7953
|
const variables = await (0, gitlab_1.getAllVariables)(io);
|
|
7634
7954
|
return Object.fromEntries(variables.map((v) => [v.key, v.value]));
|
|
7635
7955
|
}
|
|
7636
|
-
async writeSecrets(io, env, componentName, secrets) {
|
|
7637
|
-
|
|
7956
|
+
async writeSecrets(io, env, componentName, secrets, options = {}) {
|
|
7957
|
+
var _a;
|
|
7958
|
+
await (0, gitlab_1.upsertAllVariables)(io, secrets, env, componentName, (_a = options.backup) !== null && _a !== void 0 ? _a : true);
|
|
7638
7959
|
}
|
|
7639
7960
|
}
|
|
7640
7961
|
exports.GitlabVault = GitlabVault;
|
|
@@ -7720,11 +8041,11 @@ class VaultManager {
|
|
|
7720
8041
|
* writes secrets of one env/component to the vault and updates the
|
|
7721
8042
|
* local cache (write-through, "local" env only)
|
|
7722
8043
|
*/
|
|
7723
|
-
async writeSecrets(env, componentName, secrets, io = this.io) {
|
|
8044
|
+
async writeSecrets(env, componentName, secrets, io = this.io, options = {}) {
|
|
7724
8045
|
if (!io) {
|
|
7725
8046
|
throw new Error("writing to the vault requires an interactive context");
|
|
7726
8047
|
}
|
|
7727
|
-
await this.vault.writeSecrets(io, env, componentName, secrets);
|
|
8048
|
+
await this.vault.writeSecrets(io, env, componentName, secrets, options);
|
|
7728
8049
|
if (env === CACHED_ENV) {
|
|
7729
8050
|
await (0, cache_1.updateSecretsCache)(this.vault.id, env, componentName, Object.fromEntries(Object.entries(secrets).map(([key, value]) => [
|
|
7730
8051
|
key,
|
|
@@ -8723,6 +9044,43 @@ exports.getAgentSkillTargets = getAgentSkillTargets;
|
|
|
8723
9044
|
|
|
8724
9045
|
/***/ }),
|
|
8725
9046
|
|
|
9047
|
+
/***/ 72792:
|
|
9048
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
9049
|
+
|
|
9050
|
+
"use strict";
|
|
9051
|
+
|
|
9052
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
9053
|
+
exports.getPinLabelRegexSource = exports.getAutoStopConfig = exports.DEFAULT_PIN_LABEL = exports.DEFAULT_DEV_AUTO_STOP = exports.DEFAULT_REVIEW_AUTO_STOP = exports.REVIEW_AUTO_STOP_VARIABLE = void 0;
|
|
9054
|
+
const lodash_es_1 = __nccwpck_require__(50210);
|
|
9055
|
+
/**
|
|
9056
|
+
* pipeline-level variable holding the `auto_stop_in` of review
|
|
9057
|
+
* environments. Review deploy jobs reference it instead of a literal,
|
|
9058
|
+
* so the pin label's workflow rule can override it to `never` for the
|
|
9059
|
+
* whole pipeline (all components at once).
|
|
9060
|
+
*/
|
|
9061
|
+
exports.REVIEW_AUTO_STOP_VARIABLE = "CL_REVIEW_AUTO_STOP";
|
|
9062
|
+
exports.DEFAULT_REVIEW_AUTO_STOP = "1 week";
|
|
9063
|
+
exports.DEFAULT_DEV_AUTO_STOP = "4 weeks";
|
|
9064
|
+
exports.DEFAULT_PIN_LABEL = "catladder::pin-review";
|
|
9065
|
+
const getAutoStopConfig = (config) => {
|
|
9066
|
+
var _a, _b, _c, _d, _e, _f;
|
|
9067
|
+
return ({
|
|
9068
|
+
review: (_b = (_a = config.autoStop) === null || _a === void 0 ? void 0 : _a.review) !== null && _b !== void 0 ? _b : exports.DEFAULT_REVIEW_AUTO_STOP,
|
|
9069
|
+
dev: (_d = (_c = config.autoStop) === null || _c === void 0 ? void 0 : _c.dev) !== null && _d !== void 0 ? _d : exports.DEFAULT_DEV_AUTO_STOP,
|
|
9070
|
+
pinLabel: (_f = (_e = config.autoStop) === null || _e === void 0 ? void 0 : _e.pinLabel) !== null && _f !== void 0 ? _f : exports.DEFAULT_PIN_LABEL,
|
|
9071
|
+
});
|
|
9072
|
+
};
|
|
9073
|
+
exports.getAutoStopConfig = getAutoStopConfig;
|
|
9074
|
+
/**
|
|
9075
|
+
* matches the pin label inside `$CI_MERGE_REQUEST_LABELS`
|
|
9076
|
+
* (comma-separated) — anchored so `pin` never matches `no-pin`
|
|
9077
|
+
*/
|
|
9078
|
+
const getPinLabelRegexSource = (pinLabel) => `(^|,)${(0, lodash_es_1.escapeRegExp)(pinLabel).replaceAll("/", "\\/")}(,|$)`;
|
|
9079
|
+
exports.getPinLabelRegexSource = getPinLabelRegexSource;
|
|
9080
|
+
//# sourceMappingURL=autoStop.js.map
|
|
9081
|
+
|
|
9082
|
+
/***/ }),
|
|
9083
|
+
|
|
8726
9084
|
/***/ 48476:
|
|
8727
9085
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
8728
9086
|
|
|
@@ -8735,6 +9093,7 @@ const path_1 = __nccwpck_require__(16928);
|
|
|
8735
9093
|
const createAllJobs_1 = __nccwpck_require__(83477);
|
|
8736
9094
|
const config_1 = __nccwpck_require__(75591);
|
|
8737
9095
|
const ciVariables_1 = __nccwpck_require__(17300);
|
|
9096
|
+
const registryImage_1 = __nccwpck_require__(24333);
|
|
8738
9097
|
const index_1 = __nccwpck_require__(62853);
|
|
8739
9098
|
const createGithubJobs_1 = __nccwpck_require__(73474);
|
|
8740
9099
|
const jobImagesPlan_1 = __nccwpck_require__(59623);
|
|
@@ -8788,7 +9147,10 @@ class GithubBackend {
|
|
|
8788
9147
|
await (0, promises_1.rm)(scriptFiles_1.GITHUB_SCRIPTS_FOLDER, { recursive: true, force: true });
|
|
8789
9148
|
}
|
|
8790
9149
|
async createFiles(config) {
|
|
8791
|
-
|
|
9150
|
+
// ghcr rejects uppercase image paths, and `${{ github.repository }}`
|
|
9151
|
+
// interpolates github's display casing — a mixed-case owner or repo
|
|
9152
|
+
// needs a lowercased literal instead (see ./ghcr)
|
|
9153
|
+
const images = this.createImagesPlan(config, await (0, registryImage_1.resolveGithubRegistryImage)(config));
|
|
8792
9154
|
const scripts = new scriptFiles_1.GithubScriptFiles();
|
|
8793
9155
|
const workflows = await this.createWorkflows(config, images, scripts);
|
|
8794
9156
|
return [
|
|
@@ -8803,8 +9165,8 @@ class GithubBackend {
|
|
|
8803
9165
|
...(0, shippedCatci_1.getCatciGeneratedFiles)(),
|
|
8804
9166
|
];
|
|
8805
9167
|
}
|
|
8806
|
-
createImagesPlan(config) {
|
|
8807
|
-
return new jobImagesPlan_1.JobImagesPlan(this.type, config.images);
|
|
9168
|
+
createImagesPlan(config, registryImage) {
|
|
9169
|
+
return new jobImagesPlan_1.JobImagesPlan(this.type, config.images, registryImage);
|
|
8808
9170
|
}
|
|
8809
9171
|
/**
|
|
8810
9172
|
* all workflows keyed by file name, mainly for testing purposes
|
|
@@ -8813,9 +9175,11 @@ class GithubBackend {
|
|
|
8813
9175
|
var _a, _b, _c, _d;
|
|
8814
9176
|
const workflows = {};
|
|
8815
9177
|
// per-pipeline-type variables (pipelines.github.runnerVariables);
|
|
8816
|
-
// workflow-level env, so job-level runnerVariables take precedence
|
|
9178
|
+
// workflow-level env, so job-level runnerVariables take precedence.
|
|
9179
|
+
// The images plan is the single source of the ghcr namespace, so the
|
|
9180
|
+
// workflow env and the container images can never disagree.
|
|
8817
9181
|
const workflowEnv = {
|
|
8818
|
-
...ciVariables_1.
|
|
9182
|
+
...(0, ciVariables_1.getGithubInjectedWorkflowEnv)(images.registryImageRef()),
|
|
8819
9183
|
...(0, index_1.getPipelineOptions)(config, this.type).runnerVariables,
|
|
8820
9184
|
};
|
|
8821
9185
|
const reviewStopJobs = {};
|
|
@@ -9158,12 +9522,13 @@ exports.makeAggregateCheckJob = makeAggregateCheckJob;
|
|
|
9158
9522
|
/***/ }),
|
|
9159
9523
|
|
|
9160
9524
|
/***/ 17300:
|
|
9161
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
9525
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
9162
9526
|
|
|
9163
9527
|
"use strict";
|
|
9164
9528
|
|
|
9165
9529
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
9166
|
-
exports.
|
|
9530
|
+
exports.GITHUB_INJECTED_WORKFLOW_ENV_NAMES = exports.getGithubInjectedWorkflowEnv = exports.GITHUB_CI_VARIABLES = void 0;
|
|
9531
|
+
const ghcr_1 = __nccwpck_require__(59011);
|
|
9167
9532
|
/**
|
|
9168
9533
|
* how the github backend names the predefined CI variables.
|
|
9169
9534
|
*
|
|
@@ -9184,16 +9549,28 @@ exports.GITHUB_CI_VARIABLES = {
|
|
|
9184
9549
|
};
|
|
9185
9550
|
/**
|
|
9186
9551
|
* the workflow-level env the backend injects to provide the CL_*
|
|
9187
|
-
* variables referenced by {@link GITHUB_CI_VARIABLES}
|
|
9552
|
+
* variables referenced by {@link GITHUB_CI_VARIABLES}.
|
|
9553
|
+
*
|
|
9554
|
+
* `registryImage` is the ghcr namespace to push to — the actions
|
|
9555
|
+
* expression for an all-lowercase repository, a lowercased literal for
|
|
9556
|
+
* a mixed-case one (see `./ghcr`).
|
|
9188
9557
|
*/
|
|
9189
|
-
|
|
9558
|
+
const getGithubInjectedWorkflowEnv = (registryImage = ghcr_1.GHCR_REPOSITORY_EXPRESSION) => ({
|
|
9190
9559
|
CL_JOB_TOKEN: "${{ github.token }}",
|
|
9191
9560
|
CL_REGISTRY: "ghcr.io",
|
|
9192
|
-
CL_REGISTRY_IMAGE:
|
|
9561
|
+
CL_REGISTRY_IMAGE: registryImage,
|
|
9193
9562
|
CL_REGISTRY_USER: "${{ github.actor }}",
|
|
9194
9563
|
// empty outside of pull request events
|
|
9195
9564
|
CL_PR_NUMBER: "${{ github.event.number }}",
|
|
9196
|
-
};
|
|
9565
|
+
});
|
|
9566
|
+
exports.getGithubInjectedWorkflowEnv = getGithubInjectedWorkflowEnv;
|
|
9567
|
+
/**
|
|
9568
|
+
* the names of the injected workflow-level env — the values differ per
|
|
9569
|
+
* repository (see {@link getGithubInjectedWorkflowEnv}), the names never
|
|
9570
|
+
* do, so lookups that only ask "does the workflow already provide this?"
|
|
9571
|
+
* use this instead.
|
|
9572
|
+
*/
|
|
9573
|
+
exports.GITHUB_INJECTED_WORKFLOW_ENV_NAMES = new Set(Object.keys((0, exports.getGithubInjectedWorkflowEnv)()));
|
|
9197
9574
|
//# sourceMappingURL=ciVariables.js.map
|
|
9198
9575
|
|
|
9199
9576
|
/***/ }),
|
|
@@ -9420,7 +9797,7 @@ const getSecretsEnv = (context, kinds) => {
|
|
|
9420
9797
|
*/
|
|
9421
9798
|
const getReferencedSecretsEnv = (script, kinds) => Object.fromEntries([...script.matchAll(/\$\{?(CL_[A-Za-z0-9_]+)\}?/g)]
|
|
9422
9799
|
.map((match) => match[1])
|
|
9423
|
-
.filter((name) => !(name
|
|
9800
|
+
.filter((name) => !ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV_NAMES.has(name))
|
|
9424
9801
|
.map((name) => [name, vaultValueExpression(name, kinds)]));
|
|
9425
9802
|
const makeGithubJob = (context, job, allJobs, uploadProviderIds, images, scripts, secretKinds = new Map()) => {
|
|
9426
9803
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
@@ -9684,6 +10061,53 @@ exports.makeEnsureImageGithubJobs = makeEnsureImageGithubJobs;
|
|
|
9684
10061
|
|
|
9685
10062
|
/***/ }),
|
|
9686
10063
|
|
|
10064
|
+
/***/ 59011:
|
|
10065
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
10066
|
+
|
|
10067
|
+
"use strict";
|
|
10068
|
+
|
|
10069
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
10070
|
+
exports.toGhcrRegistryImage = exports.parseGithubRepoFromRemoteUrl = exports.GHCR_REPOSITORY_EXPRESSION = void 0;
|
|
10071
|
+
/**
|
|
10072
|
+
* the ghcr namespace expressed through the actions context — portable
|
|
10073
|
+
* across forks, and what every all-lowercase repository keeps using
|
|
10074
|
+
*/
|
|
10075
|
+
exports.GHCR_REPOSITORY_EXPRESSION = "ghcr.io/${{ github.repository }}";
|
|
10076
|
+
/**
|
|
10077
|
+
* parses `owner/name` out of a github remote url (ssh or https, with or
|
|
10078
|
+
* without the `.git` suffix).
|
|
10079
|
+
*
|
|
10080
|
+
* Shared with the cli (`apps/cli/src/utils/github.ts`) so the two can't
|
|
10081
|
+
* drift apart.
|
|
10082
|
+
*/
|
|
10083
|
+
const parseGithubRepoFromRemoteUrl = (url) => { var _a; return (_a = url.match(/github\.com[:/]([\w.-]+\/[\w.-]+?)(\.git)?\s*$/)) === null || _a === void 0 ? void 0 : _a[1]; };
|
|
10084
|
+
exports.parseGithubRepoFromRemoteUrl = parseGithubRepoFromRemoteUrl;
|
|
10085
|
+
/**
|
|
10086
|
+
* the ghcr image prefix for an `owner/name` repository.
|
|
10087
|
+
*
|
|
10088
|
+
* The OCI distribution spec only allows `[a-z0-9]` plus `.`, `_` and `-`
|
|
10089
|
+
* separators in a repository name, so a mixed-case owner or repo (very
|
|
10090
|
+
* common for org logins: `AcmeCorp`, …) makes the docker client reject
|
|
10091
|
+
* every tag before it even reaches the network. Lowercasing is not a
|
|
10092
|
+
* workaround: the org `AcmeCorp` owns the namespace `ghcr.io/acmecorp`,
|
|
10093
|
+
* so the lowercased path is the correct address.
|
|
10094
|
+
*
|
|
10095
|
+
* Returns the `${{ github.repository }}` expression when lowercasing
|
|
10096
|
+
* would change nothing — it is equivalent for those repositories, and
|
|
10097
|
+
* unlike a literal it keeps working in a fork (whose token can only
|
|
10098
|
+
* push to the fork's own namespace).
|
|
10099
|
+
*/
|
|
10100
|
+
const toGhcrRegistryImage = (repository) => {
|
|
10101
|
+
const lowercased = repository.toLowerCase();
|
|
10102
|
+
return lowercased === repository
|
|
10103
|
+
? exports.GHCR_REPOSITORY_EXPRESSION
|
|
10104
|
+
: `ghcr.io/${lowercased}`;
|
|
10105
|
+
};
|
|
10106
|
+
exports.toGhcrRegistryImage = toGhcrRegistryImage;
|
|
10107
|
+
//# sourceMappingURL=ghcr.js.map
|
|
10108
|
+
|
|
10109
|
+
/***/ }),
|
|
10110
|
+
|
|
9687
10111
|
/***/ 25073:
|
|
9688
10112
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
9689
10113
|
|
|
@@ -9993,12 +10417,70 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
9993
10417
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
9994
10418
|
__exportStar(__nccwpck_require__(48476), exports);
|
|
9995
10419
|
__exportStar(__nccwpck_require__(17300), exports);
|
|
10420
|
+
__exportStar(__nccwpck_require__(59011), exports);
|
|
10421
|
+
__exportStar(__nccwpck_require__(24333), exports);
|
|
9996
10422
|
__exportStar(__nccwpck_require__(61071), exports);
|
|
9997
10423
|
__exportStar(__nccwpck_require__(82145), exports);
|
|
9998
10424
|
//# sourceMappingURL=index.js.map
|
|
9999
10425
|
|
|
10000
10426
|
/***/ }),
|
|
10001
10427
|
|
|
10428
|
+
/***/ 24333:
|
|
10429
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
10430
|
+
|
|
10431
|
+
"use strict";
|
|
10432
|
+
|
|
10433
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
10434
|
+
exports.resolveGithubRegistryImage = exports.githubRegistryImageFromConfig = void 0;
|
|
10435
|
+
const child_process_1 = __nccwpck_require__(35317);
|
|
10436
|
+
const util_1 = __nccwpck_require__(39023);
|
|
10437
|
+
const index_1 = __nccwpck_require__(62853);
|
|
10438
|
+
const ghcr_1 = __nccwpck_require__(59011);
|
|
10439
|
+
const execFile = (0, util_1.promisify)(child_process_1.execFile);
|
|
10440
|
+
/**
|
|
10441
|
+
* the ghcr image prefix derived from the config alone
|
|
10442
|
+
* (`pipelines.github.repository`), without touching git.
|
|
10443
|
+
*
|
|
10444
|
+
* Used where generation must stay pure and hermetic (tests, examples);
|
|
10445
|
+
* {@link resolveGithubRegistryImage} adds the git remote fallback.
|
|
10446
|
+
*/
|
|
10447
|
+
const githubRegistryImageFromConfig = (config) => {
|
|
10448
|
+
const { repository } = (0, index_1.getPipelineOptions)(config, "github");
|
|
10449
|
+
return repository ? (0, ghcr_1.toGhcrRegistryImage)(repository) : undefined;
|
|
10450
|
+
};
|
|
10451
|
+
exports.githubRegistryImageFromConfig = githubRegistryImageFromConfig;
|
|
10452
|
+
/**
|
|
10453
|
+
* the ghcr image prefix to generate with: the configured repository, or
|
|
10454
|
+
* the one the github git remote points at.
|
|
10455
|
+
*
|
|
10456
|
+
* Falls back to the `${{ github.repository }}` expression when the
|
|
10457
|
+
* remote is unavailable (a checkout without the remote, a tarball, …).
|
|
10458
|
+
* That is the pre-existing behavior and correct for every all-lowercase
|
|
10459
|
+
* repository; `project doctor` catches the mixed-case case it is not
|
|
10460
|
+
* correct for.
|
|
10461
|
+
*/
|
|
10462
|
+
const resolveGithubRegistryImage = async (config) => {
|
|
10463
|
+
const fromConfig = (0, exports.githubRegistryImageFromConfig)(config);
|
|
10464
|
+
if (fromConfig) {
|
|
10465
|
+
return fromConfig;
|
|
10466
|
+
}
|
|
10467
|
+
const remote = (0, index_1.getPipelineGitRemote)(config, "github");
|
|
10468
|
+
try {
|
|
10469
|
+
const { stdout } = await execFile("git", ["remote", "get-url", remote]);
|
|
10470
|
+
const repository = (0, ghcr_1.parseGithubRepoFromRemoteUrl)(stdout);
|
|
10471
|
+
return repository
|
|
10472
|
+
? (0, ghcr_1.toGhcrRegistryImage)(repository)
|
|
10473
|
+
: ghcr_1.GHCR_REPOSITORY_EXPRESSION;
|
|
10474
|
+
}
|
|
10475
|
+
catch (_a) {
|
|
10476
|
+
return ghcr_1.GHCR_REPOSITORY_EXPRESSION;
|
|
10477
|
+
}
|
|
10478
|
+
};
|
|
10479
|
+
exports.resolveGithubRegistryImage = resolveGithubRegistryImage;
|
|
10480
|
+
//# sourceMappingURL=registryImage.js.map
|
|
10481
|
+
|
|
10482
|
+
/***/ }),
|
|
10483
|
+
|
|
10002
10484
|
/***/ 61071:
|
|
10003
10485
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
10004
10486
|
|
|
@@ -10101,6 +10583,7 @@ exports.GitlabBackend = void 0;
|
|
|
10101
10583
|
const promises_1 = __nccwpck_require__(91943);
|
|
10102
10584
|
const rules_1 = __nccwpck_require__(78503);
|
|
10103
10585
|
const config_1 = __nccwpck_require__(75591);
|
|
10586
|
+
const autoStop_1 = __nccwpck_require__(72792);
|
|
10104
10587
|
const createAllJobs_1 = __nccwpck_require__(83477);
|
|
10105
10588
|
const jobImagesPlan_1 = __nccwpck_require__(59623);
|
|
10106
10589
|
const shippedCatci_1 = __nccwpck_require__(27967);
|
|
@@ -10286,6 +10769,7 @@ class GitlabBackend {
|
|
|
10286
10769
|
// per-pipeline-type variables (pipelines.gitlab.runnerVariables)
|
|
10287
10770
|
...(0, index_1.getPipelineOptions)(config, this.type).runnerVariables,
|
|
10288
10771
|
},
|
|
10772
|
+
autoStop: (0, autoStop_1.getAutoStopConfig)(config),
|
|
10289
10773
|
});
|
|
10290
10774
|
}
|
|
10291
10775
|
}
|
|
@@ -10730,6 +11214,7 @@ function getGitlabNeedsForWorkspaceJob(context, { needs }, allJobs) {
|
|
|
10730
11214
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
10731
11215
|
exports.createGitlabPipelineWithDefaults = void 0;
|
|
10732
11216
|
const bash_1 = __nccwpck_require__(94143);
|
|
11217
|
+
const autoStop_1 = __nccwpck_require__(72792);
|
|
10733
11218
|
const rules_1 = __nccwpck_require__(78503);
|
|
10734
11219
|
/**
|
|
10735
11220
|
* gitlab requires a top-level default image for jobs that don't set their
|
|
@@ -10738,7 +11223,8 @@ const rules_1 = __nccwpck_require__(78503);
|
|
|
10738
11223
|
* build-free image (a catladder job image would drag in a build job).
|
|
10739
11224
|
*/
|
|
10740
11225
|
const DEFAULT_PIPELINE_IMAGE = "node:22";
|
|
10741
|
-
const createGitlabPipelineWithDefaults = ({ image, variables, before_script, ...config }) => {
|
|
11226
|
+
const createGitlabPipelineWithDefaults = ({ image, variables, before_script, autoStop, ...config }) => {
|
|
11227
|
+
const pinLabel = autoStop && autoStop.pinLabel;
|
|
10742
11228
|
return {
|
|
10743
11229
|
image: image !== null && image !== void 0 ? image : DEFAULT_PIPELINE_IMAGE,
|
|
10744
11230
|
variables: {
|
|
@@ -10747,6 +11233,10 @@ const createGitlabPipelineWithDefaults = ({ image, variables, before_script, ...
|
|
|
10747
11233
|
CACHE_COMPRESSION_LEVEL: "fast", // same as above, but for caches
|
|
10748
11234
|
TRANSFER_METER_FREQUENCY: "5s", // how often we should update the transfer meter for cache upload/download
|
|
10749
11235
|
GIT_DEPTH: "1", // no need the full depth
|
|
11236
|
+
// review env lifetime — the pin-label workflow rule below
|
|
11237
|
+
// overrides this to "never" (workflow rule variables take
|
|
11238
|
+
// precedence over pipeline-level variables)
|
|
11239
|
+
...(pinLabel ? { [autoStop_1.REVIEW_AUTO_STOP_VARIABLE]: autoStop.review } : {}),
|
|
10750
11240
|
...(variables !== null && variables !== void 0 ? variables : {}),
|
|
10751
11241
|
},
|
|
10752
11242
|
before_script: [
|
|
@@ -10763,6 +11253,20 @@ const createGitlabPipelineWithDefaults = ({ image, variables, before_script, ...
|
|
|
10763
11253
|
PIPELINE_NAME: "Thinking...",
|
|
10764
11254
|
},
|
|
10765
11255
|
},
|
|
11256
|
+
// pinned MRs (rules stop at the first match, so this must come
|
|
11257
|
+
// before the plain merge-request rule)
|
|
11258
|
+
...(pinLabel
|
|
11259
|
+
? [
|
|
11260
|
+
{
|
|
11261
|
+
if: `${rules_1.RULE_IS_MERGE_REQUEST.if} && $CI_MERGE_REQUEST_LABELS =~ /${(0, autoStop_1.getPinLabelRegexSource)(pinLabel)}/`,
|
|
11262
|
+
variables: {
|
|
11263
|
+
PIPELINE_ICON: "🐱📌",
|
|
11264
|
+
PIPELINE_NAME: "mr$CI_MERGE_REQUEST_IID - $CI_MERGE_REQUEST_TITLE",
|
|
11265
|
+
[autoStop_1.REVIEW_AUTO_STOP_VARIABLE]: "never",
|
|
11266
|
+
},
|
|
11267
|
+
},
|
|
11268
|
+
]
|
|
11269
|
+
: []),
|
|
10766
11270
|
{
|
|
10767
11271
|
if: rules_1.RULE_IS_MERGE_REQUEST.if,
|
|
10768
11272
|
variables: {
|
|
@@ -14086,6 +14590,7 @@ exports.JobImagesPlan = exports.PROJECT_IMAGES_FOLDER = exports.GENERATED_IMAGES
|
|
|
14086
14590
|
const fs_1 = __nccwpck_require__(79896);
|
|
14087
14591
|
const path_1 = __nccwpck_require__(16928);
|
|
14088
14592
|
const ciVariables_1 = __nccwpck_require__(91215);
|
|
14593
|
+
const ghcr_1 = __nccwpck_require__(59011);
|
|
14089
14594
|
const docker_1 = __nccwpck_require__(12354);
|
|
14090
14595
|
const runner_1 = __nccwpck_require__(92146);
|
|
14091
14596
|
const gitlab_1 = __nccwpck_require__(86962);
|
|
@@ -14146,9 +14651,16 @@ exports.PROJECT_IMAGES_FOLDER = `${exports.GENERATED_IMAGES_FOLDER}/project`;
|
|
|
14146
14651
|
* Reference-driven: only images actually used by a job are built.
|
|
14147
14652
|
*/
|
|
14148
14653
|
class JobImagesPlan {
|
|
14149
|
-
constructor(pipelineType, projectImages = {}
|
|
14654
|
+
constructor(pipelineType, projectImages = {},
|
|
14655
|
+
/**
|
|
14656
|
+
* the registry image prefix to generate with, overriding the
|
|
14657
|
+
* pipeline type's default. On github this carries the lowercased
|
|
14658
|
+
* ghcr namespace (see `resolveGithubRegistryImage`).
|
|
14659
|
+
*/
|
|
14660
|
+
registryImage) {
|
|
14150
14661
|
this.pipelineType = pipelineType;
|
|
14151
14662
|
this.projectImages = projectImages;
|
|
14663
|
+
this.registryImage = registryImage;
|
|
14152
14664
|
this.used = new Map();
|
|
14153
14665
|
this.usedProject = new Map();
|
|
14154
14666
|
}
|
|
@@ -14173,11 +14685,14 @@ class JobImagesPlan {
|
|
|
14173
14685
|
}
|
|
14174
14686
|
/**
|
|
14175
14687
|
* the registry image prefix. On github, container images can't use
|
|
14176
|
-
* runtime env vars —
|
|
14688
|
+
* runtime env vars — a literal or an actions expression is required.
|
|
14177
14689
|
*/
|
|
14178
14690
|
registryImageRef() {
|
|
14691
|
+
if (this.registryImage) {
|
|
14692
|
+
return this.registryImage;
|
|
14693
|
+
}
|
|
14179
14694
|
return this.pipelineType === "github"
|
|
14180
|
-
?
|
|
14695
|
+
? ghcr_1.GHCR_REPOSITORY_EXPRESSION
|
|
14181
14696
|
: `${(0, ciVariables_1.getCiVariable)({ pipelineType: this.pipelineType }, "registryImage")}`;
|
|
14182
14697
|
}
|
|
14183
14698
|
useProject(name) {
|
|
@@ -14477,6 +14992,7 @@ const docker_1 = __nccwpck_require__(12354);
|
|
|
14477
14992
|
const context_1 = __nccwpck_require__(73938);
|
|
14478
14993
|
const jobs_1 = __nccwpck_require__(98521);
|
|
14479
14994
|
const utils_1 = __nccwpck_require__(71286);
|
|
14995
|
+
const autoStop_1 = __nccwpck_require__(72792);
|
|
14480
14996
|
const stop_1 = __nccwpck_require__(35937);
|
|
14481
14997
|
const variables_1 = __nccwpck_require__(54768);
|
|
14482
14998
|
exports.DEPLOY_JOB_NAME = "🚀 Deploy";
|
|
@@ -14485,10 +15001,15 @@ class DeployJob extends jobs_1.CatladderJob {
|
|
|
14485
15001
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
14486
15002
|
const hasDocker = (0, docker_1.requiresDockerBuild)(context);
|
|
14487
15003
|
const isStoppable = (0, utils_1.contextIsStoppable)(context);
|
|
15004
|
+
const autoStopConfig = (0, autoStop_1.getAutoStopConfig)(context.fullConfig);
|
|
14488
15005
|
const autoStop = context.environment.envType === "review"
|
|
14489
|
-
?
|
|
15006
|
+
? // review envs read the lifetime from a pipeline variable, so
|
|
15007
|
+
// the pin label's workflow rule can override it to "never"
|
|
15008
|
+
autoStopConfig.pinLabel === false
|
|
15009
|
+
? autoStopConfig.review
|
|
15010
|
+
: `$${autoStop_1.REVIEW_AUTO_STOP_VARIABLE}`
|
|
14490
15011
|
: context.environment.envType === "dev"
|
|
14491
|
-
?
|
|
15012
|
+
? autoStopConfig.dev
|
|
14492
15013
|
: undefined;
|
|
14493
15014
|
const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
|
|
14494
15015
|
// if auto or manual is configured explicitly, use that
|
|
@@ -17317,6 +17838,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
17317
17838
|
};
|
|
17318
17839
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
17319
17840
|
__exportStar(__nccwpck_require__(46734), exports);
|
|
17841
|
+
__exportStar(__nccwpck_require__(72792), exports);
|
|
17320
17842
|
__exportStar(__nccwpck_require__(62853), exports);
|
|
17321
17843
|
__exportStar(__nccwpck_require__(63557), exports);
|
|
17322
17844
|
__exportStar(__nccwpck_require__(78503), exports);
|