@catladder/cli 0.0.0-next-16388362 → 0.0.0-next-8b9ad5ca
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/bundles/catenv/index.js +1209 -28
- package/dist/bundles/cli/index.js +1406 -30
- package/dist/cli/src/adapters/baseContext.d.ts +4 -0
- package/dist/cli/src/adapters/baseContext.js +5 -0
- package/dist/cli/src/adapters/baseContext.js.map +1 -1
- package/dist/cli/src/adapters/nonInteractive.d.ts +9 -0
- package/dist/cli/src/adapters/nonInteractive.js +32 -0
- package/dist/cli/src/adapters/nonInteractive.js.map +1 -0
- package/dist/cli/src/adapters/programmatic.d.ts +1 -0
- package/dist/cli/src/adapters/programmatic.js +6 -1
- package/dist/cli/src/adapters/programmatic.js.map +1 -1
- package/dist/cli/src/adapters/terminal.d.ts +1 -0
- package/dist/cli/src/adapters/terminal.js +10 -1
- package/dist/cli/src/adapters/terminal.js.map +1 -1
- package/dist/cli/src/adapters/vaultManagerAccess.d.ts +8 -0
- package/dist/cli/src/adapters/vaultManagerAccess.js +26 -0
- package/dist/cli/src/adapters/vaultManagerAccess.js.map +1 -0
- package/dist/cli/src/apps/catenv/catenv.d.ts +2 -0
- package/dist/cli/src/apps/catenv/catenv.js +8 -1
- package/dist/cli/src/apps/catenv/catenv.js.map +1 -1
- package/dist/cli/src/apps/catenv/printVariables.d.ts +2 -2
- package/dist/cli/src/apps/catenv/printVariables.js +4 -4
- package/dist/cli/src/apps/catenv/printVariables.js.map +1 -1
- package/dist/cli/src/apps/catenv/types.d.ts +9 -0
- package/dist/cli/src/apps/catenv/writeDotEnvFiles.d.ts +2 -2
- package/dist/cli/src/apps/catenv/writeDotEnvFiles.js +1 -1
- package/dist/cli/src/apps/catenv/writeDotEnvFiles.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/project/commandConfigSecrets.js +52 -3
- package/dist/cli/src/apps/cli/commands/project/commandConfigSecrets.js.map +1 -1
- package/dist/cli/src/catenv.js +3 -2
- package/dist/cli/src/catenv.js.map +1 -1
- package/dist/cli/src/commands/index.d.ts +1 -0
- package/dist/cli/src/commands/index.js +8 -1
- package/dist/cli/src/commands/index.js.map +1 -1
- package/dist/cli/src/commands/project/commandSecretsSyncGithub.d.ts +37 -0
- package/dist/cli/src/commands/project/commandSecretsSyncGithub.js +127 -0
- package/dist/cli/src/commands/project/commandSecretsSyncGithub.js.map +1 -0
- package/dist/cli/src/config/getProjectConfig.d.ts +1 -1
- package/dist/cli/src/config/getProjectConfig.js +12 -2
- package/dist/cli/src/config/getProjectConfig.js.map +1 -1
- package/dist/cli/src/core/types.d.ts +15 -0
- package/dist/cli/src/core/types.js +8 -1
- package/dist/cli/src/core/types.js.map +1 -1
- package/dist/cli/src/git/gitProjectInformation.d.ts +1 -1
- package/dist/cli/src/git/gitProjectInformation.js +3 -3
- package/dist/cli/src/git/gitProjectInformation.js.map +1 -1
- package/dist/cli/src/utils/github.d.ts +15 -0
- package/dist/cli/src/utils/github.js +54 -0
- package/dist/cli/src/utils/github.js.map +1 -0
- package/dist/cli/src/vault/BitwardenVault.d.ts +24 -0
- package/dist/cli/src/vault/BitwardenVault.js +107 -0
- package/dist/cli/src/vault/BitwardenVault.js.map +1 -0
- package/dist/cli/src/vault/GitlabVault.d.ts +11 -0
- package/dist/cli/src/vault/GitlabVault.js +24 -0
- package/dist/cli/src/vault/GitlabVault.js.map +1 -0
- package/dist/cli/src/vault/VaultManager.d.ts +43 -0
- package/dist/cli/src/vault/VaultManager.js +131 -0
- package/dist/cli/src/vault/VaultManager.js.map +1 -0
- package/dist/cli/src/vault/bw.d.ts +15 -0
- package/dist/cli/src/vault/bw.js +89 -0
- package/dist/cli/src/vault/bw.js.map +1 -0
- package/dist/cli/src/vault/cache.d.ts +38 -0
- package/dist/cli/src/vault/cache.js +53 -0
- package/dist/cli/src/vault/cache.js.map +1 -0
- package/dist/cli/src/vault/index.d.ts +5 -0
- package/dist/cli/src/vault/index.js +48 -0
- package/dist/cli/src/vault/index.js.map +1 -0
- package/dist/cli/src/vault/types.d.ts +33 -0
- package/dist/cli/src/vault/types.js +5 -0
- package/dist/cli/src/vault/types.js.map +1 -0
- package/dist/pipeline/src/backends/github/GithubBackend.d.ts +12 -0
- package/dist/pipeline/src/backends/github/GithubBackend.js +170 -0
- package/dist/pipeline/src/backends/github/GithubBackend.js.map +1 -0
- package/dist/pipeline/src/backends/github/ciVariables.d.ts +14 -0
- package/dist/pipeline/src/backends/github/ciVariables.js +31 -0
- package/dist/pipeline/src/backends/github/ciVariables.js.map +1 -0
- package/dist/pipeline/src/backends/github/createGithubJobs.d.ts +17 -0
- package/dist/pipeline/src/backends/github/createGithubJobs.js +208 -0
- package/dist/pipeline/src/backends/github/createGithubJobs.js.map +1 -0
- package/dist/pipeline/src/backends/github/githubReleaseJobs.d.ts +15 -0
- package/dist/pipeline/src/backends/github/githubReleaseJobs.js +65 -0
- package/dist/pipeline/src/backends/github/githubReleaseJobs.js.map +1 -0
- package/dist/pipeline/src/backends/github/index.d.ts +2 -0
- package/dist/pipeline/src/backends/github/index.js +26 -0
- package/dist/pipeline/src/backends/github/index.js.map +1 -0
- package/dist/pipeline/src/backends/github/scriptFunctions.d.ts +6 -0
- package/dist/pipeline/src/backends/github/scriptFunctions.js +30 -0
- package/dist/pipeline/src/backends/github/scriptFunctions.js.map +1 -0
- package/dist/pipeline/src/backends/gitlab/GitlabBackend.d.ts +1 -0
- package/dist/pipeline/src/backends/gitlab/GitlabBackend.js +7 -0
- package/dist/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
- package/dist/pipeline/src/backends/index.d.ts +18 -1
- package/dist/pipeline/src/backends/index.js +37 -2
- package/dist/pipeline/src/backends/index.js.map +1 -1
- package/dist/pipeline/src/backends/types.d.ts +7 -3
- package/dist/pipeline/src/bash/ciVariables.js +4 -2
- package/dist/pipeline/src/bash/ciVariables.js.map +1 -1
- package/dist/pipeline/src/constants.js +1 -1
- package/dist/pipeline/src/context/getReviewSlug.js +3 -1
- package/dist/pipeline/src/context/getReviewSlug.js.map +1 -1
- package/dist/pipeline/src/deploy/cloudRun/index.js +11 -4
- package/dist/pipeline/src/deploy/cloudRun/index.js.map +1 -1
- package/dist/pipeline/src/pipeline/generatePipelineFiles.js +2 -5
- package/dist/pipeline/src/pipeline/generatePipelineFiles.js.map +1 -1
- package/dist/pipeline/src/types/config.d.ts +37 -3
- package/dist/pipeline/src/types/github-types.d.ts +47 -0
- package/dist/pipeline/src/types/github-types.js +9 -0
- package/dist/pipeline/src/types/github-types.js.map +1 -0
- package/dist/pipeline/src/types/pipeline.d.ts +4 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/adapters/baseContext.ts +10 -0
- package/src/adapters/nonInteractive.ts +30 -0
- package/src/adapters/programmatic.ts +7 -1
- package/src/adapters/terminal.ts +9 -1
- package/src/adapters/vaultManagerAccess.ts +25 -0
- package/src/apps/catenv/catenv.ts +5 -1
- package/src/apps/catenv/printVariables.ts +16 -6
- package/src/apps/catenv/types.ts +9 -0
- package/src/apps/catenv/writeDotEnvFiles.ts +3 -3
- package/src/apps/cli/commands/project/commandConfigSecrets.ts +94 -9
- package/src/catenv.ts +22 -2
- package/src/commands/index.ts +1 -0
- package/src/commands/project/commandSecretsSyncGithub.ts +149 -0
- package/src/config/getProjectConfig.ts +21 -7
- package/src/core/types.ts +23 -0
- package/src/git/gitProjectInformation.ts +5 -3
- package/src/utils/github.ts +59 -0
- package/src/vault/BitwardenVault.ts +161 -0
- package/src/vault/GitlabVault.ts +25 -0
- package/src/vault/VaultManager.ts +211 -0
- package/src/vault/bw.ts +110 -0
- package/src/vault/cache.ts +80 -0
- package/src/vault/index.ts +5 -0
- package/src/vault/types.ts +42 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/******/ var __webpack_modules__ = ({
|
|
3
3
|
|
|
4
4
|
/***/ 48618:
|
|
5
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
5
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6
6
|
|
|
7
7
|
"use strict";
|
|
8
8
|
|
|
@@ -11,6 +11,7 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
11
11
|
value: true
|
|
12
12
|
}));
|
|
13
13
|
exports.BaseContext = void 0;
|
|
14
|
+
const vaultManagerAccess_1 = __nccwpck_require__(37881);
|
|
14
15
|
/**
|
|
15
16
|
* Base class for CommandContext implementations.
|
|
16
17
|
* Handles caching, the `get()` method, and `promptDirect` delegation.
|
|
@@ -20,6 +21,10 @@ class BaseContext {
|
|
|
20
21
|
constructor(command) {
|
|
21
22
|
this.command = command;
|
|
22
23
|
this.cache = new Map();
|
|
24
|
+
this.vaultManagerGetter = (0, vaultManagerAccess_1.createVaultManagerGetter)(() => this);
|
|
25
|
+
}
|
|
26
|
+
getVaultManager() {
|
|
27
|
+
return this.vaultManagerGetter();
|
|
23
28
|
}
|
|
24
29
|
get(name) {
|
|
25
30
|
if (!this.cache.has(name)) {
|
|
@@ -91,6 +96,7 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
91
96
|
exports.createTerminalIO = exports.createTerminalContext = void 0;
|
|
92
97
|
const types_1 = __nccwpck_require__(92284);
|
|
93
98
|
const baseContext_1 = __nccwpck_require__(48618);
|
|
99
|
+
const vaultManagerAccess_1 = __nccwpck_require__(37881);
|
|
94
100
|
/**
|
|
95
101
|
* Resolve choices from a choices function.
|
|
96
102
|
*/
|
|
@@ -155,6 +161,10 @@ class TerminalContext extends baseContext_1.BaseContext {
|
|
|
155
161
|
super(command);
|
|
156
162
|
this.options = options;
|
|
157
163
|
}
|
|
164
|
+
get interactive() {
|
|
165
|
+
var _a;
|
|
166
|
+
return (_a = this.options.interactive) !== null && _a !== void 0 ? _a : process.stdin.isTTY === true;
|
|
167
|
+
}
|
|
158
168
|
log(message) {
|
|
159
169
|
console.log(message);
|
|
160
170
|
}
|
|
@@ -229,7 +239,10 @@ exports.createTerminalContext = createTerminalContext;
|
|
|
229
239
|
* Create a bare IO instance for terminal helper functions.
|
|
230
240
|
*/
|
|
231
241
|
function createTerminalIO(options = {}) {
|
|
232
|
-
|
|
242
|
+
var _a;
|
|
243
|
+
const io = {
|
|
244
|
+
interactive: (_a = options.interactive) !== null && _a !== void 0 ? _a : process.stdin.isTTY === true,
|
|
245
|
+
getVaultManager: (0, vaultManagerAccess_1.createVaultManagerGetter)(() => io),
|
|
233
246
|
log(message) {
|
|
234
247
|
console.log(message);
|
|
235
248
|
},
|
|
@@ -255,11 +268,45 @@ function createTerminalIO(options = {}) {
|
|
|
255
268
|
throw new types_1.MissingInputError(spec.name, spec.message);
|
|
256
269
|
}
|
|
257
270
|
};
|
|
271
|
+
return io;
|
|
258
272
|
}
|
|
259
273
|
exports.createTerminalIO = createTerminalIO;
|
|
260
274
|
|
|
261
275
|
/***/ }),
|
|
262
276
|
|
|
277
|
+
/***/ 37881:
|
|
278
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
279
|
+
|
|
280
|
+
"use strict";
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
284
|
+
value: true
|
|
285
|
+
}));
|
|
286
|
+
exports.createVaultManagerGetter = void 0;
|
|
287
|
+
const getProjectConfig_1 = __nccwpck_require__(50001);
|
|
288
|
+
const VaultManager_1 = __nccwpck_require__(55771);
|
|
289
|
+
/**
|
|
290
|
+
* lazily creates the vault manager of a context (once per context),
|
|
291
|
+
* loading the project config on first use
|
|
292
|
+
*/
|
|
293
|
+
const createVaultManagerGetter = (io, options = {}) => {
|
|
294
|
+
let managerPromise;
|
|
295
|
+
return () => managerPromise !== null && managerPromise !== void 0 ? managerPromise : managerPromise = (async () => {
|
|
296
|
+
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
297
|
+
if (!config) {
|
|
298
|
+
throw new Error("no catladder config found — the secrets vault needs a project config");
|
|
299
|
+
}
|
|
300
|
+
return new VaultManager_1.VaultManager(config, {
|
|
301
|
+
...options,
|
|
302
|
+
io: io()
|
|
303
|
+
});
|
|
304
|
+
})();
|
|
305
|
+
};
|
|
306
|
+
exports.createVaultManagerGetter = createVaultManagerGetter;
|
|
307
|
+
|
|
308
|
+
/***/ }),
|
|
309
|
+
|
|
263
310
|
/***/ 38365:
|
|
264
311
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
265
312
|
|
|
@@ -355,7 +402,9 @@ const pipeline_1 = __nccwpck_require__(60241);
|
|
|
355
402
|
const common_tags_1 = __nccwpck_require__(63779);
|
|
356
403
|
const lodash_es_1 = __nccwpck_require__(64284);
|
|
357
404
|
const getProjectConfig_1 = __nccwpck_require__(50001);
|
|
405
|
+
const commandSecretsSyncGithub_1 = __nccwpck_require__(50962);
|
|
358
406
|
const editAsFile_1 = __nccwpck_require__(82805);
|
|
407
|
+
const github_1 = __nccwpck_require__(18036);
|
|
359
408
|
const gitlab_1 = __nccwpck_require__(4508);
|
|
360
409
|
const promise_1 = __nccwpck_require__(51762);
|
|
361
410
|
/* for convenience, parse json objects. that makes it easier to edit secrets that are object */
|
|
@@ -433,21 +482,68 @@ const doItFor = async (instance, envAndComponents) => {
|
|
|
433
482
|
}
|
|
434
483
|
}
|
|
435
484
|
}
|
|
485
|
+
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
486
|
+
if (!config) {
|
|
487
|
+
throw new Error("no catladder config found");
|
|
488
|
+
}
|
|
436
489
|
instance.log("");
|
|
437
|
-
instance.log("
|
|
490
|
+
instance.log("writing all secrets to the vault, please wait...");
|
|
438
491
|
instance.log("");
|
|
439
492
|
for (const [componentName, envs] of Object.entries(envAndComponents)) {
|
|
440
493
|
for (const env of envs) {
|
|
441
|
-
instance.log("
|
|
442
|
-
await (
|
|
494
|
+
instance.log("writing " + env + ":" + componentName + "...\n");
|
|
495
|
+
await (await instance.getVaultManager()).writeSecrets(env, componentName, valuesToEdit[componentName][env]);
|
|
443
496
|
instance.log("");
|
|
444
497
|
instance.log("✅ " + env + ":" + componentName);
|
|
445
498
|
instance.log("--------------------------------\n");
|
|
446
499
|
}
|
|
447
500
|
}
|
|
501
|
+
await mirrorSecretsToCiBackends(instance, config, envAndComponents, valuesToEdit);
|
|
448
502
|
instance.log("done! 😻");
|
|
449
503
|
instance.log("");
|
|
450
504
|
};
|
|
505
|
+
/**
|
|
506
|
+
* the vault is the source of truth; every enabled CI backend receives
|
|
507
|
+
* a mirrored copy of the edited secrets (gitlab variables, github
|
|
508
|
+
* secrets), so all CI systems stay in sync
|
|
509
|
+
*/
|
|
510
|
+
const mirrorSecretsToCiBackends = async (instance, config, envAndComponents, valuesToEdit) => {
|
|
511
|
+
const enabled = (0, pipeline_1.getEnabledPipelineTypes)(config);
|
|
512
|
+
// gitlab mirror (unless gitlab is the vault itself, then it is
|
|
513
|
+
// already written)
|
|
514
|
+
if ((0, pipeline_1.getVaultConfig)(config).type !== "gitlab" && enabled.includes("gitlab")) {
|
|
515
|
+
for (const [componentName, envs] of Object.entries(envAndComponents)) {
|
|
516
|
+
for (const env of envs) {
|
|
517
|
+
await (0, gitlab_1.upsertAllVariables)(instance, valuesToEdit[componentName][env], env, componentName);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
instance.log("✅ mirrored to gitlab");
|
|
521
|
+
}
|
|
522
|
+
if (!enabled.includes("github")) {
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
const secrets = Object.entries(envAndComponents).flatMap(([componentName, envs]) => envs.flatMap(env => {
|
|
526
|
+
var _a;
|
|
527
|
+
return Object.entries((_a = valuesToEdit[componentName][env]) !== null && _a !== void 0 ? _a : {}).map(([key, value]) => ({
|
|
528
|
+
name: (0, pipeline_1.getSecretVarName)(env, componentName, key),
|
|
529
|
+
value: typeof value === "string" ? value : JSON.stringify(value !== null && value !== void 0 ? value : "")
|
|
530
|
+
}));
|
|
531
|
+
}));
|
|
532
|
+
if (secrets.length === 0) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
if (!(await (0, github_1.isGhAuthenticated)())) {
|
|
536
|
+
instance.log("⚠️ github pipeline is enabled, but the github cli (gh) is not authenticated — run `project secrets-sync-github` later to mirror the secrets");
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const repo = await (0, commandSecretsSyncGithub_1.getConfiguredGithubRepo)();
|
|
540
|
+
if (!repo) {
|
|
541
|
+
instance.log("⚠️ github pipeline is enabled, but no github repository was found — run `project secrets-sync-github` later to mirror the secrets");
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
instance.log(`mirroring ${secrets.length} secrets to github ('${repo}')...`);
|
|
545
|
+
await (0, commandSecretsSyncGithub_1.pushSecretsToGithub)(instance, repo, secrets);
|
|
546
|
+
};
|
|
451
547
|
const projectConfigSecrets = async (io, envComponent) => {
|
|
452
548
|
if (!envComponent) {
|
|
453
549
|
const allEnvAndcomponents = await (0, getProjectConfig_1.getAllComponentsWithAllEnvsHierarchical)();
|
|
@@ -1874,7 +1970,7 @@ exports.commandKubeStopPortforward = (0, defineCommand_1.defineCommand)({
|
|
|
1874
1970
|
Object.defineProperty(exports, "__esModule", ({
|
|
1875
1971
|
value: true
|
|
1876
1972
|
}));
|
|
1877
|
-
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.commandSetup = exports.commandGetMyTotalWorktime = exports.commandRenewToken = exports.commandTriggerCronjobGeneral = exports.commandOpenLogs = exports.commandSecretsClearBackups = 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;
|
|
1973
|
+
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.commandSetup = exports.commandGetMyTotalWorktime = exports.commandRenewToken = exports.commandTriggerCronjobGeneral = exports.commandOpenLogs = exports.commandSecretsSyncGithub = exports.commandSecretsClearBackups = 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;
|
|
1878
1974
|
// General commands
|
|
1879
1975
|
var commandKubeCurrentContext_1 = __nccwpck_require__(70243);
|
|
1880
1976
|
Object.defineProperty(exports, "commandKubeCurrentContext", ({
|
|
@@ -1975,6 +2071,13 @@ Object.defineProperty(exports, "commandSecretsClearBackups", ({
|
|
|
1975
2071
|
return commandSecretsClearBackups_1.commandSecretsClearBackups;
|
|
1976
2072
|
}
|
|
1977
2073
|
}));
|
|
2074
|
+
var commandSecretsSyncGithub_1 = __nccwpck_require__(50962);
|
|
2075
|
+
Object.defineProperty(exports, "commandSecretsSyncGithub", ({
|
|
2076
|
+
enumerable: true,
|
|
2077
|
+
get: function () {
|
|
2078
|
+
return commandSecretsSyncGithub_1.commandSecretsSyncGithub;
|
|
2079
|
+
}
|
|
2080
|
+
}));
|
|
1978
2081
|
var commandOpenLogs_1 = __nccwpck_require__(98720);
|
|
1979
2082
|
Object.defineProperty(exports, "commandOpenLogs", ({
|
|
1980
2083
|
enumerable: true,
|
|
@@ -3186,6 +3289,140 @@ exports.commandSecretsClearBackups = (0, defineCommand_1.defineCommand)({
|
|
|
3186
3289
|
|
|
3187
3290
|
/***/ }),
|
|
3188
3291
|
|
|
3292
|
+
/***/ 50962:
|
|
3293
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
3294
|
+
|
|
3295
|
+
"use strict";
|
|
3296
|
+
|
|
3297
|
+
|
|
3298
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
3299
|
+
value: true
|
|
3300
|
+
}));
|
|
3301
|
+
exports.commandSecretsSyncGithub = exports.getConfiguredGithubRepo = exports.pushSecretsToGithub = exports.collectSecretsFromVault = void 0;
|
|
3302
|
+
const pipeline_1 = __nccwpck_require__(60241);
|
|
3303
|
+
const getProjectConfig_1 = __nccwpck_require__(50001);
|
|
3304
|
+
const defineCommand_1 = __nccwpck_require__(39489);
|
|
3305
|
+
const github_1 = __nccwpck_require__(18036);
|
|
3306
|
+
/**
|
|
3307
|
+
* all secrets declared in the config, with their values read from the
|
|
3308
|
+
* vault (github secrets are write-only and can never act as a source)
|
|
3309
|
+
*/
|
|
3310
|
+
const collectSecretsFromVault = async io => {
|
|
3311
|
+
const envAndComponents = await (0, getProjectConfig_1.getAllComponentsWithAllEnvsHierarchical)();
|
|
3312
|
+
const names = [];
|
|
3313
|
+
for (const [componentName, envs] of Object.entries(envAndComponents)) {
|
|
3314
|
+
for (const env of envs) {
|
|
3315
|
+
const {
|
|
3316
|
+
secretEnvVarKeys,
|
|
3317
|
+
jobOnlyVars
|
|
3318
|
+
} = await (0, getProjectConfig_1.getEnvironment)(env, componentName);
|
|
3319
|
+
const keys = [...secretEnvVarKeys, ...jobOnlyVars.build.secretEnvVarKeys, ...jobOnlyVars.deploy.secretEnvVarKeys];
|
|
3320
|
+
keys.forEach(({
|
|
3321
|
+
key
|
|
3322
|
+
}) => names.push((0, pipeline_1.getSecretVarName)(env, componentName, key)));
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
3325
|
+
const values = await (await io.getVaultManager()).readSecrets(names, io);
|
|
3326
|
+
const secrets = names.filter(name => values[name] !== undefined).map(name => ({
|
|
3327
|
+
name,
|
|
3328
|
+
value: values[name]
|
|
3329
|
+
}));
|
|
3330
|
+
const missing = names.filter(name => values[name] === undefined);
|
|
3331
|
+
return {
|
|
3332
|
+
secrets,
|
|
3333
|
+
missing
|
|
3334
|
+
};
|
|
3335
|
+
};
|
|
3336
|
+
exports.collectSecretsFromVault = collectSecretsFromVault;
|
|
3337
|
+
/**
|
|
3338
|
+
* pushes secrets to github repository secrets via the gh cli
|
|
3339
|
+
*/
|
|
3340
|
+
const pushSecretsToGithub = async (io, repo, secrets) => {
|
|
3341
|
+
for (const {
|
|
3342
|
+
name,
|
|
3343
|
+
value
|
|
3344
|
+
} of secrets) {
|
|
3345
|
+
await (0, github_1.setGithubSecret)(repo, name, value);
|
|
3346
|
+
io.log(`✅ ${name}`);
|
|
3347
|
+
}
|
|
3348
|
+
};
|
|
3349
|
+
exports.pushSecretsToGithub = pushSecretsToGithub;
|
|
3350
|
+
/**
|
|
3351
|
+
* resolves the github repository from the configured git remote
|
|
3352
|
+
* (`pipelines.github.gitRemote`, defaults to origin)
|
|
3353
|
+
*/
|
|
3354
|
+
const getConfiguredGithubRepo = async () => {
|
|
3355
|
+
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
3356
|
+
if (!config) {
|
|
3357
|
+
return undefined;
|
|
3358
|
+
}
|
|
3359
|
+
return (0, github_1.getGithubRepoFromRemote)((0, pipeline_1.getPipelineGitRemote)(config, "github"));
|
|
3360
|
+
};
|
|
3361
|
+
exports.getConfiguredGithubRepo = getConfiguredGithubRepo;
|
|
3362
|
+
/**
|
|
3363
|
+
* copies the catladder secrets from the vault to github actions
|
|
3364
|
+
* repository secrets, keeping the exact same names, so the github
|
|
3365
|
+
* pipeline can reference them as ${{ secrets.<NAME> }}.
|
|
3366
|
+
*/
|
|
3367
|
+
exports.commandSecretsSyncGithub = (0, defineCommand_1.defineCommand)({
|
|
3368
|
+
name: "project secrets-sync-github",
|
|
3369
|
+
description: "copies all secrets from the vault to github repo secrets (same names), for the github pipeline",
|
|
3370
|
+
group: "project",
|
|
3371
|
+
inputs: {
|
|
3372
|
+
repo: {
|
|
3373
|
+
type: "string",
|
|
3374
|
+
message: "github repository (owner/name)",
|
|
3375
|
+
positional: true,
|
|
3376
|
+
required: false
|
|
3377
|
+
}
|
|
3378
|
+
},
|
|
3379
|
+
execute: async ctx => {
|
|
3380
|
+
var _a;
|
|
3381
|
+
const config = await (0, getProjectConfig_1.getProjectConfig)();
|
|
3382
|
+
if (!config) {
|
|
3383
|
+
throw new Error("no catladder config found");
|
|
3384
|
+
}
|
|
3385
|
+
const enabled = (0, pipeline_1.getEnabledPipelineTypes)(config);
|
|
3386
|
+
if (!enabled.includes("github")) {
|
|
3387
|
+
throw new Error("the github pipeline is not enabled in `pipelines` — nothing to sync to");
|
|
3388
|
+
}
|
|
3389
|
+
if (!(await (0, github_1.isGhAuthenticated)())) {
|
|
3390
|
+
throw new Error("the github cli (gh) is not installed or not authenticated — run `gh auth login` first");
|
|
3391
|
+
}
|
|
3392
|
+
const repo = (_a = await ctx.get("repo")) !== null && _a !== void 0 ? _a : await (0, exports.getConfiguredGithubRepo)();
|
|
3393
|
+
if (!repo) {
|
|
3394
|
+
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`);
|
|
3395
|
+
}
|
|
3396
|
+
const {
|
|
3397
|
+
secrets,
|
|
3398
|
+
missing
|
|
3399
|
+
} = await (0, exports.collectSecretsFromVault)(ctx);
|
|
3400
|
+
if (missing.length > 0) {
|
|
3401
|
+
ctx.log(`⚠️ ${missing.length} secrets are not set in the vault and will be skipped:`);
|
|
3402
|
+
missing.forEach(name => ctx.log(` - ${name}`));
|
|
3403
|
+
ctx.log("");
|
|
3404
|
+
}
|
|
3405
|
+
if (secrets.length === 0) {
|
|
3406
|
+
ctx.log("no secrets to sync 🤷");
|
|
3407
|
+
return;
|
|
3408
|
+
}
|
|
3409
|
+
ctx.log(`about to set ${secrets.length} secrets on '${repo}':`);
|
|
3410
|
+
secrets.forEach(({
|
|
3411
|
+
name
|
|
3412
|
+
}) => ctx.log(` - ${name}`));
|
|
3413
|
+
ctx.log("");
|
|
3414
|
+
const confirmed = await ctx.confirm("continue? 🤔");
|
|
3415
|
+
if (!confirmed) {
|
|
3416
|
+
throw new Error("abort");
|
|
3417
|
+
}
|
|
3418
|
+
await (0, exports.pushSecretsToGithub)(ctx, repo, secrets);
|
|
3419
|
+
ctx.log("");
|
|
3420
|
+
ctx.log("done! 😻 the github pipeline can use them as ${{ secrets.<NAME> }}");
|
|
3421
|
+
}
|
|
3422
|
+
});
|
|
3423
|
+
|
|
3424
|
+
/***/ }),
|
|
3425
|
+
|
|
3189
3426
|
/***/ 92494:
|
|
3190
3427
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
3191
3428
|
|
|
@@ -4179,14 +4416,24 @@ const getGitlabVar = async (io, env, componentName, variableName) => {
|
|
|
4179
4416
|
};
|
|
4180
4417
|
exports.getGitlabVar = getGitlabVar;
|
|
4181
4418
|
const resolveSecrets = async (io, varSets) => {
|
|
4182
|
-
|
|
4419
|
+
// the secret variables actually referenced by the env var values —
|
|
4420
|
+
// when they are all in the local cache, the vault is not contacted
|
|
4421
|
+
const referencedNames = [...new Set(varSets.flatMap(({
|
|
4422
|
+
envVars
|
|
4423
|
+
}) => Object.values(envVars).flatMap(value => {
|
|
4424
|
+
var _a;
|
|
4425
|
+
return (_a = `${value}`.match(/\$CL_\w+/g)) !== null && _a !== void 0 ? _a : [];
|
|
4426
|
+
})))].map(reference => reference.slice(1));
|
|
4427
|
+
const vaultManager = await io.getVaultManager();
|
|
4428
|
+
const secrets = await vaultManager.readSecrets(referencedNames, io);
|
|
4429
|
+
const secretEntries = Object.entries(secrets);
|
|
4183
4430
|
return Object.fromEntries(varSets.flatMap(({
|
|
4184
4431
|
envVars,
|
|
4185
4432
|
secretEnvVarKeys
|
|
4186
4433
|
}) => Object.entries(envVars).filter(([key, value]) => {
|
|
4187
4434
|
var _a;
|
|
4188
4435
|
return value !== undefined && value !== null && !((_a = secretEnvVarKeys.find(k => k.key === key)) === null || _a === void 0 ? void 0 : _a.hidden);
|
|
4189
|
-
}).map(([key, value]) => [key,
|
|
4436
|
+
}).map(([key, value]) => [key, secretEntries.reduce((acc, [name, secretValue]) => acc.replace(new RegExp("\\$" + name, "g"), secretValue), `${value}`)])));
|
|
4190
4437
|
};
|
|
4191
4438
|
const getEnvVarsResolved = async (io, env, componentName) => {
|
|
4192
4439
|
if (!componentName) {
|
|
@@ -4291,8 +4538,15 @@ exports.defineCommand = defineCommand;
|
|
|
4291
4538
|
Object.defineProperty(exports, "__esModule", ({
|
|
4292
4539
|
value: true
|
|
4293
4540
|
}));
|
|
4294
|
-
exports.MissingInputError = void 0;
|
|
4541
|
+
exports.MissingInputError = exports.NonInteractiveError = void 0;
|
|
4295
4542
|
// ─── Errors ──────────────────────────────────────────────────────────
|
|
4543
|
+
class NonInteractiveError extends Error {
|
|
4544
|
+
constructor(interaction) {
|
|
4545
|
+
super(`${interaction} requires an interactive terminal, but this context is not interactive`);
|
|
4546
|
+
this.name = "NonInteractiveError";
|
|
4547
|
+
}
|
|
4548
|
+
}
|
|
4549
|
+
exports.NonInteractiveError = NonInteractiveError;
|
|
4296
4550
|
class MissingInputError extends Error {
|
|
4297
4551
|
constructor(inputName, promptMessage) {
|
|
4298
4552
|
super(`Missing required input: "${inputName}" (${promptMessage}). ` + `Provide it via --${inputName}=<value> or --inputs='{"${inputName}": ...}'`);
|
|
@@ -4742,14 +4996,14 @@ exports.getProjectRootPath = getProjectRootPath;
|
|
|
4742
4996
|
/**
|
|
4743
4997
|
* Get the git remote hostname and project path from the git config.
|
|
4744
4998
|
*/
|
|
4745
|
-
const getGitRemoteHostAndPath = async () => {
|
|
4999
|
+
const getGitRemoteHostAndPath = async (remoteName = "origin") => {
|
|
4746
5000
|
var _a;
|
|
4747
|
-
const remoteUrl = await (0, gitConfig_1.gitConfigGet)(
|
|
5001
|
+
const remoteUrl = await (0, gitConfig_1.gitConfigGet)(`remote.${remoteName}.url`);
|
|
4748
5002
|
const remoteReg = /(https:\/\/|git@)([^:/]+)[:/]([^.]*)(\.git)?/;
|
|
4749
5003
|
const match = (_a = remoteUrl.match(remoteReg)) !== null && _a !== void 0 ? _a : [];
|
|
4750
5004
|
const [,, gitRemoteHost, gitRemotePath] = match;
|
|
4751
5005
|
if (!(gitRemoteHost === null || gitRemoteHost === void 0 ? void 0 : gitRemoteHost.length) || !(gitRemotePath === null || gitRemotePath === void 0 ? void 0 : gitRemotePath.length)) {
|
|
4752
|
-
throw new Error(`Failed to parse git remote hostname and path from git configs remote.
|
|
5006
|
+
throw new Error(`Failed to parse git remote hostname and path from git configs remote.${remoteName}.url! ${remoteUrl}`);
|
|
4753
5007
|
}
|
|
4754
5008
|
return {
|
|
4755
5009
|
gitRemoteHost,
|
|
@@ -5306,6 +5560,67 @@ exports["default"] = async () => {
|
|
|
5306
5560
|
|
|
5307
5561
|
/***/ }),
|
|
5308
5562
|
|
|
5563
|
+
/***/ 18036:
|
|
5564
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
5565
|
+
|
|
5566
|
+
"use strict";
|
|
5567
|
+
|
|
5568
|
+
|
|
5569
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
5570
|
+
value: true
|
|
5571
|
+
}));
|
|
5572
|
+
exports.setGithubSecret = exports.getGithubRepoFromRemote = exports.isGhAuthenticated = void 0;
|
|
5573
|
+
const child_process_1 = __nccwpck_require__(35317);
|
|
5574
|
+
const util_1 = __nccwpck_require__(39023);
|
|
5575
|
+
const execFile = (0, util_1.promisify)(child_process_1.execFile);
|
|
5576
|
+
/**
|
|
5577
|
+
* whether the github cli (gh) is installed and authenticated
|
|
5578
|
+
*/
|
|
5579
|
+
const isGhAuthenticated = async () => {
|
|
5580
|
+
try {
|
|
5581
|
+
await execFile("gh", ["auth", "status"]);
|
|
5582
|
+
return true;
|
|
5583
|
+
} catch (_a) {
|
|
5584
|
+
return false;
|
|
5585
|
+
}
|
|
5586
|
+
};
|
|
5587
|
+
exports.isGhAuthenticated = isGhAuthenticated;
|
|
5588
|
+
/**
|
|
5589
|
+
* the github repository (owner/name) a git remote points to.
|
|
5590
|
+
* Which remote belongs to github is configured per pipeline type
|
|
5591
|
+
* (`pipelines.github.gitRemote`, defaults to origin).
|
|
5592
|
+
*/
|
|
5593
|
+
const getGithubRepoFromRemote = async remoteName => {
|
|
5594
|
+
try {
|
|
5595
|
+
const {
|
|
5596
|
+
stdout
|
|
5597
|
+
} = await execFile("git", ["remote", "get-url", remoteName]);
|
|
5598
|
+
const match = stdout.match(/github\.com[:/]([\w.-]+\/[\w.-]+?)(\.git)?\s*$/);
|
|
5599
|
+
return match === null || match === void 0 ? void 0 : match[1];
|
|
5600
|
+
} catch (_a) {
|
|
5601
|
+
return undefined;
|
|
5602
|
+
}
|
|
5603
|
+
};
|
|
5604
|
+
exports.getGithubRepoFromRemote = getGithubRepoFromRemote;
|
|
5605
|
+
/**
|
|
5606
|
+
* sets a github actions repository secret via the gh cli.
|
|
5607
|
+
* The value is passed via stdin so it never shows up in a process list.
|
|
5608
|
+
*/
|
|
5609
|
+
const setGithubSecret = async (repo, name, value) => new Promise((resolve, reject) => {
|
|
5610
|
+
var _a, _b;
|
|
5611
|
+
const child = (0, child_process_1.spawn)("gh", ["secret", "set", name, "--repo", repo], {
|
|
5612
|
+
stdio: ["pipe", "ignore", "pipe"]
|
|
5613
|
+
});
|
|
5614
|
+
let stderr = "";
|
|
5615
|
+
(_a = child.stderr) === null || _a === void 0 ? void 0 : _a.on("data", data => stderr += data);
|
|
5616
|
+
child.on("error", reject);
|
|
5617
|
+
child.on("close", code => code === 0 ? resolve() : reject(new Error(`gh secret set ${name} failed: ${stderr.trim()}`)));
|
|
5618
|
+
(_b = child.stdin) === null || _b === void 0 ? void 0 : _b.end(value);
|
|
5619
|
+
});
|
|
5620
|
+
exports.setGithubSecret = setGithubSecret;
|
|
5621
|
+
|
|
5622
|
+
/***/ }),
|
|
5623
|
+
|
|
5309
5624
|
/***/ 4508:
|
|
5310
5625
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
5311
5626
|
|
|
@@ -5845,6 +6160,1017 @@ exports.getShell = getShell;
|
|
|
5845
6160
|
|
|
5846
6161
|
/***/ }),
|
|
5847
6162
|
|
|
6163
|
+
/***/ 63510:
|
|
6164
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6165
|
+
|
|
6166
|
+
"use strict";
|
|
6167
|
+
|
|
6168
|
+
|
|
6169
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6170
|
+
value: true
|
|
6171
|
+
}));
|
|
6172
|
+
exports.BitwardenVault = void 0;
|
|
6173
|
+
const pipeline_1 = __nccwpck_require__(60241);
|
|
6174
|
+
const yaml_1 = __nccwpck_require__(6637);
|
|
6175
|
+
const bw_1 = __nccwpck_require__(52211);
|
|
6176
|
+
const DEFAULT_COLLECTION = "catladder";
|
|
6177
|
+
const SECURE_NOTE_TYPE = 2;
|
|
6178
|
+
/**
|
|
6179
|
+
* one yaml note per env and component:
|
|
6180
|
+
* `<customerName>/<appName>/<env>/<componentName>/secrets.yml`
|
|
6181
|
+
*/
|
|
6182
|
+
const itemName = (config, env, componentName) => `${config.customerName}/${config.appName}/${env}/${componentName}/secrets.yml`;
|
|
6183
|
+
const itemPrefix = config => `${config.customerName}/${config.appName}/`;
|
|
6184
|
+
/**
|
|
6185
|
+
* parses env and componentName back out of an item name
|
|
6186
|
+
*/
|
|
6187
|
+
const parseItemName = (config, name) => {
|
|
6188
|
+
const match = name.slice(itemPrefix(config).length).match(/^([^/]+)\/([^/]+)\/secrets\.yml$/);
|
|
6189
|
+
return match ? {
|
|
6190
|
+
env: match[1],
|
|
6191
|
+
componentName: match[2]
|
|
6192
|
+
} : null;
|
|
6193
|
+
};
|
|
6194
|
+
const findCollection = async (session, collectionName) => {
|
|
6195
|
+
const collections = await (0, bw_1.runBwJson)(session, ["list", "collections", "--search", collectionName]);
|
|
6196
|
+
const collection = collections.find(c => c.name === collectionName);
|
|
6197
|
+
if (!collection) {
|
|
6198
|
+
throw new Error(`bitwarden collection '${collectionName}' not found — create it and make sure you have access`);
|
|
6199
|
+
}
|
|
6200
|
+
return collection;
|
|
6201
|
+
};
|
|
6202
|
+
const encodePayload = payload => Buffer.from(JSON.stringify(payload), "utf-8").toString("base64");
|
|
6203
|
+
class BitwardenVault {
|
|
6204
|
+
constructor(config, options,
|
|
6205
|
+
/**
|
|
6206
|
+
* whether a locked bitwarden may be unlocked interactively
|
|
6207
|
+
* (false with catenv --vault-mode no-prompt)
|
|
6208
|
+
*/
|
|
6209
|
+
allowPrompt) {
|
|
6210
|
+
var _a;
|
|
6211
|
+
this.config = config;
|
|
6212
|
+
this.allowPrompt = allowPrompt;
|
|
6213
|
+
this.collectionName = (_a = options.collection) !== null && _a !== void 0 ? _a : DEFAULT_COLLECTION;
|
|
6214
|
+
this.id = `bitwarden:${this.collectionName}`;
|
|
6215
|
+
}
|
|
6216
|
+
session(io) {
|
|
6217
|
+
return (0, bw_1.getBwSession)(io, {
|
|
6218
|
+
allowPrompt: this.allowPrompt
|
|
6219
|
+
});
|
|
6220
|
+
}
|
|
6221
|
+
async readAllSecrets(io) {
|
|
6222
|
+
const {
|
|
6223
|
+
config,
|
|
6224
|
+
collectionName
|
|
6225
|
+
} = this;
|
|
6226
|
+
const bwSession = await this.session(io);
|
|
6227
|
+
const collection = await findCollection(bwSession, collectionName);
|
|
6228
|
+
const items = await (0, bw_1.runBwJson)(bwSession, ["list", "items", "--collectionid", collection.id]);
|
|
6229
|
+
const secrets = {};
|
|
6230
|
+
for (const item of items) {
|
|
6231
|
+
const parsed = parseItemName(config, item.name);
|
|
6232
|
+
if (!parsed || !item.notes) {
|
|
6233
|
+
continue;
|
|
6234
|
+
}
|
|
6235
|
+
const values = (0, yaml_1.parse)(item.notes);
|
|
6236
|
+
Object.entries(values !== null && values !== void 0 ? values : {}).forEach(([key, value]) => {
|
|
6237
|
+
secrets[(0, pipeline_1.getSecretVarName)(parsed.env, parsed.componentName, key)] = typeof value === "string" ? value : JSON.stringify(value);
|
|
6238
|
+
});
|
|
6239
|
+
}
|
|
6240
|
+
return secrets;
|
|
6241
|
+
}
|
|
6242
|
+
async writeSecrets(io, env, componentName, secrets) {
|
|
6243
|
+
const {
|
|
6244
|
+
config,
|
|
6245
|
+
collectionName
|
|
6246
|
+
} = this;
|
|
6247
|
+
const bwSession = await this.session(io);
|
|
6248
|
+
const collection = await findCollection(bwSession, collectionName);
|
|
6249
|
+
const name = itemName(config, env, componentName);
|
|
6250
|
+
const existing = (await (0, bw_1.runBwJson)(bwSession, ["list", "items", "--collectionid", collection.id, "--search", name])).find(item => item.name === name);
|
|
6251
|
+
const notes = (0, yaml_1.stringify)(secrets);
|
|
6252
|
+
if (existing) {
|
|
6253
|
+
await (0, bw_1.runBw)(bwSession, ["edit", "item", existing.id, encodePayload({
|
|
6254
|
+
...existing,
|
|
6255
|
+
notes
|
|
6256
|
+
})]);
|
|
6257
|
+
} else {
|
|
6258
|
+
await (0, bw_1.runBw)(bwSession, ["create", "item", encodePayload({
|
|
6259
|
+
type: SECURE_NOTE_TYPE,
|
|
6260
|
+
secureNote: {
|
|
6261
|
+
type: 0
|
|
6262
|
+
},
|
|
6263
|
+
name,
|
|
6264
|
+
notes,
|
|
6265
|
+
...(collection.organizationId ? {
|
|
6266
|
+
organizationId: collection.organizationId,
|
|
6267
|
+
collectionIds: [collection.id]
|
|
6268
|
+
} : {})
|
|
6269
|
+
})]);
|
|
6270
|
+
}
|
|
6271
|
+
}
|
|
6272
|
+
}
|
|
6273
|
+
exports.BitwardenVault = BitwardenVault;
|
|
6274
|
+
|
|
6275
|
+
/***/ }),
|
|
6276
|
+
|
|
6277
|
+
/***/ 31107:
|
|
6278
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6279
|
+
|
|
6280
|
+
"use strict";
|
|
6281
|
+
|
|
6282
|
+
|
|
6283
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6284
|
+
value: true
|
|
6285
|
+
}));
|
|
6286
|
+
exports.GitlabVault = void 0;
|
|
6287
|
+
const gitlab_1 = __nccwpck_require__(4508);
|
|
6288
|
+
/**
|
|
6289
|
+
* the legacy (and default) vault: the gitlab project variables double
|
|
6290
|
+
* as the secret store
|
|
6291
|
+
*/
|
|
6292
|
+
class GitlabVault {
|
|
6293
|
+
constructor() {
|
|
6294
|
+
this.id = "gitlab";
|
|
6295
|
+
}
|
|
6296
|
+
async readAllSecrets(io) {
|
|
6297
|
+
const variables = await (0, gitlab_1.getAllVariables)(io);
|
|
6298
|
+
return Object.fromEntries(variables.map(v => [v.key, v.value]));
|
|
6299
|
+
}
|
|
6300
|
+
async writeSecrets(io, env, componentName, secrets) {
|
|
6301
|
+
await (0, gitlab_1.upsertAllVariables)(io, secrets, env, componentName);
|
|
6302
|
+
}
|
|
6303
|
+
}
|
|
6304
|
+
exports.GitlabVault = GitlabVault;
|
|
6305
|
+
|
|
6306
|
+
/***/ }),
|
|
6307
|
+
|
|
6308
|
+
/***/ 55771:
|
|
6309
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6310
|
+
|
|
6311
|
+
"use strict";
|
|
6312
|
+
|
|
6313
|
+
|
|
6314
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6315
|
+
value: true
|
|
6316
|
+
}));
|
|
6317
|
+
exports.VaultManager = void 0;
|
|
6318
|
+
const pipeline_1 = __nccwpck_require__(60241);
|
|
6319
|
+
const BitwardenVault_1 = __nccwpck_require__(63510);
|
|
6320
|
+
const cache_1 = __nccwpck_require__(14236);
|
|
6321
|
+
const GitlabVault_1 = __nccwpck_require__(31107);
|
|
6322
|
+
/**
|
|
6323
|
+
* only secrets of this env are cached locally — the other envs'
|
|
6324
|
+
* secrets have no business sitting on developer machines
|
|
6325
|
+
*/
|
|
6326
|
+
const CACHED_ENV = "local";
|
|
6327
|
+
/**
|
|
6328
|
+
* owns the configured vault, the secrets mode and the local cache.
|
|
6329
|
+
* The vault is the readable source of truth for secrets; CI backends
|
|
6330
|
+
* only receive mirrored copies.
|
|
6331
|
+
*/
|
|
6332
|
+
class VaultManager {
|
|
6333
|
+
constructor(config, options = {}) {
|
|
6334
|
+
var _a, _b;
|
|
6335
|
+
this.config = config;
|
|
6336
|
+
/** refresh mode bypasses the cache only once per manager */
|
|
6337
|
+
this.refreshed = false;
|
|
6338
|
+
this.mode = (_a = options.mode) !== null && _a !== void 0 ? _a : "auto";
|
|
6339
|
+
this.io = (_b = options.io) !== null && _b !== void 0 ? _b : null;
|
|
6340
|
+
this.vault = this.createVault();
|
|
6341
|
+
}
|
|
6342
|
+
createVault() {
|
|
6343
|
+
const vaultConfig = (0, pipeline_1.getVaultConfig)(this.config);
|
|
6344
|
+
switch (vaultConfig.type) {
|
|
6345
|
+
case "gitlab":
|
|
6346
|
+
return new GitlabVault_1.GitlabVault();
|
|
6347
|
+
case "bitwarden":
|
|
6348
|
+
return new BitwardenVault_1.BitwardenVault(this.config, vaultConfig, this.mode === "auto" || this.mode === "refresh");
|
|
6349
|
+
}
|
|
6350
|
+
}
|
|
6351
|
+
/**
|
|
6352
|
+
* the vault secrets, served from the local cache when it contains
|
|
6353
|
+
* all required names; otherwise (depending on the mode) refreshed
|
|
6354
|
+
* from the vault. Only the "local" env is (re-)cached.
|
|
6355
|
+
*/
|
|
6356
|
+
async readSecrets(requiredNames, io = this.io) {
|
|
6357
|
+
const bypassCache = this.mode === "refresh" && !this.refreshed;
|
|
6358
|
+
const cache = bypassCache ? null : await (0, cache_1.readSecretsCache)();
|
|
6359
|
+
// known entries include recorded misses (null values), so declared
|
|
6360
|
+
// but intentionally unset secrets don't force a vault refresh
|
|
6361
|
+
const known = (cache === null || cache === void 0 ? void 0 : cache.vaultId) === this.vault.id ? flattenSecrets(cache.secrets) : undefined;
|
|
6362
|
+
const missing = requiredNames.filter(name => !(name in (known !== null && known !== void 0 ? known : {})));
|
|
6363
|
+
// nothing missing (or nothing required at all): don't touch the vault
|
|
6364
|
+
if (missing.length === 0 && (known || requiredNames.length === 0)) {
|
|
6365
|
+
return withoutMisses(known !== null && known !== void 0 ? known : {});
|
|
6366
|
+
}
|
|
6367
|
+
if (this.mode === "offline") {
|
|
6368
|
+
if (missing.length > 0) {
|
|
6369
|
+
io === null || io === void 0 ? void 0 : io.log(`⚠️ vault is offline (--vault-mode offline) and ${missing.length} secrets are not in the local cache: ${missing.join(", ")}`);
|
|
6370
|
+
}
|
|
6371
|
+
return withoutMisses(known !== null && known !== void 0 ? known : {});
|
|
6372
|
+
}
|
|
6373
|
+
const secrets = await this.vault.readAllSecrets(io);
|
|
6374
|
+
this.refreshed = true;
|
|
6375
|
+
await (0, cache_1.writeSecretsCache)(this.vault.id, await this.cacheableSubset(secrets));
|
|
6376
|
+
return secrets;
|
|
6377
|
+
}
|
|
6378
|
+
/**
|
|
6379
|
+
* writes secrets of one env/component to the vault and updates the
|
|
6380
|
+
* local cache (write-through, "local" env only)
|
|
6381
|
+
*/
|
|
6382
|
+
async writeSecrets(env, componentName, secrets, io = this.io) {
|
|
6383
|
+
if (!io) {
|
|
6384
|
+
throw new Error("writing to the vault requires an interactive context");
|
|
6385
|
+
}
|
|
6386
|
+
await this.vault.writeSecrets(io, env, componentName, secrets);
|
|
6387
|
+
if (env === CACHED_ENV) {
|
|
6388
|
+
await (0, cache_1.updateSecretsCache)(this.vault.id, env, componentName, Object.fromEntries(Object.entries(secrets).map(([key, value]) => [key, typeof value === "string" ? value : JSON.stringify(value)])));
|
|
6389
|
+
}
|
|
6390
|
+
}
|
|
6391
|
+
/**
|
|
6392
|
+
* the subset of the vault secrets that may be cached: the declared
|
|
6393
|
+
* secrets of the "local" env, per component, as a hierarchy
|
|
6394
|
+
*/
|
|
6395
|
+
async cacheableSubset(flatSecrets) {
|
|
6396
|
+
const local = {};
|
|
6397
|
+
for (const componentName of Object.keys(this.config.components)) {
|
|
6398
|
+
const keys = await this.declaredSecretKeys(componentName);
|
|
6399
|
+
const values = Object.fromEntries(keys.map(key => {
|
|
6400
|
+
var _a;
|
|
6401
|
+
return [key,
|
|
6402
|
+
// null records "absent in the vault" (a known miss)
|
|
6403
|
+
(_a = flatSecrets[(0, pipeline_1.getSecretVarName)(CACHED_ENV, componentName, key)]) !== null && _a !== void 0 ? _a : null];
|
|
6404
|
+
}));
|
|
6405
|
+
if (Object.keys(values).length > 0) {
|
|
6406
|
+
local[componentName] = values;
|
|
6407
|
+
}
|
|
6408
|
+
}
|
|
6409
|
+
return Object.keys(local).length > 0 ? {
|
|
6410
|
+
[CACHED_ENV]: local
|
|
6411
|
+
} : {};
|
|
6412
|
+
}
|
|
6413
|
+
async declaredSecretKeys(componentName) {
|
|
6414
|
+
try {
|
|
6415
|
+
const {
|
|
6416
|
+
secretEnvVarKeys,
|
|
6417
|
+
jobOnlyVars
|
|
6418
|
+
} = await (0, pipeline_1.getEnvironment)({
|
|
6419
|
+
config: this.config,
|
|
6420
|
+
componentName,
|
|
6421
|
+
env: CACHED_ENV
|
|
6422
|
+
});
|
|
6423
|
+
return [...secretEnvVarKeys, ...jobOnlyVars.build.secretEnvVarKeys, ...jobOnlyVars.deploy.secretEnvVarKeys].map(({
|
|
6424
|
+
key
|
|
6425
|
+
}) => key);
|
|
6426
|
+
} catch (_a) {
|
|
6427
|
+
// components without a local env simply have nothing to cache
|
|
6428
|
+
return [];
|
|
6429
|
+
}
|
|
6430
|
+
}
|
|
6431
|
+
}
|
|
6432
|
+
exports.VaultManager = VaultManager;
|
|
6433
|
+
/**
|
|
6434
|
+
* the cache hierarchy as a flat map of raw secret variable names
|
|
6435
|
+
* (null values = recorded misses)
|
|
6436
|
+
*/
|
|
6437
|
+
const flattenSecrets = secrets => Object.fromEntries(Object.entries(secrets).flatMap(([env, components]) => Object.entries(components).flatMap(([componentName, values]) => Object.entries(values).map(([key, value]) => [(0, pipeline_1.getSecretVarName)(env, componentName, key), value]))));
|
|
6438
|
+
/**
|
|
6439
|
+
* only actual values — recorded misses stay unresolved, like any other
|
|
6440
|
+
* unset variable
|
|
6441
|
+
*/
|
|
6442
|
+
const withoutMisses = known => Object.fromEntries(Object.entries(known).filter(entry => entry[1] !== null));
|
|
6443
|
+
|
|
6444
|
+
/***/ }),
|
|
6445
|
+
|
|
6446
|
+
/***/ 52211:
|
|
6447
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6448
|
+
|
|
6449
|
+
"use strict";
|
|
6450
|
+
|
|
6451
|
+
|
|
6452
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6453
|
+
value: true
|
|
6454
|
+
}));
|
|
6455
|
+
exports.runBwJson = exports.runBw = exports.getBwSession = void 0;
|
|
6456
|
+
const child_process_1 = __nccwpck_require__(35317);
|
|
6457
|
+
const util_1 = __nccwpck_require__(39023);
|
|
6458
|
+
const preferences_1 = __nccwpck_require__(66261);
|
|
6459
|
+
const execFile = (0, util_1.promisify)(child_process_1.execFile);
|
|
6460
|
+
const SESSION_PREFERENCE = "bwsession";
|
|
6461
|
+
class BitwardenLockedError extends Error {
|
|
6462
|
+
constructor() {
|
|
6463
|
+
super("bitwarden is locked and prompting is disabled — run `bw unlock` or catenv without --vault-mode no-prompt");
|
|
6464
|
+
}
|
|
6465
|
+
}
|
|
6466
|
+
/**
|
|
6467
|
+
* runs an interactive bw command that prints a session key on stdout
|
|
6468
|
+
* (login/unlock) while the user types the password on the terminal
|
|
6469
|
+
*/
|
|
6470
|
+
const interactiveSessionCommand = args => new Promise((resolve, reject) => {
|
|
6471
|
+
var _a;
|
|
6472
|
+
const child = (0, child_process_1.spawn)("bw", [...args, "--raw"], {
|
|
6473
|
+
stdio: ["inherit", "pipe", "inherit"]
|
|
6474
|
+
});
|
|
6475
|
+
let session = "";
|
|
6476
|
+
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", data => session += data.toString("utf-8"));
|
|
6477
|
+
child.on("error", reject);
|
|
6478
|
+
child.on("close", code => code === 0 && session.trim() ? resolve(session.trim()) : reject(new Error(`bw ${args[0]} failed`)));
|
|
6479
|
+
});
|
|
6480
|
+
const getBwStatus = async session => {
|
|
6481
|
+
try {
|
|
6482
|
+
const {
|
|
6483
|
+
stdout
|
|
6484
|
+
} = await execFile("bw", ["status"], {
|
|
6485
|
+
env: {
|
|
6486
|
+
...process.env,
|
|
6487
|
+
...(session ? {
|
|
6488
|
+
BW_SESSION: session
|
|
6489
|
+
} : {})
|
|
6490
|
+
}
|
|
6491
|
+
});
|
|
6492
|
+
return JSON.parse(stdout).status;
|
|
6493
|
+
} catch (_a) {
|
|
6494
|
+
return "unauthenticated";
|
|
6495
|
+
}
|
|
6496
|
+
};
|
|
6497
|
+
/**
|
|
6498
|
+
* a working bw session: reuses the cached one, otherwise unlocks (or
|
|
6499
|
+
* logs in) interactively — unless prompting is disabled
|
|
6500
|
+
*/
|
|
6501
|
+
const getBwSession = async (io, {
|
|
6502
|
+
allowPrompt
|
|
6503
|
+
}) => {
|
|
6504
|
+
const cached = (await (0, preferences_1.hasPreference)(SESSION_PREFERENCE)) ? String(await (0, preferences_1.getPreference)(SESSION_PREFERENCE)) : null;
|
|
6505
|
+
const status = await getBwStatus(cached);
|
|
6506
|
+
if (status === "unlocked" && cached) {
|
|
6507
|
+
return cached;
|
|
6508
|
+
}
|
|
6509
|
+
if (!allowPrompt) {
|
|
6510
|
+
throw new BitwardenLockedError();
|
|
6511
|
+
}
|
|
6512
|
+
io === null || io === void 0 ? void 0 : io.log("");
|
|
6513
|
+
io === null || io === void 0 ? void 0 : io.log(status === "unauthenticated" ? "# Please login to Bitwarden:" : "# Bitwarden is locked, please unlock:");
|
|
6514
|
+
io === null || io === void 0 ? void 0 : io.log("");
|
|
6515
|
+
const session = await interactiveSessionCommand([status === "unauthenticated" ? "login" : "unlock"]);
|
|
6516
|
+
await (0, preferences_1.setPreference)(SESSION_PREFERENCE, session);
|
|
6517
|
+
await (0, exports.runBw)(session, ["sync"]);
|
|
6518
|
+
return session;
|
|
6519
|
+
};
|
|
6520
|
+
exports.getBwSession = getBwSession;
|
|
6521
|
+
/**
|
|
6522
|
+
* runs a bw command with the given session and returns stdout
|
|
6523
|
+
*/
|
|
6524
|
+
const runBw = async (session, args) => {
|
|
6525
|
+
const {
|
|
6526
|
+
stdout
|
|
6527
|
+
} = await execFile("bw", [...args, "--raw", "--nointeraction"], {
|
|
6528
|
+
env: {
|
|
6529
|
+
...process.env,
|
|
6530
|
+
BW_SESSION: session
|
|
6531
|
+
},
|
|
6532
|
+
maxBuffer: 50 * 1024 * 1024
|
|
6533
|
+
});
|
|
6534
|
+
return stdout;
|
|
6535
|
+
};
|
|
6536
|
+
exports.runBw = runBw;
|
|
6537
|
+
const runBwJson = async (session, args) => JSON.parse(await (0, exports.runBw)(session, args));
|
|
6538
|
+
exports.runBwJson = runBwJson;
|
|
6539
|
+
|
|
6540
|
+
/***/ }),
|
|
6541
|
+
|
|
6542
|
+
/***/ 14236:
|
|
6543
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6544
|
+
|
|
6545
|
+
"use strict";
|
|
6546
|
+
|
|
6547
|
+
|
|
6548
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6549
|
+
value: true
|
|
6550
|
+
}));
|
|
6551
|
+
exports.updateSecretsCache = exports.writeSecretsCache = exports.readSecretsCache = void 0;
|
|
6552
|
+
const promises_1 = __nccwpck_require__(91943);
|
|
6553
|
+
const path_1 = __nccwpck_require__(16928);
|
|
6554
|
+
const gitProjectInformation_1 = __nccwpck_require__(21111);
|
|
6555
|
+
const getCacheFolder = async () => (0, path_1.join)(await (0, gitProjectInformation_1.getProjectRootPath)(), ".catladder");
|
|
6556
|
+
const getCachePath = async () => (0, path_1.join)(await getCacheFolder(), "secrets.json");
|
|
6557
|
+
const readSecretsCache = async () => {
|
|
6558
|
+
try {
|
|
6559
|
+
return JSON.parse(await (0, promises_1.readFile)(await getCachePath(), "utf-8"));
|
|
6560
|
+
} catch (_a) {
|
|
6561
|
+
return null;
|
|
6562
|
+
}
|
|
6563
|
+
};
|
|
6564
|
+
exports.readSecretsCache = readSecretsCache;
|
|
6565
|
+
const writeSecretsCache = async (vaultId, secrets) => {
|
|
6566
|
+
const folder = await getCacheFolder();
|
|
6567
|
+
await (0, promises_1.mkdir)(folder, {
|
|
6568
|
+
recursive: true
|
|
6569
|
+
});
|
|
6570
|
+
// the folder ignores itself, so the cache can never be committed
|
|
6571
|
+
await (0, promises_1.writeFile)((0, path_1.join)(folder, ".gitignore"), "*\n");
|
|
6572
|
+
const cache = {
|
|
6573
|
+
vaultId,
|
|
6574
|
+
updatedAt: new Date().toISOString(),
|
|
6575
|
+
secrets
|
|
6576
|
+
};
|
|
6577
|
+
await (0, promises_1.writeFile)(await getCachePath(), JSON.stringify(cache, null, 2));
|
|
6578
|
+
};
|
|
6579
|
+
exports.writeSecretsCache = writeSecretsCache;
|
|
6580
|
+
/**
|
|
6581
|
+
* merges freshly written secrets of one env/component into the cache
|
|
6582
|
+
* (write-through from config-secrets), so the next catenv run doesn't
|
|
6583
|
+
* need the vault
|
|
6584
|
+
*/
|
|
6585
|
+
const updateSecretsCache = async (vaultId, env, componentName, values) => {
|
|
6586
|
+
var _a;
|
|
6587
|
+
const existing = await (0, exports.readSecretsCache)();
|
|
6588
|
+
const secrets = (existing === null || existing === void 0 ? void 0 : existing.vaultId) === vaultId ? existing.secrets : {};
|
|
6589
|
+
secrets[env] = {
|
|
6590
|
+
...secrets[env],
|
|
6591
|
+
[componentName]: {
|
|
6592
|
+
...((_a = secrets[env]) === null || _a === void 0 ? void 0 : _a[componentName]),
|
|
6593
|
+
...values
|
|
6594
|
+
}
|
|
6595
|
+
};
|
|
6596
|
+
await (0, exports.writeSecretsCache)(vaultId, secrets);
|
|
6597
|
+
};
|
|
6598
|
+
exports.updateSecretsCache = updateSecretsCache;
|
|
6599
|
+
|
|
6600
|
+
/***/ }),
|
|
6601
|
+
|
|
6602
|
+
/***/ 54038:
|
|
6603
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6604
|
+
|
|
6605
|
+
"use strict";
|
|
6606
|
+
|
|
6607
|
+
|
|
6608
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6609
|
+
value: true
|
|
6610
|
+
}));
|
|
6611
|
+
exports.GithubBackend = void 0;
|
|
6612
|
+
const promises_1 = __nccwpck_require__(91943);
|
|
6613
|
+
const path_1 = __nccwpck_require__(16928);
|
|
6614
|
+
const createAllJobs_1 = __nccwpck_require__(83671);
|
|
6615
|
+
const config_1 = __nccwpck_require__(96925);
|
|
6616
|
+
const ciVariables_1 = __nccwpck_require__(25474);
|
|
6617
|
+
const createGithubJobs_1 = __nccwpck_require__(14016);
|
|
6618
|
+
const githubReleaseJobs_1 = __nccwpck_require__(55611);
|
|
6619
|
+
const WORKFLOWS_FOLDER = ".github/workflows";
|
|
6620
|
+
/**
|
|
6621
|
+
* generated workflow files are prefixed so that cleanup never touches
|
|
6622
|
+
* user-maintained workflows in the same folder
|
|
6623
|
+
*/
|
|
6624
|
+
const GENERATED_FILE_PREFIX = "catladder-";
|
|
6625
|
+
const TRIGGER_WORKFLOWS = {
|
|
6626
|
+
mr: {
|
|
6627
|
+
name: "catladder review",
|
|
6628
|
+
on: {
|
|
6629
|
+
pull_request: {
|
|
6630
|
+
types: ["opened", "synchronize", "reopened"]
|
|
6631
|
+
}
|
|
6632
|
+
},
|
|
6633
|
+
concurrency: {
|
|
6634
|
+
group: "catladder-review-${{ github.event.number }}",
|
|
6635
|
+
"cancel-in-progress": true
|
|
6636
|
+
}
|
|
6637
|
+
},
|
|
6638
|
+
mainBranch: {
|
|
6639
|
+
name: "catladder main",
|
|
6640
|
+
// TODO: make the default branch configurable
|
|
6641
|
+
on: {
|
|
6642
|
+
push: {
|
|
6643
|
+
branches: ["main"]
|
|
6644
|
+
}
|
|
6645
|
+
}
|
|
6646
|
+
},
|
|
6647
|
+
taggedRelease: {
|
|
6648
|
+
name: "catladder release",
|
|
6649
|
+
on: {
|
|
6650
|
+
push: {
|
|
6651
|
+
tags: ["v*"]
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6654
|
+
}
|
|
6655
|
+
};
|
|
6656
|
+
class GithubBackend {
|
|
6657
|
+
constructor() {
|
|
6658
|
+
this.type = "github";
|
|
6659
|
+
}
|
|
6660
|
+
async cleanup() {
|
|
6661
|
+
const entries = await (0, promises_1.readdir)(WORKFLOWS_FOLDER).catch(() => []);
|
|
6662
|
+
await Promise.all(entries.filter(file => file.startsWith(GENERATED_FILE_PREFIX)).map(file => (0, promises_1.unlink)((0, path_1.join)(WORKFLOWS_FOLDER, file))));
|
|
6663
|
+
}
|
|
6664
|
+
async createFiles(config) {
|
|
6665
|
+
const workflows = await this.createWorkflows(config);
|
|
6666
|
+
return Object.entries(workflows).map(([fileName, workflow]) => ({
|
|
6667
|
+
path: (0, path_1.join)(WORKFLOWS_FOLDER, fileName),
|
|
6668
|
+
content: workflow
|
|
6669
|
+
}));
|
|
6670
|
+
}
|
|
6671
|
+
/**
|
|
6672
|
+
* all workflows keyed by file name, mainly for testing purposes
|
|
6673
|
+
*/
|
|
6674
|
+
async createWorkflows(config) {
|
|
6675
|
+
const workflows = {};
|
|
6676
|
+
const reviewStopJobs = {};
|
|
6677
|
+
const manualJobs = {};
|
|
6678
|
+
for (const trigger of config_1.ALL_PIPELINE_TRIGGERS) {
|
|
6679
|
+
const allJobs = await (0, createAllJobs_1.createAllJobs)({
|
|
6680
|
+
config,
|
|
6681
|
+
trigger,
|
|
6682
|
+
pipelineType: this.type
|
|
6683
|
+
});
|
|
6684
|
+
const uploadProviderIds = (0, createGithubJobs_1.getUploadProviderIds)(allJobs);
|
|
6685
|
+
const jobs = {};
|
|
6686
|
+
// NOTE: agent jobs are gitlab-only and skipped on github
|
|
6687
|
+
[...allJobs.workspaces, ...allJobs.components].forEach(({
|
|
6688
|
+
context,
|
|
6689
|
+
jobs: contextJobs
|
|
6690
|
+
}) => contextJobs.forEach(job => {
|
|
6691
|
+
const [id, githubJob] = (0, createGithubJobs_1.makeGithubJob)(context, job, allJobs, uploadProviderIds);
|
|
6692
|
+
if (isReviewStopJob(context, job)) {
|
|
6693
|
+
reviewStopJobs[id] = githubJob;
|
|
6694
|
+
} else if (isManualTaskJob(job)) {
|
|
6695
|
+
manualJobs[id] = githubJob;
|
|
6696
|
+
} else {
|
|
6697
|
+
jobs[id] = githubJob;
|
|
6698
|
+
}
|
|
6699
|
+
}));
|
|
6700
|
+
if (trigger === "mainBranch") {
|
|
6701
|
+
const releaseJobs = (0, githubReleaseJobs_1.getGithubReleaseJobs)(config, Object.keys(jobs));
|
|
6702
|
+
Object.assign(jobs, releaseJobs.main);
|
|
6703
|
+
Object.assign(manualJobs, releaseJobs.manual);
|
|
6704
|
+
}
|
|
6705
|
+
if (Object.keys(jobs).length > 0) {
|
|
6706
|
+
workflows[`${GENERATED_FILE_PREFIX}${workflowFileName(trigger)}`] = {
|
|
6707
|
+
...TRIGGER_WORKFLOWS[trigger],
|
|
6708
|
+
env: ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV,
|
|
6709
|
+
jobs
|
|
6710
|
+
};
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6713
|
+
if (Object.keys(reviewStopJobs).length > 0) {
|
|
6714
|
+
workflows[`${GENERATED_FILE_PREFIX}review-stop.yml`] = {
|
|
6715
|
+
name: "catladder review stop",
|
|
6716
|
+
on: {
|
|
6717
|
+
pull_request: {
|
|
6718
|
+
types: ["closed"]
|
|
6719
|
+
}
|
|
6720
|
+
},
|
|
6721
|
+
env: ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV,
|
|
6722
|
+
jobs: reviewStopJobs
|
|
6723
|
+
};
|
|
6724
|
+
}
|
|
6725
|
+
if (Object.keys(manualJobs).length > 0) {
|
|
6726
|
+
workflows[`${GENERATED_FILE_PREFIX}manual.yml`] = {
|
|
6727
|
+
name: "catladder manual tasks",
|
|
6728
|
+
on: {
|
|
6729
|
+
workflow_dispatch: {
|
|
6730
|
+
inputs: {
|
|
6731
|
+
job: {
|
|
6732
|
+
description: "the task to run",
|
|
6733
|
+
required: true,
|
|
6734
|
+
type: "choice",
|
|
6735
|
+
options: Object.keys(manualJobs)
|
|
6736
|
+
}
|
|
6737
|
+
}
|
|
6738
|
+
}
|
|
6739
|
+
},
|
|
6740
|
+
env: ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV,
|
|
6741
|
+
jobs: Object.fromEntries(Object.entries(manualJobs).map(([id, job]) => [id, {
|
|
6742
|
+
...job,
|
|
6743
|
+
if: `\${{ inputs.job == '${id}' }}`
|
|
6744
|
+
}]))
|
|
6745
|
+
};
|
|
6746
|
+
}
|
|
6747
|
+
return workflows;
|
|
6748
|
+
}
|
|
6749
|
+
}
|
|
6750
|
+
exports.GithubBackend = GithubBackend;
|
|
6751
|
+
const workflowFileName = trigger => {
|
|
6752
|
+
switch (trigger) {
|
|
6753
|
+
case "mr":
|
|
6754
|
+
return "review.yml";
|
|
6755
|
+
case "mainBranch":
|
|
6756
|
+
return "main.yml";
|
|
6757
|
+
case "taggedRelease":
|
|
6758
|
+
return "release.yml";
|
|
6759
|
+
}
|
|
6760
|
+
throw new Error(`${trigger} is not supported`);
|
|
6761
|
+
};
|
|
6762
|
+
/**
|
|
6763
|
+
* stop jobs of review environments run in their own workflow when the
|
|
6764
|
+
* pull request is closed (the counterpart of gitlab's on_stop wiring)
|
|
6765
|
+
*/
|
|
6766
|
+
const isReviewStopJob = (context, job) => {
|
|
6767
|
+
var _a;
|
|
6768
|
+
return ((_a = job.environment) === null || _a === void 0 ? void 0 : _a.action) === "stop" && context.type === "component" && context.environment.envType === "review";
|
|
6769
|
+
};
|
|
6770
|
+
/**
|
|
6771
|
+
* stop/rollback jobs of non-review environments have no automatic
|
|
6772
|
+
* trigger; they are collected in a workflow_dispatch workflow
|
|
6773
|
+
* (gitlab runs them as manual jobs inside the pipeline)
|
|
6774
|
+
*/
|
|
6775
|
+
const isManualTaskJob = job => job.stage === "stop" || job.stage === "rollback";
|
|
6776
|
+
|
|
6777
|
+
/***/ }),
|
|
6778
|
+
|
|
6779
|
+
/***/ 25474:
|
|
6780
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
6781
|
+
|
|
6782
|
+
"use strict";
|
|
6783
|
+
|
|
6784
|
+
|
|
6785
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6786
|
+
value: true
|
|
6787
|
+
}));
|
|
6788
|
+
exports.GITHUB_INJECTED_WORKFLOW_ENV = exports.GITHUB_CI_VARIABLES = void 0;
|
|
6789
|
+
/**
|
|
6790
|
+
* how the github backend names the predefined CI variables.
|
|
6791
|
+
*
|
|
6792
|
+
* GITHUB_* variables are provided by github actions natively; the CL_*
|
|
6793
|
+
* variables are injected by the {@link GithubBackend} itself (workflow or
|
|
6794
|
+
* job level), because github has no direct counterpart.
|
|
6795
|
+
*/
|
|
6796
|
+
exports.GITHUB_CI_VARIABLES = {
|
|
6797
|
+
commitSha: "GITHUB_SHA",
|
|
6798
|
+
jobToken: "CL_JOB_TOKEN",
|
|
6799
|
+
jobImage: "CL_JOB_IMAGE",
|
|
6800
|
+
registry: "CL_REGISTRY",
|
|
6801
|
+
registryImage: "CL_REGISTRY_IMAGE"
|
|
6802
|
+
};
|
|
6803
|
+
/**
|
|
6804
|
+
* the workflow-level env the backend injects to provide the CL_*
|
|
6805
|
+
* variables referenced by {@link GITHUB_CI_VARIABLES}
|
|
6806
|
+
*/
|
|
6807
|
+
exports.GITHUB_INJECTED_WORKFLOW_ENV = {
|
|
6808
|
+
CL_JOB_TOKEN: "${{ github.token }}",
|
|
6809
|
+
CL_REGISTRY: "ghcr.io",
|
|
6810
|
+
CL_REGISTRY_IMAGE: "ghcr.io/${{ github.repository }}",
|
|
6811
|
+
// empty outside of pull request events
|
|
6812
|
+
CL_PR_NUMBER: "${{ github.event.number }}"
|
|
6813
|
+
};
|
|
6814
|
+
|
|
6815
|
+
/***/ }),
|
|
6816
|
+
|
|
6817
|
+
/***/ 14016:
|
|
6818
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
6819
|
+
|
|
6820
|
+
"use strict";
|
|
6821
|
+
|
|
6822
|
+
|
|
6823
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
6824
|
+
value: true
|
|
6825
|
+
}));
|
|
6826
|
+
exports.getUploadProviderIds = exports.makeGithubJob = exports.resolveGithubNeeds = exports.githubJobId = void 0;
|
|
6827
|
+
const lodash_es_1 = __nccwpck_require__(64284);
|
|
6828
|
+
const getInjectVarsScript_1 = __nccwpck_require__(90436);
|
|
6829
|
+
const createJobCache_1 = __nccwpck_require__(65644);
|
|
6830
|
+
const getEnvironmentVariables_1 = __nccwpck_require__(85855);
|
|
6831
|
+
const utils_1 = __nccwpck_require__(20595);
|
|
6832
|
+
const gitlab_1 = __nccwpck_require__(13468);
|
|
6833
|
+
const scriptFunctions_1 = __nccwpck_require__(75759);
|
|
6834
|
+
/**
|
|
6835
|
+
* runner variables that only make sense on gitlab runners and must not
|
|
6836
|
+
* leak into github jobs (docker-in-docker daemon config, kubernetes
|
|
6837
|
+
* executor resource requests, gitlab clone strategy)
|
|
6838
|
+
*/
|
|
6839
|
+
const GITLAB_ONLY_RUNNER_VARIABLES = new Set(["DOCKER_HOST", "DOCKER_TLS_CERTDIR", "DOCKER_DRIVER", "KUBERNETES_CPU_REQUEST", "KUBERNETES_MEMORY_REQUEST", "KUBERNETES_CPU_LIMIT", "KUBERNETES_MEMORY_LIMIT", "GIT_STRATEGY"]);
|
|
6840
|
+
/**
|
|
6841
|
+
* github runs docker natively on its runners, gitlab needs a
|
|
6842
|
+
* docker-in-docker service for it
|
|
6843
|
+
*/
|
|
6844
|
+
const isDindService = image => /(^|\/)docker:.*dind/.test(image);
|
|
6845
|
+
const slug = value => {
|
|
6846
|
+
const slugged = value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
6847
|
+
// job ids must start with a letter or _
|
|
6848
|
+
return /^[a-z_]/.test(slugged) ? slugged : `job-${slugged}`;
|
|
6849
|
+
};
|
|
6850
|
+
const githubJobId = (context, jobName) => slug(`${context.type === "workspace" ? "ws-" : ""}${context.name}-${jobName}-${context.env}`);
|
|
6851
|
+
exports.githubJobId = githubJobId;
|
|
6852
|
+
const githubJobName = (context, jobName) => `${context.name} ${jobName} | ${context.env}`;
|
|
6853
|
+
const resolveNeed = (context, need, allJobs) => {
|
|
6854
|
+
var _a;
|
|
6855
|
+
const env = context.env;
|
|
6856
|
+
const findComponentJob = (componentName, jobName) => {
|
|
6857
|
+
const provider = allJobs.components.find(c => c.context.name === componentName && c.context.env === env);
|
|
6858
|
+
const job = provider === null || provider === void 0 ? void 0 : provider.jobs.find(j => j.name === jobName);
|
|
6859
|
+
if (!provider || !job) {
|
|
6860
|
+
throw new Error(`unknown job referenced: '${jobName}' from '${env}:${componentName}'`);
|
|
6861
|
+
}
|
|
6862
|
+
return (0, exports.githubJobId)(provider.context, jobName);
|
|
6863
|
+
};
|
|
6864
|
+
const findWorkspaceJob = (workspaceName, jobName) => {
|
|
6865
|
+
const provider = allJobs.workspaces.find(w => w.context.name === workspaceName && w.context.env === env);
|
|
6866
|
+
const job = provider === null || provider === void 0 ? void 0 : provider.jobs.find(j => j.name === jobName);
|
|
6867
|
+
if (!provider || !job) {
|
|
6868
|
+
throw new Error(`unknown job referenced: '${jobName}' from workspace '${env}:${workspaceName}'`);
|
|
6869
|
+
}
|
|
6870
|
+
return (0, exports.githubJobId)(provider.context, jobName);
|
|
6871
|
+
};
|
|
6872
|
+
if ((0, lodash_es_1.isObject)(need)) {
|
|
6873
|
+
if ("workspaceName" in need && need.workspaceName) {
|
|
6874
|
+
return {
|
|
6875
|
+
id: findWorkspaceJob(need.workspaceName, need.job),
|
|
6876
|
+
artifacts: need.artifacts
|
|
6877
|
+
};
|
|
6878
|
+
}
|
|
6879
|
+
return {
|
|
6880
|
+
id: findComponentJob((_a = "componentName" in need ? need.componentName : undefined) !== null && _a !== void 0 ? _a : context.name, need.job),
|
|
6881
|
+
artifacts: need.artifacts
|
|
6882
|
+
};
|
|
6883
|
+
}
|
|
6884
|
+
return {
|
|
6885
|
+
id: context.type === "workspace" ? findWorkspaceJob(context.name, need) : findComponentJob(context.name, need),
|
|
6886
|
+
// plain string needs download artifacts by default (gitlab semantics)
|
|
6887
|
+
artifacts: true
|
|
6888
|
+
};
|
|
6889
|
+
};
|
|
6890
|
+
const resolveGithubNeeds = (context, job, allJobs) => {
|
|
6891
|
+
var _a;
|
|
6892
|
+
const resolved = ((_a = job.needs) !== null && _a !== void 0 ? _a : []).map(need => resolveNeed(context, need, allJobs));
|
|
6893
|
+
// deduplicate by provider id, explicit entries win (they come last)
|
|
6894
|
+
return [...new Map(resolved.map(n => [n.id, n])).values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
6895
|
+
};
|
|
6896
|
+
exports.resolveGithubNeeds = resolveGithubNeeds;
|
|
6897
|
+
const createCacheSteps = (context, job) => {
|
|
6898
|
+
var _a, _b;
|
|
6899
|
+
if (!((_a = job.caches) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
6900
|
+
return [];
|
|
6901
|
+
}
|
|
6902
|
+
const lowered = (_b = (0, createJobCache_1.createJobCacheFromCacheConfigs)(context, job.caches)) !== null && _b !== void 0 ? _b : [];
|
|
6903
|
+
return (0, utils_1.ensureArray)(lowered).map(cache => {
|
|
6904
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6905
|
+
const paths = (0, utils_1.ensureArray)((_a = cache.paths) !== null && _a !== void 0 ? _a : []);
|
|
6906
|
+
const key = cache.key;
|
|
6907
|
+
const {
|
|
6908
|
+
cacheKey,
|
|
6909
|
+
restoreKeyPrefix,
|
|
6910
|
+
label
|
|
6911
|
+
} = typeof key === "string" || key === undefined ? {
|
|
6912
|
+
// unique key per run so the cache is re-saved, restored via prefix
|
|
6913
|
+
cacheKey: `${key !== null && key !== void 0 ? key : "cache"}-\${{ github.run_id }}`,
|
|
6914
|
+
restoreKeyPrefix: `${key !== null && key !== void 0 ? key : "cache"}-`,
|
|
6915
|
+
label: key !== null && key !== void 0 ? key : "cache"
|
|
6916
|
+
} : {
|
|
6917
|
+
cacheKey: `${(_b = key.prefix) !== null && _b !== void 0 ? _b : "files"}-\${{ hashFiles(${((_c = key.files) !== null && _c !== void 0 ? _c : []).map(f => `'${f}'`).join(", ")}) }}`,
|
|
6918
|
+
restoreKeyPrefix: `${(_d = key.prefix) !== null && _d !== void 0 ? _d : "files"}-`,
|
|
6919
|
+
label: (_e = key.prefix) !== null && _e !== void 0 ? _e : ((_f = key.files) !== null && _f !== void 0 ? _f : []).join(",")
|
|
6920
|
+
};
|
|
6921
|
+
return {
|
|
6922
|
+
name: `Cache ${label}`,
|
|
6923
|
+
// pull-only caches are restored but never saved
|
|
6924
|
+
uses: cache.policy === "pull" ? "actions/cache/restore@v4" : "actions/cache@v4",
|
|
6925
|
+
with: {
|
|
6926
|
+
path: paths.join("\n"),
|
|
6927
|
+
key: cacheKey,
|
|
6928
|
+
"restore-keys": restoreKeyPrefix
|
|
6929
|
+
}
|
|
6930
|
+
};
|
|
6931
|
+
});
|
|
6932
|
+
};
|
|
6933
|
+
const getSecretsEnv = context => {
|
|
6934
|
+
var _a, _b;
|
|
6935
|
+
const keys = [...context.environment.secretEnvVarKeys, ...((_a = context.environment.jobOnlyVars.build.secretEnvVarKeys) !== null && _a !== void 0 ? _a : []), ...((_b = context.environment.jobOnlyVars.deploy.secretEnvVarKeys) !== null && _b !== void 0 ? _b : [])];
|
|
6936
|
+
return Object.fromEntries(keys.map(({
|
|
6937
|
+
key
|
|
6938
|
+
}) => {
|
|
6939
|
+
const name = (0, getEnvironmentVariables_1.getSecretVarName)(context.env, context.name, key);
|
|
6940
|
+
return [name, `\${{ secrets.${name} }}`];
|
|
6941
|
+
}));
|
|
6942
|
+
};
|
|
6943
|
+
const makeGithubJob = (context, job, allJobs, uploadProviderIds) => {
|
|
6944
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
6945
|
+
const id = (0, exports.githubJobId)(context, job.name);
|
|
6946
|
+
const isComponent = context.type === "component";
|
|
6947
|
+
const createsJobEnv = !!job.environment && isComponent && (!job.environment.action || job.environment.action === "start");
|
|
6948
|
+
const skipCheckout = ((_a = job.runnerVariables) === null || _a === void 0 ? void 0 : _a.GIT_STRATEGY) === "none";
|
|
6949
|
+
const needs = (0, exports.resolveGithubNeeds)(context, job, allJobs);
|
|
6950
|
+
const image = typeof job.image === "string" ? job.image : Array.isArray(job.image) ? job.image[0] : (_b = job.image) === null || _b === void 0 ? void 0 : _b.name;
|
|
6951
|
+
const runScript = [...(0, scriptFunctions_1.getGithubScriptFunctionDefinitions)(), ...(0, gitlab_1.collapseableSection)("injectvars", "Injecting variables")((0, getInjectVarsScript_1.getInjectVarsScript)((_c = job.variables) !== null && _c !== void 0 ? _c : {})), ...((_e = (_d = job.script) === null || _d === void 0 ? void 0 : _d.filter(utils_1.notNil)) !== null && _e !== void 0 ? _e : []), ...(createsJobEnv ? [`echo "url=$ROOT_URL" >> "$GITHUB_OUTPUT"`] : [])].join("\n");
|
|
6952
|
+
const artifactPaths = (_g = (_f = job.artifacts) === null || _f === void 0 ? void 0 : _f.paths) !== null && _g !== void 0 ? _g : [];
|
|
6953
|
+
const services = Object.fromEntries(((_h = job.services) !== null && _h !== void 0 ? _h : []).map(service => typeof service === "string" ? {
|
|
6954
|
+
name: service
|
|
6955
|
+
} : service).filter(service => !isDindService(service.name)).map(service => [slug("alias" in service && service.alias ? service.alias : service.name), {
|
|
6956
|
+
image: service.name,
|
|
6957
|
+
...("variables" in service && service.variables ? {
|
|
6958
|
+
env: service.variables
|
|
6959
|
+
} : {})
|
|
6960
|
+
}]));
|
|
6961
|
+
const env = {
|
|
6962
|
+
...Object.fromEntries(Object.entries((_j = job.runnerVariables) !== null && _j !== void 0 ? _j : {}).filter(([key]) => !GITLAB_ONLY_RUNNER_VARIABLES.has(key))),
|
|
6963
|
+
...(isComponent ? getSecretsEnv(context) : {}),
|
|
6964
|
+
CL_JOB_IMAGE: image !== null && image !== void 0 ? image : "runner"
|
|
6965
|
+
};
|
|
6966
|
+
const githubJob = {
|
|
6967
|
+
name: githubJobName(context, job.name),
|
|
6968
|
+
"runs-on": "ubuntu-latest",
|
|
6969
|
+
...(needs.length > 0 ? {
|
|
6970
|
+
needs: needs.map(n => n.id)
|
|
6971
|
+
} : {}),
|
|
6972
|
+
...(image ? {
|
|
6973
|
+
container: {
|
|
6974
|
+
image
|
|
6975
|
+
}
|
|
6976
|
+
} : {}),
|
|
6977
|
+
...(Object.keys(services).length > 0 ? {
|
|
6978
|
+
services
|
|
6979
|
+
} : {}),
|
|
6980
|
+
...(job.environment && isComponent ? {
|
|
6981
|
+
environment: {
|
|
6982
|
+
name: context.environment.envType === "review" ? `review-pr\${{ github.event.number }}-${context.name}` : `${context.env}-${context.name}`,
|
|
6983
|
+
...(createsJobEnv ? {
|
|
6984
|
+
url: "${{ steps.main.outputs.url }}"
|
|
6985
|
+
} : {})
|
|
6986
|
+
}
|
|
6987
|
+
} : {}),
|
|
6988
|
+
env,
|
|
6989
|
+
steps: [...(skipCheckout ? [] : [{
|
|
6990
|
+
name: "Checkout",
|
|
6991
|
+
uses: "actions/checkout@v4"
|
|
6992
|
+
}]), ...createCacheSteps(context, job), ...needs.filter(n => n.artifacts).map(n => ({
|
|
6993
|
+
name: `Download artifacts from ${n.id}`,
|
|
6994
|
+
uses: "actions/download-artifact@v4",
|
|
6995
|
+
with: {
|
|
6996
|
+
name: n.id
|
|
6997
|
+
}
|
|
6998
|
+
})), {
|
|
6999
|
+
name: job.name,
|
|
7000
|
+
id: "main",
|
|
7001
|
+
run: runScript,
|
|
7002
|
+
shell: "bash"
|
|
7003
|
+
}, ...(uploadProviderIds.has(id) || artifactPaths.length > 0 ? artifactPaths.length > 0 ? [{
|
|
7004
|
+
name: "Upload artifacts",
|
|
7005
|
+
uses: "actions/upload-artifact@v4",
|
|
7006
|
+
with: {
|
|
7007
|
+
name: id,
|
|
7008
|
+
path: artifactPaths.join("\n"),
|
|
7009
|
+
"if-no-files-found": "warn"
|
|
7010
|
+
}
|
|
7011
|
+
}] : [] : [])]
|
|
7012
|
+
};
|
|
7013
|
+
return [id, githubJob];
|
|
7014
|
+
};
|
|
7015
|
+
exports.makeGithubJob = makeGithubJob;
|
|
7016
|
+
/**
|
|
7017
|
+
* the ids of all jobs whose artifacts are consumed by other jobs
|
|
7018
|
+
* (they need an upload step)
|
|
7019
|
+
*/
|
|
7020
|
+
const getUploadProviderIds = allJobs => {
|
|
7021
|
+
const ids = new Set();
|
|
7022
|
+
[...allJobs.workspaces, ...allJobs.components].forEach(({
|
|
7023
|
+
context,
|
|
7024
|
+
jobs
|
|
7025
|
+
}) => jobs.forEach(job => (0, exports.resolveGithubNeeds)(context, job, allJobs).filter(n => n.artifacts).forEach(n => ids.add(n.id))));
|
|
7026
|
+
return ids;
|
|
7027
|
+
};
|
|
7028
|
+
exports.getUploadProviderIds = getUploadProviderIds;
|
|
7029
|
+
|
|
7030
|
+
/***/ }),
|
|
7031
|
+
|
|
7032
|
+
/***/ 55611:
|
|
7033
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
7034
|
+
|
|
7035
|
+
"use strict";
|
|
7036
|
+
|
|
7037
|
+
|
|
7038
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
7039
|
+
value: true
|
|
7040
|
+
}));
|
|
7041
|
+
exports.getGithubReleaseJobs = void 0;
|
|
7042
|
+
const runner_1 = __nccwpck_require__(92348);
|
|
7043
|
+
const createReleaseJob = needs => ({
|
|
7044
|
+
name: "create release",
|
|
7045
|
+
"runs-on": "ubuntu-latest",
|
|
7046
|
+
container: {
|
|
7047
|
+
image: (0, runner_1.getRunnerImage)("semantic-release")
|
|
7048
|
+
},
|
|
7049
|
+
// semantic-release pushes the version tag and release commit
|
|
7050
|
+
permissions: {
|
|
7051
|
+
contents: "write"
|
|
7052
|
+
},
|
|
7053
|
+
...(needs && needs.length > 0 ? {
|
|
7054
|
+
needs
|
|
7055
|
+
} : {}),
|
|
7056
|
+
env: {
|
|
7057
|
+
GITHUB_TOKEN: "${{ github.token }}"
|
|
7058
|
+
},
|
|
7059
|
+
steps: [{
|
|
7060
|
+
name: "Checkout",
|
|
7061
|
+
uses: "actions/checkout@v4",
|
|
7062
|
+
// semantic-release needs the full history to determine the version
|
|
7063
|
+
with: {
|
|
7064
|
+
"fetch-depth": 0
|
|
7065
|
+
}
|
|
7066
|
+
}, {
|
|
7067
|
+
name: "create release",
|
|
7068
|
+
run: "semanticRelease",
|
|
7069
|
+
shell: "bash"
|
|
7070
|
+
}]
|
|
7071
|
+
});
|
|
7072
|
+
/**
|
|
7073
|
+
* the release jobs for the github backend (the counterpart of the
|
|
7074
|
+
* gitlab release jobs):
|
|
7075
|
+
* - releases.when === "auto": the release job runs in the main-branch
|
|
7076
|
+
* workflow after all other jobs; a force variant goes to the manual
|
|
7077
|
+
* tasks workflow
|
|
7078
|
+
* - otherwise (manual, the default): the release job goes to the
|
|
7079
|
+
* manual tasks workflow
|
|
7080
|
+
*/
|
|
7081
|
+
const getGithubReleaseJobs = (config, mainWorkflowJobIds) => {
|
|
7082
|
+
var _a;
|
|
7083
|
+
if (((_a = config.releases) === null || _a === void 0 ? void 0 : _a.when) === "auto") {
|
|
7084
|
+
return {
|
|
7085
|
+
main: {
|
|
7086
|
+
"create-release": createReleaseJob(mainWorkflowJobIds)
|
|
7087
|
+
},
|
|
7088
|
+
manual: {
|
|
7089
|
+
"force-create-release": createReleaseJob()
|
|
7090
|
+
}
|
|
7091
|
+
};
|
|
7092
|
+
}
|
|
7093
|
+
return {
|
|
7094
|
+
main: {},
|
|
7095
|
+
manual: {
|
|
7096
|
+
"create-release": createReleaseJob()
|
|
7097
|
+
}
|
|
7098
|
+
};
|
|
7099
|
+
};
|
|
7100
|
+
exports.getGithubReleaseJobs = getGithubReleaseJobs;
|
|
7101
|
+
|
|
7102
|
+
/***/ }),
|
|
7103
|
+
|
|
7104
|
+
/***/ 99635:
|
|
7105
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
7106
|
+
|
|
7107
|
+
"use strict";
|
|
7108
|
+
|
|
7109
|
+
|
|
7110
|
+
var __createBinding = this && this.__createBinding || (Object.create ? function (o, m, k, k2) {
|
|
7111
|
+
if (k2 === undefined) k2 = k;
|
|
7112
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7113
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7114
|
+
desc = {
|
|
7115
|
+
enumerable: true,
|
|
7116
|
+
get: function () {
|
|
7117
|
+
return m[k];
|
|
7118
|
+
}
|
|
7119
|
+
};
|
|
7120
|
+
}
|
|
7121
|
+
Object.defineProperty(o, k2, desc);
|
|
7122
|
+
} : function (o, m, k, k2) {
|
|
7123
|
+
if (k2 === undefined) k2 = k;
|
|
7124
|
+
o[k2] = m[k];
|
|
7125
|
+
});
|
|
7126
|
+
var __exportStar = this && this.__exportStar || function (m, exports) {
|
|
7127
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
7128
|
+
};
|
|
7129
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
7130
|
+
value: true
|
|
7131
|
+
}));
|
|
7132
|
+
__exportStar(__nccwpck_require__(54038), exports);
|
|
7133
|
+
__exportStar(__nccwpck_require__(25474), exports);
|
|
7134
|
+
|
|
7135
|
+
/***/ }),
|
|
7136
|
+
|
|
7137
|
+
/***/ 75759:
|
|
7138
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
7139
|
+
|
|
7140
|
+
"use strict";
|
|
7141
|
+
|
|
7142
|
+
|
|
7143
|
+
Object.defineProperty(exports, "__esModule", ({
|
|
7144
|
+
value: true
|
|
7145
|
+
}));
|
|
7146
|
+
exports.getGithubScriptFunctionDefinitions = void 0;
|
|
7147
|
+
const globalScriptFunctions_1 = __nccwpck_require__(53891);
|
|
7148
|
+
/**
|
|
7149
|
+
* github variants of the global script functions where the gitlab
|
|
7150
|
+
* implementation uses gitlab-specific mechanics (e.g. collapsible log
|
|
7151
|
+
* sections use gitlab's `section_start` escape codes, github uses
|
|
7152
|
+
* `::group::` workflow commands). All other functions are plain bash
|
|
7153
|
+
* and shared as-is.
|
|
7154
|
+
*/
|
|
7155
|
+
const GITHUB_FUNCTION_OVERRIDES = {
|
|
7156
|
+
collapseable_section_start: `local section_title="\${1}"
|
|
7157
|
+
local section_description="\${2:-$section_title}"
|
|
7158
|
+
echo "::group::\${section_description}"`,
|
|
7159
|
+
collapseable_section_end: `echo "::endgroup::"`
|
|
7160
|
+
};
|
|
7161
|
+
/**
|
|
7162
|
+
* the bash function definitions to prepend to every job script.
|
|
7163
|
+
* github has no pipeline-wide before_script like gitlab, so each job
|
|
7164
|
+
* carries its own definitions.
|
|
7165
|
+
*/
|
|
7166
|
+
const getGithubScriptFunctionDefinitions = () => [...globalScriptFunctions_1.globalScriptFunctions.values()].map(fn => {
|
|
7167
|
+
const override = GITHUB_FUNCTION_OVERRIDES[fn.name];
|
|
7168
|
+
return override ? `function ${fn.name} () {\n${override.trim()}\n}` : fn.toBashFunction();
|
|
7169
|
+
});
|
|
7170
|
+
exports.getGithubScriptFunctionDefinitions = getGithubScriptFunctionDefinitions;
|
|
7171
|
+
|
|
7172
|
+
/***/ }),
|
|
7173
|
+
|
|
5848
7174
|
/***/ 22278:
|
|
5849
7175
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
5850
7176
|
|
|
@@ -5855,6 +7181,7 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
5855
7181
|
value: true
|
|
5856
7182
|
}));
|
|
5857
7183
|
exports.GitlabBackend = void 0;
|
|
7184
|
+
const promises_1 = __nccwpck_require__(91943);
|
|
5858
7185
|
const rules_1 = __nccwpck_require__(44565);
|
|
5859
7186
|
const config_1 = __nccwpck_require__(96925);
|
|
5860
7187
|
const createAllJobs_1 = __nccwpck_require__(83671);
|
|
@@ -5870,6 +7197,12 @@ class GitlabBackend {
|
|
|
5870
7197
|
this.type = "gitlab";
|
|
5871
7198
|
this.generatedFolder = GITLAB_GENERATED_FOLDER;
|
|
5872
7199
|
}
|
|
7200
|
+
async cleanup() {
|
|
7201
|
+
await (0, promises_1.rm)(this.generatedFolder, {
|
|
7202
|
+
force: true,
|
|
7203
|
+
recursive: true
|
|
7204
|
+
});
|
|
7205
|
+
}
|
|
5873
7206
|
async createFiles(config) {
|
|
5874
7207
|
const includes = await this.createIncludes(config);
|
|
5875
7208
|
const mainFile = {
|
|
@@ -6584,12 +7917,15 @@ var __exportStar = this && this.__exportStar || function (m, exports) {
|
|
|
6584
7917
|
Object.defineProperty(exports, "__esModule", ({
|
|
6585
7918
|
value: true
|
|
6586
7919
|
}));
|
|
6587
|
-
exports.getEnabledPipelineTypes = exports.getPipelineBackend = void 0;
|
|
7920
|
+
exports.getEnabledPipelineTypes = exports.getVaultConfig = exports.getPipelineGitRemote = exports.getPipelineOptions = exports.getPipelineBackend = void 0;
|
|
7921
|
+
const github_1 = __nccwpck_require__(99635);
|
|
6588
7922
|
const gitlab_1 = __nccwpck_require__(8475);
|
|
6589
7923
|
__exportStar(__nccwpck_require__(92474), exports);
|
|
6590
7924
|
__exportStar(__nccwpck_require__(8475), exports);
|
|
7925
|
+
__exportStar(__nccwpck_require__(99635), exports);
|
|
6591
7926
|
const BACKENDS = {
|
|
6592
|
-
gitlab: () => new gitlab_1.GitlabBackend()
|
|
7927
|
+
gitlab: () => new gitlab_1.GitlabBackend(),
|
|
7928
|
+
github: () => new github_1.GithubBackend()
|
|
6593
7929
|
};
|
|
6594
7930
|
const getPipelineBackend = type => {
|
|
6595
7931
|
const createBackend = BACKENDS[type];
|
|
@@ -6599,6 +7935,38 @@ const getPipelineBackend = type => {
|
|
|
6599
7935
|
return createBackend();
|
|
6600
7936
|
};
|
|
6601
7937
|
exports.getPipelineBackend = getPipelineBackend;
|
|
7938
|
+
/**
|
|
7939
|
+
* the options of an enabled pipeline type (empty object when enabled
|
|
7940
|
+
* with `true`)
|
|
7941
|
+
*/
|
|
7942
|
+
const getPipelineOptions = (config, type) => {
|
|
7943
|
+
var _a;
|
|
7944
|
+
const value = (_a = config.pipelines) === null || _a === void 0 ? void 0 : _a[type];
|
|
7945
|
+
return typeof value === "object" ? value : {};
|
|
7946
|
+
};
|
|
7947
|
+
exports.getPipelineOptions = getPipelineOptions;
|
|
7948
|
+
/**
|
|
7949
|
+
* the git remote pointing to the repository of this pipeline type's CI
|
|
7950
|
+
* system (e.g. during a migration, gitlab may be `origin` and github a
|
|
7951
|
+
* second remote)
|
|
7952
|
+
*/
|
|
7953
|
+
const getPipelineGitRemote = (config, type) => {
|
|
7954
|
+
var _a;
|
|
7955
|
+
return (_a = (0, exports.getPipelineOptions)(config, type).gitRemote) !== null && _a !== void 0 ? _a : "origin";
|
|
7956
|
+
};
|
|
7957
|
+
exports.getPipelineGitRemote = getPipelineGitRemote;
|
|
7958
|
+
/**
|
|
7959
|
+
* the normalized secrets vault of a config (string shorthands resolved
|
|
7960
|
+
* to their object form; defaults to the legacy gitlab store)
|
|
7961
|
+
*/
|
|
7962
|
+
const getVaultConfig = config => {
|
|
7963
|
+
var _a, _b;
|
|
7964
|
+
const vault = (_b = (_a = config.secrets) === null || _a === void 0 ? void 0 : _a.vault) !== null && _b !== void 0 ? _b : "gitlab";
|
|
7965
|
+
return typeof vault === "string" ? {
|
|
7966
|
+
type: vault
|
|
7967
|
+
} : vault;
|
|
7968
|
+
};
|
|
7969
|
+
exports.getVaultConfig = getVaultConfig;
|
|
6602
7970
|
/**
|
|
6603
7971
|
* the pipeline types enabled for this config. Multiple types can be
|
|
6604
7972
|
* enabled at once (parallel generation, e.g. during a CI migration).
|
|
@@ -6941,10 +8309,12 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
6941
8309
|
value: true
|
|
6942
8310
|
}));
|
|
6943
8311
|
exports.getCiVariable = void 0;
|
|
6944
|
-
const ciVariables_1 = __nccwpck_require__(
|
|
8312
|
+
const ciVariables_1 = __nccwpck_require__(25474);
|
|
8313
|
+
const ciVariables_2 = __nccwpck_require__(78506);
|
|
6945
8314
|
const BashExpression_1 = __nccwpck_require__(25354);
|
|
6946
8315
|
const CI_VARIABLES_PER_PIPELINE_TYPE = {
|
|
6947
|
-
gitlab:
|
|
8316
|
+
gitlab: ciVariables_2.GITLAB_CI_VARIABLES,
|
|
8317
|
+
github: ciVariables_1.GITHUB_CI_VARIABLES
|
|
6948
8318
|
};
|
|
6949
8319
|
/**
|
|
6950
8320
|
* resolves a platform-neutral CI variable to a bash expression for the
|
|
@@ -8563,7 +9933,7 @@ Object.defineProperty(exports, "__esModule", ({
|
|
|
8563
9933
|
value: true
|
|
8564
9934
|
}));
|
|
8565
9935
|
exports.DOCKER_REGISTRY = exports.PIPELINE_IMAGE_TAG = void 0;
|
|
8566
|
-
exports.PIPELINE_IMAGE_TAG = "next-
|
|
9936
|
+
exports.PIPELINE_IMAGE_TAG = "next-8b9ad5ca" || 0;
|
|
8567
9937
|
exports.DOCKER_REGISTRY = "git.panter.ch:5001/catladder/catladder" || 0;
|
|
8568
9938
|
|
|
8569
9939
|
/***/ }),
|
|
@@ -9130,7 +10500,9 @@ const bashExpressionPerPipelineType_1 = __nccwpck_require__(61945);
|
|
|
9130
10500
|
const getEnvType_1 = __nccwpck_require__(28254);
|
|
9131
10501
|
const REVIEW_SLUG = {
|
|
9132
10502
|
default: "unknown-review-slug",
|
|
9133
|
-
gitlab: new BashExpression_1.BashExpression(`$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })`)
|
|
10503
|
+
gitlab: new BashExpression_1.BashExpression(`$([ -n "$CI_MERGE_REQUEST_IID" ] && echo "mr$CI_MERGE_REQUEST_IID" || { [ -n "$CI_COMMIT_REF_SLUG" ] && echo "$CI_COMMIT_REF_SLUG" || echo "unknown"; })`),
|
|
10504
|
+
// CL_PR_NUMBER is injected by the github backend at the workflow level
|
|
10505
|
+
github: new BashExpression_1.BashExpression(`$([ -n "$CL_PR_NUMBER" ] && echo "pr$CL_PR_NUMBER" || echo "unknown")`)
|
|
9134
10506
|
};
|
|
9135
10507
|
const getReviewSlug = (envConfig, env, pipelineType) => {
|
|
9136
10508
|
const envType = (0, getEnvType_1.getEnvType)(env, envConfig);
|
|
@@ -10466,13 +11838,15 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
|
|
|
10466
11838
|
}
|
|
10467
11839
|
return {};
|
|
10468
11840
|
},
|
|
10469
|
-
additionalSecretKeys: ctx => [
|
|
11841
|
+
additionalSecretKeys: ctx => [
|
|
11842
|
+
// deploy-time credentials don't exist for the local env
|
|
11843
|
+
...(ctx.envType !== "local" ? [{
|
|
10470
11844
|
key: exports.GCLOUD_DEPLOY_CREDENTIALS_KEY,
|
|
10471
11845
|
hidden: true
|
|
10472
11846
|
}, {
|
|
10473
11847
|
key: exports.GCLOUD_RUN_CANONICAL_HOST_SUFFIX,
|
|
10474
11848
|
hidden: true
|
|
10475
|
-
}, ...(ctx.deployConfigRaw && ctx.deployConfigRaw.cloudSql ? [{
|
|
11849
|
+
}] : []), ...(ctx.deployConfigRaw && ctx.deployConfigRaw.cloudSql ? [{
|
|
10476
11850
|
key: "DB_PASSWORD"
|
|
10477
11851
|
}] : [])],
|
|
10478
11852
|
getAdditionalEnvVars: ctx => {
|
|
@@ -10480,7 +11854,8 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
|
|
|
10480
11854
|
fullName,
|
|
10481
11855
|
env,
|
|
10482
11856
|
componentName,
|
|
10483
|
-
deployConfigRaw
|
|
11857
|
+
deployConfigRaw,
|
|
11858
|
+
envType
|
|
10484
11859
|
} = ctx;
|
|
10485
11860
|
const HOSTNAME_INTERNAL = (0, BashExpression_1.joinBashExpressions)([fullName, (0, BashExpression_1.getBashVariable)((0, context_1.getSecretVarName)(env, componentName, exports.GCLOUD_RUN_CANONICAL_HOST_SUFFIX))], "-").toLowerCase();
|
|
10486
11861
|
const jobTriggers = deployConfigRaw && deployConfigRaw.jobs ? Object.fromEntries(Object.entries(deployConfigRaw.jobs).filter(([name, job]) => Boolean(job)).map(([name, job]) => ["CLOUD_RUN_JOB_TRIGGER_URL_" + (0, gitlab_1.sanitizeForBashVariable)(name), (0, cloudRunExecutionUrl_1.getCloudRunJobExecuteUrl)(name, {
|
|
@@ -10489,7 +11864,11 @@ exports.GCLOUD_RUN_DEPLOY_TYPE = {
|
|
|
10489
11864
|
region: deployConfigRaw.region
|
|
10490
11865
|
})])) : {};
|
|
10491
11866
|
return {
|
|
10492
|
-
|
|
11867
|
+
// references the canonical host suffix secret, which doesn't
|
|
11868
|
+
// exist for the local env
|
|
11869
|
+
...(envType !== "local" ? {
|
|
11870
|
+
HOSTNAME_INTERNAL
|
|
11871
|
+
} : {}),
|
|
10493
11872
|
...getCloudSqlVariables(ctx),
|
|
10494
11873
|
...jobTriggers,
|
|
10495
11874
|
DEPLOY_CLOUD_RUN_SERVICE_NAME: (0, getServiceName_1.getServiceNameForEnvContext)(ctx),
|
|
@@ -12320,11 +13699,8 @@ async function generatePipelineFiles(context, pipelineType) {
|
|
|
12320
13699
|
exports.generatePipelineFiles = generatePipelineFiles;
|
|
12321
13700
|
async function generatePipelineFilesForBackend(context, backend) {
|
|
12322
13701
|
const files = await backend.createFiles(context.config);
|
|
12323
|
-
// first clean up
|
|
12324
|
-
await (
|
|
12325
|
-
force: true,
|
|
12326
|
-
recursive: true
|
|
12327
|
-
});
|
|
13702
|
+
// first clean up previously generated files
|
|
13703
|
+
await backend.cleanup();
|
|
12328
13704
|
// write files
|
|
12329
13705
|
await Promise.all(files.map(async ({
|
|
12330
13706
|
path,
|
|
@@ -155941,7 +157317,7 @@ function differenceInCalendarMonths(dateLeft, dateRight) {
|
|
|
155941
157317
|
"use strict";
|
|
155942
157318
|
|
|
155943
157319
|
exports.differenceInCalendarQuarters = differenceInCalendarQuarters;
|
|
155944
|
-
var _index = __nccwpck_require__(
|
|
157320
|
+
var _index = __nccwpck_require__(91635);
|
|
155945
157321
|
var _index2 = __nccwpck_require__(65073);
|
|
155946
157322
|
|
|
155947
157323
|
/**
|
|
@@ -160353,7 +161729,7 @@ function getOverlappingDaysInIntervals(intervalLeft, intervalRight) {
|
|
|
160353
161729
|
|
|
160354
161730
|
/***/ }),
|
|
160355
161731
|
|
|
160356
|
-
/***/
|
|
161732
|
+
/***/ 91635:
|
|
160357
161733
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
160358
161734
|
|
|
160359
161735
|
"use strict";
|
|
@@ -161921,7 +163297,7 @@ Object.keys(_index92).forEach(function (key) {
|
|
|
161921
163297
|
},
|
|
161922
163298
|
});
|
|
161923
163299
|
});
|
|
161924
|
-
var _index93 = __nccwpck_require__(
|
|
163300
|
+
var _index93 = __nccwpck_require__(91635);
|
|
161925
163301
|
Object.keys(_index93).forEach(function (key) {
|
|
161926
163302
|
if (key === "default" || key === "__esModule") return;
|
|
161927
163303
|
if (key in exports && exports[key] === _index93[key]) return;
|