@catladder/cli 0.0.0-next-e7541a00 → 0.0.0-next-4e7c6848

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.
Files changed (45) hide show
  1. package/dist/bundles/catenv/index.js +626 -15
  2. package/dist/bundles/cli/index.js +628 -16
  3. package/dist/cli/src/apps/catenv/catenv.js +1 -2
  4. package/dist/cli/src/apps/catenv/catenv.js.map +1 -1
  5. package/dist/pipeline/src/backends/github/GithubBackend.d.ts +12 -0
  6. package/dist/pipeline/src/backends/github/GithubBackend.js +170 -0
  7. package/dist/pipeline/src/backends/github/GithubBackend.js.map +1 -0
  8. package/dist/pipeline/src/backends/github/ciVariables.d.ts +14 -0
  9. package/dist/pipeline/src/backends/github/ciVariables.js +31 -0
  10. package/dist/pipeline/src/backends/github/ciVariables.js.map +1 -0
  11. package/dist/pipeline/src/backends/github/createGithubJobs.d.ts +17 -0
  12. package/dist/pipeline/src/backends/github/createGithubJobs.js +208 -0
  13. package/dist/pipeline/src/backends/github/createGithubJobs.js.map +1 -0
  14. package/dist/pipeline/src/backends/github/githubReleaseJobs.d.ts +15 -0
  15. package/dist/pipeline/src/backends/github/githubReleaseJobs.js +65 -0
  16. package/dist/pipeline/src/backends/github/githubReleaseJobs.js.map +1 -0
  17. package/dist/pipeline/src/backends/github/index.d.ts +2 -0
  18. package/dist/pipeline/src/backends/github/index.js +26 -0
  19. package/dist/pipeline/src/backends/github/index.js.map +1 -0
  20. package/dist/pipeline/src/backends/github/scriptFunctions.d.ts +6 -0
  21. package/dist/pipeline/src/backends/github/scriptFunctions.js +30 -0
  22. package/dist/pipeline/src/backends/github/scriptFunctions.js.map +1 -0
  23. package/dist/pipeline/src/backends/gitlab/GitlabBackend.d.ts +1 -0
  24. package/dist/pipeline/src/backends/gitlab/GitlabBackend.js +7 -0
  25. package/dist/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
  26. package/dist/pipeline/src/backends/index.d.ts +8 -2
  27. package/dist/pipeline/src/backends/index.js +25 -3
  28. package/dist/pipeline/src/backends/index.js.map +1 -1
  29. package/dist/pipeline/src/backends/types.d.ts +7 -3
  30. package/dist/pipeline/src/bash/ciVariables.js +4 -2
  31. package/dist/pipeline/src/bash/ciVariables.js.map +1 -1
  32. package/dist/pipeline/src/constants.js +1 -1
  33. package/dist/pipeline/src/context/getReviewSlug.js +3 -1
  34. package/dist/pipeline/src/context/getReviewSlug.js.map +1 -1
  35. package/dist/pipeline/src/pipeline/generatePipelineFiles.d.ts +6 -1
  36. package/dist/pipeline/src/pipeline/generatePipelineFiles.js +14 -7
  37. package/dist/pipeline/src/pipeline/generatePipelineFiles.js.map +1 -1
  38. package/dist/pipeline/src/types/config.d.ts +20 -0
  39. package/dist/pipeline/src/types/github-types.d.ts +47 -0
  40. package/dist/pipeline/src/types/github-types.js +9 -0
  41. package/dist/pipeline/src/types/github-types.js.map +1 -0
  42. package/dist/pipeline/src/types/pipeline.d.ts +4 -3
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +1 -1
  45. package/src/apps/catenv/catenv.ts +1 -1
@@ -17,7 +17,6 @@ const writeDotEnvFiles_1 = __nccwpck_require__(5614);
17
17
  const writeEnvDTs_1 = __nccwpck_require__(8832);
18
18
  const pipeline_1 = __nccwpck_require__(241);
19
19
  exports["default"] = async (choice, options) => {
20
- var _a;
21
20
  const config = await (0, getProjectConfig_1.getProjectConfig)();
22
21
  if (!config) {
23
22
  return;
@@ -26,7 +25,7 @@ exports["default"] = async (choice, options) => {
26
25
  if (options === null || options === void 0 ? void 0 : options.verbose) {
27
26
  (0, verboseBanner_1.printVerboseBanner)();
28
27
  }
29
- await Promise.all([(0, pipeline_1.generatePipelineFiles)(context, (_a = config.pipelineType) !== null && _a !== void 0 ? _a : "gitlab"), (0, writeDotEnvFiles_1.writeDotEnvFiles)(context, choice), (0, writeEnvDTs_1.writeDTsFiles)(context, choice), (options === null || options === void 0 ? void 0 : options.printVariables) ? (0, printVariables_1.printVariables)(context, choice) : Promise.resolve()]);
28
+ await Promise.all([(0, pipeline_1.generatePipelineFiles)(context), (0, writeDotEnvFiles_1.writeDotEnvFiles)(context, choice), (0, writeEnvDTs_1.writeDTsFiles)(context, choice), (options === null || options === void 0 ? void 0 : options.printVariables) ? (0, printVariables_1.printVariables)(context, choice) : Promise.resolve()]);
30
29
  };
31
30
 
32
31
  /***/ }),
@@ -948,6 +947,578 @@ exports.getProjectNamespace = getProjectNamespace;
948
947
 
949
948
  /***/ }),
950
949
 
950
+ /***/ 4038:
951
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
952
+
953
+ "use strict";
954
+
955
+
956
+ Object.defineProperty(exports, "__esModule", ({
957
+ value: true
958
+ }));
959
+ exports.GithubBackend = void 0;
960
+ const promises_1 = __nccwpck_require__(1943);
961
+ const path_1 = __nccwpck_require__(6928);
962
+ const createAllJobs_1 = __nccwpck_require__(3671);
963
+ const config_1 = __nccwpck_require__(6925);
964
+ const ciVariables_1 = __nccwpck_require__(3093);
965
+ const createGithubJobs_1 = __nccwpck_require__(4016);
966
+ const githubReleaseJobs_1 = __nccwpck_require__(5611);
967
+ const WORKFLOWS_FOLDER = ".github/workflows";
968
+ /**
969
+ * generated workflow files are prefixed so that cleanup never touches
970
+ * user-maintained workflows in the same folder
971
+ */
972
+ const GENERATED_FILE_PREFIX = "catladder-";
973
+ const TRIGGER_WORKFLOWS = {
974
+ mr: {
975
+ name: "catladder review",
976
+ on: {
977
+ pull_request: {
978
+ types: ["opened", "synchronize", "reopened"]
979
+ }
980
+ },
981
+ concurrency: {
982
+ group: "catladder-review-${{ github.event.number }}",
983
+ "cancel-in-progress": true
984
+ }
985
+ },
986
+ mainBranch: {
987
+ name: "catladder main",
988
+ // TODO: make the default branch configurable
989
+ on: {
990
+ push: {
991
+ branches: ["main"]
992
+ }
993
+ }
994
+ },
995
+ taggedRelease: {
996
+ name: "catladder release",
997
+ on: {
998
+ push: {
999
+ tags: ["v*"]
1000
+ }
1001
+ }
1002
+ }
1003
+ };
1004
+ class GithubBackend {
1005
+ constructor() {
1006
+ this.type = "github";
1007
+ }
1008
+ async cleanup() {
1009
+ const entries = await (0, promises_1.readdir)(WORKFLOWS_FOLDER).catch(() => []);
1010
+ await Promise.all(entries.filter(file => file.startsWith(GENERATED_FILE_PREFIX)).map(file => (0, promises_1.unlink)((0, path_1.join)(WORKFLOWS_FOLDER, file))));
1011
+ }
1012
+ async createFiles(config) {
1013
+ const workflows = await this.createWorkflows(config);
1014
+ return Object.entries(workflows).map(([fileName, workflow]) => ({
1015
+ path: (0, path_1.join)(WORKFLOWS_FOLDER, fileName),
1016
+ content: workflow
1017
+ }));
1018
+ }
1019
+ /**
1020
+ * all workflows keyed by file name, mainly for testing purposes
1021
+ */
1022
+ async createWorkflows(config) {
1023
+ const workflows = {};
1024
+ const reviewStopJobs = {};
1025
+ const manualJobs = {};
1026
+ for (const trigger of config_1.ALL_PIPELINE_TRIGGERS) {
1027
+ const allJobs = await (0, createAllJobs_1.createAllJobs)({
1028
+ config,
1029
+ trigger,
1030
+ pipelineType: this.type
1031
+ });
1032
+ const uploadProviderIds = (0, createGithubJobs_1.getUploadProviderIds)(allJobs);
1033
+ const jobs = {};
1034
+ // NOTE: agent jobs are gitlab-only and skipped on github
1035
+ [...allJobs.workspaces, ...allJobs.components].forEach(({
1036
+ context,
1037
+ jobs: contextJobs
1038
+ }) => contextJobs.forEach(job => {
1039
+ const [id, githubJob] = (0, createGithubJobs_1.makeGithubJob)(context, job, allJobs, uploadProviderIds);
1040
+ if (isReviewStopJob(context, job)) {
1041
+ reviewStopJobs[id] = githubJob;
1042
+ } else if (isManualTaskJob(job)) {
1043
+ manualJobs[id] = githubJob;
1044
+ } else {
1045
+ jobs[id] = githubJob;
1046
+ }
1047
+ }));
1048
+ if (trigger === "mainBranch") {
1049
+ const releaseJobs = (0, githubReleaseJobs_1.getGithubReleaseJobs)(config, Object.keys(jobs));
1050
+ Object.assign(jobs, releaseJobs.main);
1051
+ Object.assign(manualJobs, releaseJobs.manual);
1052
+ }
1053
+ if (Object.keys(jobs).length > 0) {
1054
+ workflows[`${GENERATED_FILE_PREFIX}${workflowFileName(trigger)}`] = {
1055
+ ...TRIGGER_WORKFLOWS[trigger],
1056
+ env: ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV,
1057
+ jobs
1058
+ };
1059
+ }
1060
+ }
1061
+ if (Object.keys(reviewStopJobs).length > 0) {
1062
+ workflows[`${GENERATED_FILE_PREFIX}review-stop.yml`] = {
1063
+ name: "catladder review stop",
1064
+ on: {
1065
+ pull_request: {
1066
+ types: ["closed"]
1067
+ }
1068
+ },
1069
+ env: ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV,
1070
+ jobs: reviewStopJobs
1071
+ };
1072
+ }
1073
+ if (Object.keys(manualJobs).length > 0) {
1074
+ workflows[`${GENERATED_FILE_PREFIX}manual.yml`] = {
1075
+ name: "catladder manual tasks",
1076
+ on: {
1077
+ workflow_dispatch: {
1078
+ inputs: {
1079
+ job: {
1080
+ description: "the task to run",
1081
+ required: true,
1082
+ type: "choice",
1083
+ options: Object.keys(manualJobs)
1084
+ }
1085
+ }
1086
+ }
1087
+ },
1088
+ env: ciVariables_1.GITHUB_INJECTED_WORKFLOW_ENV,
1089
+ jobs: Object.fromEntries(Object.entries(manualJobs).map(([id, job]) => [id, {
1090
+ ...job,
1091
+ if: `\${{ inputs.job == '${id}' }}`
1092
+ }]))
1093
+ };
1094
+ }
1095
+ return workflows;
1096
+ }
1097
+ }
1098
+ exports.GithubBackend = GithubBackend;
1099
+ const workflowFileName = trigger => {
1100
+ switch (trigger) {
1101
+ case "mr":
1102
+ return "review.yml";
1103
+ case "mainBranch":
1104
+ return "main.yml";
1105
+ case "taggedRelease":
1106
+ return "release.yml";
1107
+ }
1108
+ throw new Error(`${trigger} is not supported`);
1109
+ };
1110
+ /**
1111
+ * stop jobs of review environments run in their own workflow when the
1112
+ * pull request is closed (the counterpart of gitlab's on_stop wiring)
1113
+ */
1114
+ const isReviewStopJob = (context, job) => {
1115
+ var _a;
1116
+ return ((_a = job.environment) === null || _a === void 0 ? void 0 : _a.action) === "stop" && context.type === "component" && context.environment.envType === "review";
1117
+ };
1118
+ /**
1119
+ * stop/rollback jobs of non-review environments have no automatic
1120
+ * trigger; they are collected in a workflow_dispatch workflow
1121
+ * (gitlab runs them as manual jobs inside the pipeline)
1122
+ */
1123
+ const isManualTaskJob = job => job.stage === "stop" || job.stage === "rollback";
1124
+
1125
+ /***/ }),
1126
+
1127
+ /***/ 3093:
1128
+ /***/ ((__unused_webpack_module, exports) => {
1129
+
1130
+ "use strict";
1131
+
1132
+
1133
+ Object.defineProperty(exports, "__esModule", ({
1134
+ value: true
1135
+ }));
1136
+ exports.GITHUB_INJECTED_WORKFLOW_ENV = exports.GITHUB_CI_VARIABLES = void 0;
1137
+ /**
1138
+ * how the github backend names the predefined CI variables.
1139
+ *
1140
+ * GITHUB_* variables are provided by github actions natively; the CL_*
1141
+ * variables are injected by the {@link GithubBackend} itself (workflow or
1142
+ * job level), because github has no direct counterpart.
1143
+ */
1144
+ exports.GITHUB_CI_VARIABLES = {
1145
+ commitSha: "GITHUB_SHA",
1146
+ jobToken: "CL_JOB_TOKEN",
1147
+ jobImage: "CL_JOB_IMAGE",
1148
+ registry: "CL_REGISTRY",
1149
+ registryImage: "CL_REGISTRY_IMAGE"
1150
+ };
1151
+ /**
1152
+ * the workflow-level env the backend injects to provide the CL_*
1153
+ * variables referenced by {@link GITHUB_CI_VARIABLES}
1154
+ */
1155
+ exports.GITHUB_INJECTED_WORKFLOW_ENV = {
1156
+ CL_JOB_TOKEN: "${{ github.token }}",
1157
+ CL_REGISTRY: "ghcr.io",
1158
+ CL_REGISTRY_IMAGE: "ghcr.io/${{ github.repository }}",
1159
+ // empty outside of pull request events
1160
+ CL_PR_NUMBER: "${{ github.event.number }}"
1161
+ };
1162
+
1163
+ /***/ }),
1164
+
1165
+ /***/ 4016:
1166
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
1167
+
1168
+ "use strict";
1169
+
1170
+
1171
+ Object.defineProperty(exports, "__esModule", ({
1172
+ value: true
1173
+ }));
1174
+ exports.getUploadProviderIds = exports.makeGithubJob = exports.resolveGithubNeeds = exports.githubJobId = void 0;
1175
+ const lodash_es_1 = __nccwpck_require__(4284);
1176
+ const getInjectVarsScript_1 = __nccwpck_require__(436);
1177
+ const createJobCache_1 = __nccwpck_require__(5644);
1178
+ const getEnvironmentVariables_1 = __nccwpck_require__(5855);
1179
+ const utils_1 = __nccwpck_require__(595);
1180
+ const gitlab_1 = __nccwpck_require__(3468);
1181
+ const scriptFunctions_1 = __nccwpck_require__(5759);
1182
+ /**
1183
+ * runner variables that only make sense on gitlab runners and must not
1184
+ * leak into github jobs (docker-in-docker daemon config, kubernetes
1185
+ * executor resource requests, gitlab clone strategy)
1186
+ */
1187
+ 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"]);
1188
+ /**
1189
+ * github runs docker natively on its runners, gitlab needs a
1190
+ * docker-in-docker service for it
1191
+ */
1192
+ const isDindService = image => /(^|\/)docker:.*dind/.test(image);
1193
+ const slug = value => {
1194
+ const slugged = value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1195
+ // job ids must start with a letter or _
1196
+ return /^[a-z_]/.test(slugged) ? slugged : `job-${slugged}`;
1197
+ };
1198
+ const githubJobId = (context, jobName) => slug(`${context.type === "workspace" ? "ws-" : ""}${context.name}-${jobName}-${context.env}`);
1199
+ exports.githubJobId = githubJobId;
1200
+ const githubJobName = (context, jobName) => `${context.name} ${jobName} | ${context.env}`;
1201
+ const resolveNeed = (context, need, allJobs) => {
1202
+ var _a;
1203
+ const env = context.env;
1204
+ const findComponentJob = (componentName, jobName) => {
1205
+ const provider = allJobs.components.find(c => c.context.name === componentName && c.context.env === env);
1206
+ const job = provider === null || provider === void 0 ? void 0 : provider.jobs.find(j => j.name === jobName);
1207
+ if (!provider || !job) {
1208
+ throw new Error(`unknown job referenced: '${jobName}' from '${env}:${componentName}'`);
1209
+ }
1210
+ return (0, exports.githubJobId)(provider.context, jobName);
1211
+ };
1212
+ const findWorkspaceJob = (workspaceName, jobName) => {
1213
+ const provider = allJobs.workspaces.find(w => w.context.name === workspaceName && w.context.env === env);
1214
+ const job = provider === null || provider === void 0 ? void 0 : provider.jobs.find(j => j.name === jobName);
1215
+ if (!provider || !job) {
1216
+ throw new Error(`unknown job referenced: '${jobName}' from workspace '${env}:${workspaceName}'`);
1217
+ }
1218
+ return (0, exports.githubJobId)(provider.context, jobName);
1219
+ };
1220
+ if ((0, lodash_es_1.isObject)(need)) {
1221
+ if ("workspaceName" in need && need.workspaceName) {
1222
+ return {
1223
+ id: findWorkspaceJob(need.workspaceName, need.job),
1224
+ artifacts: need.artifacts
1225
+ };
1226
+ }
1227
+ return {
1228
+ id: findComponentJob((_a = "componentName" in need ? need.componentName : undefined) !== null && _a !== void 0 ? _a : context.name, need.job),
1229
+ artifacts: need.artifacts
1230
+ };
1231
+ }
1232
+ return {
1233
+ id: context.type === "workspace" ? findWorkspaceJob(context.name, need) : findComponentJob(context.name, need),
1234
+ // plain string needs download artifacts by default (gitlab semantics)
1235
+ artifacts: true
1236
+ };
1237
+ };
1238
+ const resolveGithubNeeds = (context, job, allJobs) => {
1239
+ var _a;
1240
+ const resolved = ((_a = job.needs) !== null && _a !== void 0 ? _a : []).map(need => resolveNeed(context, need, allJobs));
1241
+ // deduplicate by provider id, explicit entries win (they come last)
1242
+ return [...new Map(resolved.map(n => [n.id, n])).values()].sort((a, b) => a.id.localeCompare(b.id));
1243
+ };
1244
+ exports.resolveGithubNeeds = resolveGithubNeeds;
1245
+ const createCacheSteps = (context, job) => {
1246
+ var _a, _b;
1247
+ if (!((_a = job.caches) === null || _a === void 0 ? void 0 : _a.length)) {
1248
+ return [];
1249
+ }
1250
+ const lowered = (_b = (0, createJobCache_1.createJobCacheFromCacheConfigs)(context, job.caches)) !== null && _b !== void 0 ? _b : [];
1251
+ return (0, utils_1.ensureArray)(lowered).map(cache => {
1252
+ var _a, _b, _c, _d, _e, _f;
1253
+ const paths = (0, utils_1.ensureArray)((_a = cache.paths) !== null && _a !== void 0 ? _a : []);
1254
+ const key = cache.key;
1255
+ const {
1256
+ cacheKey,
1257
+ restoreKeyPrefix,
1258
+ label
1259
+ } = typeof key === "string" || key === undefined ? {
1260
+ // unique key per run so the cache is re-saved, restored via prefix
1261
+ cacheKey: `${key !== null && key !== void 0 ? key : "cache"}-\${{ github.run_id }}`,
1262
+ restoreKeyPrefix: `${key !== null && key !== void 0 ? key : "cache"}-`,
1263
+ label: key !== null && key !== void 0 ? key : "cache"
1264
+ } : {
1265
+ cacheKey: `${(_b = key.prefix) !== null && _b !== void 0 ? _b : "files"}-\${{ hashFiles(${((_c = key.files) !== null && _c !== void 0 ? _c : []).map(f => `'${f}'`).join(", ")}) }}`,
1266
+ restoreKeyPrefix: `${(_d = key.prefix) !== null && _d !== void 0 ? _d : "files"}-`,
1267
+ label: (_e = key.prefix) !== null && _e !== void 0 ? _e : ((_f = key.files) !== null && _f !== void 0 ? _f : []).join(",")
1268
+ };
1269
+ return {
1270
+ name: `Cache ${label}`,
1271
+ // pull-only caches are restored but never saved
1272
+ uses: cache.policy === "pull" ? "actions/cache/restore@v4" : "actions/cache@v4",
1273
+ with: {
1274
+ path: paths.join("\n"),
1275
+ key: cacheKey,
1276
+ "restore-keys": restoreKeyPrefix
1277
+ }
1278
+ };
1279
+ });
1280
+ };
1281
+ const getSecretsEnv = context => {
1282
+ var _a, _b;
1283
+ 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 : [])];
1284
+ return Object.fromEntries(keys.map(({
1285
+ key
1286
+ }) => {
1287
+ const name = (0, getEnvironmentVariables_1.getSecretVarName)(context.env, context.name, key);
1288
+ return [name, `\${{ secrets.${name} }}`];
1289
+ }));
1290
+ };
1291
+ const makeGithubJob = (context, job, allJobs, uploadProviderIds) => {
1292
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
1293
+ const id = (0, exports.githubJobId)(context, job.name);
1294
+ const isComponent = context.type === "component";
1295
+ const createsJobEnv = !!job.environment && isComponent && (!job.environment.action || job.environment.action === "start");
1296
+ const skipCheckout = ((_a = job.runnerVariables) === null || _a === void 0 ? void 0 : _a.GIT_STRATEGY) === "none";
1297
+ const needs = (0, exports.resolveGithubNeeds)(context, job, allJobs);
1298
+ 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;
1299
+ 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");
1300
+ const artifactPaths = (_g = (_f = job.artifacts) === null || _f === void 0 ? void 0 : _f.paths) !== null && _g !== void 0 ? _g : [];
1301
+ const services = Object.fromEntries(((_h = job.services) !== null && _h !== void 0 ? _h : []).map(service => typeof service === "string" ? {
1302
+ name: service
1303
+ } : service).filter(service => !isDindService(service.name)).map(service => [slug("alias" in service && service.alias ? service.alias : service.name), {
1304
+ image: service.name,
1305
+ ...("variables" in service && service.variables ? {
1306
+ env: service.variables
1307
+ } : {})
1308
+ }]));
1309
+ const env = {
1310
+ ...Object.fromEntries(Object.entries((_j = job.runnerVariables) !== null && _j !== void 0 ? _j : {}).filter(([key]) => !GITLAB_ONLY_RUNNER_VARIABLES.has(key))),
1311
+ ...(isComponent ? getSecretsEnv(context) : {}),
1312
+ CL_JOB_IMAGE: image !== null && image !== void 0 ? image : "runner"
1313
+ };
1314
+ const githubJob = {
1315
+ name: githubJobName(context, job.name),
1316
+ "runs-on": "ubuntu-latest",
1317
+ ...(needs.length > 0 ? {
1318
+ needs: needs.map(n => n.id)
1319
+ } : {}),
1320
+ ...(image ? {
1321
+ container: {
1322
+ image
1323
+ }
1324
+ } : {}),
1325
+ ...(Object.keys(services).length > 0 ? {
1326
+ services
1327
+ } : {}),
1328
+ ...(job.environment && isComponent ? {
1329
+ environment: {
1330
+ name: context.environment.envType === "review" ? `review-pr\${{ github.event.number }}-${context.name}` : `${context.env}-${context.name}`,
1331
+ ...(createsJobEnv ? {
1332
+ url: "${{ steps.main.outputs.url }}"
1333
+ } : {})
1334
+ }
1335
+ } : {}),
1336
+ env,
1337
+ steps: [...(skipCheckout ? [] : [{
1338
+ name: "Checkout",
1339
+ uses: "actions/checkout@v4"
1340
+ }]), ...createCacheSteps(context, job), ...needs.filter(n => n.artifacts).map(n => ({
1341
+ name: `Download artifacts from ${n.id}`,
1342
+ uses: "actions/download-artifact@v4",
1343
+ with: {
1344
+ name: n.id
1345
+ }
1346
+ })), {
1347
+ name: job.name,
1348
+ id: "main",
1349
+ run: runScript,
1350
+ shell: "bash"
1351
+ }, ...(uploadProviderIds.has(id) || artifactPaths.length > 0 ? artifactPaths.length > 0 ? [{
1352
+ name: "Upload artifacts",
1353
+ uses: "actions/upload-artifact@v4",
1354
+ with: {
1355
+ name: id,
1356
+ path: artifactPaths.join("\n"),
1357
+ "if-no-files-found": "warn"
1358
+ }
1359
+ }] : [] : [])]
1360
+ };
1361
+ return [id, githubJob];
1362
+ };
1363
+ exports.makeGithubJob = makeGithubJob;
1364
+ /**
1365
+ * the ids of all jobs whose artifacts are consumed by other jobs
1366
+ * (they need an upload step)
1367
+ */
1368
+ const getUploadProviderIds = allJobs => {
1369
+ const ids = new Set();
1370
+ [...allJobs.workspaces, ...allJobs.components].forEach(({
1371
+ context,
1372
+ jobs
1373
+ }) => jobs.forEach(job => (0, exports.resolveGithubNeeds)(context, job, allJobs).filter(n => n.artifacts).forEach(n => ids.add(n.id))));
1374
+ return ids;
1375
+ };
1376
+ exports.getUploadProviderIds = getUploadProviderIds;
1377
+
1378
+ /***/ }),
1379
+
1380
+ /***/ 5611:
1381
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
1382
+
1383
+ "use strict";
1384
+
1385
+
1386
+ Object.defineProperty(exports, "__esModule", ({
1387
+ value: true
1388
+ }));
1389
+ exports.getGithubReleaseJobs = void 0;
1390
+ const runner_1 = __nccwpck_require__(2348);
1391
+ const createReleaseJob = needs => ({
1392
+ name: "create release",
1393
+ "runs-on": "ubuntu-latest",
1394
+ container: {
1395
+ image: (0, runner_1.getRunnerImage)("semantic-release")
1396
+ },
1397
+ // semantic-release pushes the version tag and release commit
1398
+ permissions: {
1399
+ contents: "write"
1400
+ },
1401
+ ...(needs && needs.length > 0 ? {
1402
+ needs
1403
+ } : {}),
1404
+ env: {
1405
+ GITHUB_TOKEN: "${{ github.token }}"
1406
+ },
1407
+ steps: [{
1408
+ name: "Checkout",
1409
+ uses: "actions/checkout@v4",
1410
+ // semantic-release needs the full history to determine the version
1411
+ with: {
1412
+ "fetch-depth": 0
1413
+ }
1414
+ }, {
1415
+ name: "create release",
1416
+ run: "semanticRelease",
1417
+ shell: "bash"
1418
+ }]
1419
+ });
1420
+ /**
1421
+ * the release jobs for the github backend (the counterpart of the
1422
+ * gitlab release jobs):
1423
+ * - releases.when === "auto": the release job runs in the main-branch
1424
+ * workflow after all other jobs; a force variant goes to the manual
1425
+ * tasks workflow
1426
+ * - otherwise (manual, the default): the release job goes to the
1427
+ * manual tasks workflow
1428
+ */
1429
+ const getGithubReleaseJobs = (config, mainWorkflowJobIds) => {
1430
+ var _a;
1431
+ if (((_a = config.releases) === null || _a === void 0 ? void 0 : _a.when) === "auto") {
1432
+ return {
1433
+ main: {
1434
+ "create-release": createReleaseJob(mainWorkflowJobIds)
1435
+ },
1436
+ manual: {
1437
+ "force-create-release": createReleaseJob()
1438
+ }
1439
+ };
1440
+ }
1441
+ return {
1442
+ main: {},
1443
+ manual: {
1444
+ "create-release": createReleaseJob()
1445
+ }
1446
+ };
1447
+ };
1448
+ exports.getGithubReleaseJobs = getGithubReleaseJobs;
1449
+
1450
+ /***/ }),
1451
+
1452
+ /***/ 9635:
1453
+ /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
1454
+
1455
+ "use strict";
1456
+
1457
+
1458
+ var __createBinding = this && this.__createBinding || (Object.create ? function (o, m, k, k2) {
1459
+ if (k2 === undefined) k2 = k;
1460
+ var desc = Object.getOwnPropertyDescriptor(m, k);
1461
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
1462
+ desc = {
1463
+ enumerable: true,
1464
+ get: function () {
1465
+ return m[k];
1466
+ }
1467
+ };
1468
+ }
1469
+ Object.defineProperty(o, k2, desc);
1470
+ } : function (o, m, k, k2) {
1471
+ if (k2 === undefined) k2 = k;
1472
+ o[k2] = m[k];
1473
+ });
1474
+ var __exportStar = this && this.__exportStar || function (m, exports) {
1475
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
1476
+ };
1477
+ Object.defineProperty(exports, "__esModule", ({
1478
+ value: true
1479
+ }));
1480
+ __exportStar(__nccwpck_require__(4038), exports);
1481
+ __exportStar(__nccwpck_require__(3093), exports);
1482
+
1483
+ /***/ }),
1484
+
1485
+ /***/ 5759:
1486
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
1487
+
1488
+ "use strict";
1489
+
1490
+
1491
+ Object.defineProperty(exports, "__esModule", ({
1492
+ value: true
1493
+ }));
1494
+ exports.getGithubScriptFunctionDefinitions = void 0;
1495
+ const globalScriptFunctions_1 = __nccwpck_require__(3891);
1496
+ /**
1497
+ * github variants of the global script functions where the gitlab
1498
+ * implementation uses gitlab-specific mechanics (e.g. collapsible log
1499
+ * sections use gitlab's `section_start` escape codes, github uses
1500
+ * `::group::` workflow commands). All other functions are plain bash
1501
+ * and shared as-is.
1502
+ */
1503
+ const GITHUB_FUNCTION_OVERRIDES = {
1504
+ collapseable_section_start: `local section_title="\${1}"
1505
+ local section_description="\${2:-$section_title}"
1506
+ echo "::group::\${section_description}"`,
1507
+ collapseable_section_end: `echo "::endgroup::"`
1508
+ };
1509
+ /**
1510
+ * the bash function definitions to prepend to every job script.
1511
+ * github has no pipeline-wide before_script like gitlab, so each job
1512
+ * carries its own definitions.
1513
+ */
1514
+ const getGithubScriptFunctionDefinitions = () => [...globalScriptFunctions_1.globalScriptFunctions.values()].map(fn => {
1515
+ const override = GITHUB_FUNCTION_OVERRIDES[fn.name];
1516
+ return override ? `function ${fn.name} () {\n${override.trim()}\n}` : fn.toBashFunction();
1517
+ });
1518
+ exports.getGithubScriptFunctionDefinitions = getGithubScriptFunctionDefinitions;
1519
+
1520
+ /***/ }),
1521
+
951
1522
  /***/ 2278:
952
1523
  /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
953
1524
 
@@ -958,6 +1529,7 @@ Object.defineProperty(exports, "__esModule", ({
958
1529
  value: true
959
1530
  }));
960
1531
  exports.GitlabBackend = void 0;
1532
+ const promises_1 = __nccwpck_require__(1943);
961
1533
  const rules_1 = __nccwpck_require__(4565);
962
1534
  const config_1 = __nccwpck_require__(6925);
963
1535
  const createAllJobs_1 = __nccwpck_require__(3671);
@@ -973,6 +1545,12 @@ class GitlabBackend {
973
1545
  this.type = "gitlab";
974
1546
  this.generatedFolder = GITLAB_GENERATED_FOLDER;
975
1547
  }
1548
+ async cleanup() {
1549
+ await (0, promises_1.rm)(this.generatedFolder, {
1550
+ force: true,
1551
+ recursive: true
1552
+ });
1553
+ }
976
1554
  async createFiles(config) {
977
1555
  const includes = await this.createIncludes(config);
978
1556
  const mainFile = {
@@ -1687,12 +2265,15 @@ var __exportStar = this && this.__exportStar || function (m, exports) {
1687
2265
  Object.defineProperty(exports, "__esModule", ({
1688
2266
  value: true
1689
2267
  }));
1690
- exports.getPipelineBackend = void 0;
2268
+ exports.getEnabledPipelineTypes = exports.getPipelineBackend = void 0;
2269
+ const github_1 = __nccwpck_require__(9635);
1691
2270
  const gitlab_1 = __nccwpck_require__(8475);
1692
2271
  __exportStar(__nccwpck_require__(2474), exports);
1693
2272
  __exportStar(__nccwpck_require__(8475), exports);
2273
+ __exportStar(__nccwpck_require__(9635), exports);
1694
2274
  const BACKENDS = {
1695
- gitlab: () => new gitlab_1.GitlabBackend()
2275
+ gitlab: () => new gitlab_1.GitlabBackend(),
2276
+ github: () => new github_1.GithubBackend()
1696
2277
  };
1697
2278
  const getPipelineBackend = type => {
1698
2279
  const createBackend = BACKENDS[type];
@@ -1702,6 +2283,25 @@ const getPipelineBackend = type => {
1702
2283
  return createBackend();
1703
2284
  };
1704
2285
  exports.getPipelineBackend = getPipelineBackend;
2286
+ /**
2287
+ * the pipeline types enabled for this config. Multiple types can be
2288
+ * enabled at once (parallel generation, e.g. during a CI migration).
2289
+ */
2290
+ const getEnabledPipelineTypes = config => {
2291
+ var _a;
2292
+ if (config.pipelines) {
2293
+ const enabled = Object.keys(BACKENDS).filter(type => {
2294
+ var _a;
2295
+ return (_a = config.pipelines) === null || _a === void 0 ? void 0 : _a[type];
2296
+ });
2297
+ if (enabled.length === 0) {
2298
+ throw new Error("`pipelines` is configured, but no pipeline type is enabled");
2299
+ }
2300
+ return enabled;
2301
+ }
2302
+ return [(_a = config.pipelineType) !== null && _a !== void 0 ? _a : "gitlab"];
2303
+ };
2304
+ exports.getEnabledPipelineTypes = getEnabledPipelineTypes;
1705
2305
 
1706
2306
  /***/ }),
1707
2307
 
@@ -2025,10 +2625,12 @@ Object.defineProperty(exports, "__esModule", ({
2025
2625
  value: true
2026
2626
  }));
2027
2627
  exports.getCiVariable = void 0;
2028
- const ciVariables_1 = __nccwpck_require__(8506);
2628
+ const ciVariables_1 = __nccwpck_require__(3093);
2629
+ const ciVariables_2 = __nccwpck_require__(8506);
2029
2630
  const BashExpression_1 = __nccwpck_require__(5354);
2030
2631
  const CI_VARIABLES_PER_PIPELINE_TYPE = {
2031
- gitlab: ciVariables_1.GITLAB_CI_VARIABLES
2632
+ gitlab: ciVariables_2.GITLAB_CI_VARIABLES,
2633
+ github: ciVariables_1.GITHUB_CI_VARIABLES
2032
2634
  };
2033
2635
  /**
2034
2636
  * resolves a platform-neutral CI variable to a bash expression for the
@@ -3647,7 +4249,7 @@ Object.defineProperty(exports, "__esModule", ({
3647
4249
  value: true
3648
4250
  }));
3649
4251
  exports.DOCKER_REGISTRY = exports.PIPELINE_IMAGE_TAG = void 0;
3650
- exports.PIPELINE_IMAGE_TAG = "next-e7541a00" || 0;
4252
+ exports.PIPELINE_IMAGE_TAG = "next-4e7c6848" || 0;
3651
4253
  exports.DOCKER_REGISTRY = "git.panter.ch:5001/catladder/catladder" || 0;
3652
4254
 
3653
4255
  /***/ }),
@@ -4214,7 +4816,9 @@ const bashExpressionPerPipelineType_1 = __nccwpck_require__(1945);
4214
4816
  const getEnvType_1 = __nccwpck_require__(8254);
4215
4817
  const REVIEW_SLUG = {
4216
4818
  default: "unknown-review-slug",
4217
- 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"; })`)
4819
+ 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"; })`),
4820
+ // CL_PR_NUMBER is injected by the github backend at the workflow level
4821
+ github: new BashExpression_1.BashExpression(`$([ -n "$CL_PR_NUMBER" ] && echo "pr$CL_PR_NUMBER" || echo "unknown")`)
4218
4822
  };
4219
4823
  const getReviewSlug = (envConfig, env, pipelineType) => {
4220
4824
  const envType = (0, getEnvType_1.getEnvType)(env, envConfig);
@@ -7390,14 +7994,22 @@ const promises_1 = __nccwpck_require__(1943);
7390
7994
  const path_1 = __nccwpck_require__(6928);
7391
7995
  const backends_1 = __nccwpck_require__(3243);
7392
7996
  const gitlab_1 = __nccwpck_require__(8475);
7997
+ /**
7998
+ * generates the pipeline files of all pipeline types enabled in the
7999
+ * config (see `pipelines`). Pass an explicit `pipelineType` to generate
8000
+ * only that one.
8001
+ */
7393
8002
  async function generatePipelineFiles(context, pipelineType) {
7394
- const backend = (0, backends_1.getPipelineBackend)(pipelineType);
8003
+ const pipelineTypes = pipelineType ? [pipelineType] : (0, backends_1.getEnabledPipelineTypes)(context.config);
8004
+ for (const type of pipelineTypes) {
8005
+ await generatePipelineFilesForBackend(context, (0, backends_1.getPipelineBackend)(type));
8006
+ }
8007
+ }
8008
+ exports.generatePipelineFiles = generatePipelineFiles;
8009
+ async function generatePipelineFilesForBackend(context, backend) {
7395
8010
  const files = await backend.createFiles(context.config);
7396
- // first clean up the folder
7397
- await (0, promises_1.rm)(backend.generatedFolder, {
7398
- force: true,
7399
- recursive: true
7400
- });
8011
+ // first clean up previously generated files
8012
+ await backend.cleanup();
7401
8013
  // write files
7402
8014
  await Promise.all(files.map(async ({
7403
8015
  path,
@@ -7409,7 +8021,6 @@ async function generatePipelineFiles(context, pipelineType) {
7409
8021
  await context.fileWriter.writeYamlfile(path, content);
7410
8022
  }));
7411
8023
  }
7412
- exports.generatePipelineFiles = generatePipelineFiles;
7413
8024
  /**
7414
8025
  *
7415
8026
  * for testing purposes