@catladder/cli 5.2.0 → 5.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/apps/cli/src/commands/project/commandPortForward.js +1 -1
  2. package/dist/apps/cli/src/commands/project/commandPortForward.js.map +1 -1
  3. package/dist/apps/cli/src/commands/project/secrets/scope.js +25 -2
  4. package/dist/apps/cli/src/commands/project/secrets/scope.js.map +1 -1
  5. package/dist/apps/cli/src/config/getProjectConfig.js +4 -1
  6. package/dist/apps/cli/src/config/getProjectConfig.js.map +1 -1
  7. package/dist/apps/cli/src/release/changesetCheckJob.js +17 -10
  8. package/dist/apps/cli/src/release/changesetCheckJob.js.map +1 -1
  9. package/dist/apps/cli/src/secrets/github.js +4 -2
  10. package/dist/apps/cli/src/secrets/github.js.map +1 -1
  11. package/dist/bundles/catci/index.js +1 -1
  12. package/dist/bundles/catenv/index.js +402 -111
  13. package/dist/bundles/cli/index.js +432 -116
  14. package/dist/bundles/skills/catladder-config/SKILL.md +34 -2
  15. package/dist/bundles/skills/catladder-deploys/SKILL.md +13 -1
  16. package/dist/bundles/skills/catladder-deploys/references/deploy-types.md +1 -1
  17. package/dist/bundles/skills/catladder-migrate-release-method/SKILL.md +4 -3
  18. package/dist/bundles/skills/catladder-pipelines/SKILL.md +10 -1
  19. package/dist/bundles/skills/catladder-releases/SKILL.md +12 -7
  20. package/dist/bundles/skills/catladder-secrets/SKILL.md +6 -0
  21. package/dist/packages/pipeline/src/backends/github/GithubBackend.js +23 -3
  22. package/dist/packages/pipeline/src/backends/github/GithubBackend.js.map +1 -1
  23. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js +2 -2
  24. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js.map +1 -1
  25. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js +18 -2
  26. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
  27. package/dist/packages/pipeline/src/backends/gitlab/createGitlabJobs.js +9 -4
  28. package/dist/packages/pipeline/src/backends/gitlab/createGitlabJobs.js.map +1 -1
  29. package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.d.ts +6 -1
  30. package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.js +8 -1
  31. package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.js.map +1 -1
  32. package/dist/packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.js +5 -3
  33. package/dist/packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.js.map +1 -1
  34. package/dist/packages/pipeline/src/config/configruedEnvs.d.ts +9 -2
  35. package/dist/packages/pipeline/src/config/configruedEnvs.js +54 -5
  36. package/dist/packages/pipeline/src/config/configruedEnvs.js.map +1 -1
  37. package/dist/packages/pipeline/src/context/createAllComponentsContext.d.ts +2 -2
  38. package/dist/packages/pipeline/src/context/createComponentContext.d.ts +2 -2
  39. package/dist/packages/pipeline/src/context/createWorkspaceContext.d.ts +2 -2
  40. package/dist/packages/pipeline/src/context/getEnvConfig.js +35 -19
  41. package/dist/packages/pipeline/src/context/getEnvConfig.js.map +1 -1
  42. package/dist/packages/pipeline/src/context/getEnvInherit.d.ts +20 -0
  43. package/dist/packages/pipeline/src/context/getEnvInherit.js +72 -0
  44. package/dist/packages/pipeline/src/context/getEnvInherit.js.map +1 -0
  45. package/dist/packages/pipeline/src/context/getEnvInstance.d.ts +4 -0
  46. package/dist/packages/pipeline/src/context/{getReviewSlug.js → getEnvInstance.js} +13 -9
  47. package/dist/packages/pipeline/src/context/getEnvInstance.js.map +1 -0
  48. package/dist/packages/pipeline/src/context/getEnvOn.d.ts +13 -0
  49. package/dist/packages/pipeline/src/context/getEnvOn.js +28 -0
  50. package/dist/packages/pipeline/src/context/getEnvOn.js.map +1 -0
  51. package/dist/packages/pipeline/src/context/getEnvType.d.ts +8 -2
  52. package/dist/packages/pipeline/src/context/getEnvType.js +27 -5
  53. package/dist/packages/pipeline/src/context/getEnvType.js.map +1 -1
  54. package/dist/packages/pipeline/src/context/getEnvironment.js +3 -0
  55. package/dist/packages/pipeline/src/context/getEnvironment.js.map +1 -1
  56. package/dist/packages/pipeline/src/context/getEnvironmentContext.js +18 -8
  57. package/dist/packages/pipeline/src/context/getEnvironmentContext.js.map +1 -1
  58. package/dist/packages/pipeline/src/context/getEnvironmentVariables.d.ts +1 -1
  59. package/dist/packages/pipeline/src/context/getEnvironmentVariables.js +4 -4
  60. package/dist/packages/pipeline/src/context/getEnvironmentVariables.js.map +1 -1
  61. package/dist/packages/pipeline/src/context/index.d.ts +1 -0
  62. package/dist/packages/pipeline/src/context/index.js +1 -0
  63. package/dist/packages/pipeline/src/context/index.js.map +1 -1
  64. package/dist/packages/pipeline/src/deploy/base/deploy.js +11 -1
  65. package/dist/packages/pipeline/src/deploy/base/deploy.js.map +1 -1
  66. package/dist/packages/pipeline/src/deploy/cloudRun/artifactsRegistry.js +5 -4
  67. package/dist/packages/pipeline/src/deploy/cloudRun/artifactsRegistry.js.map +1 -1
  68. package/dist/packages/pipeline/src/deploy/cloudRun/cleanup.js +8 -2
  69. package/dist/packages/pipeline/src/deploy/cloudRun/cleanup.js.map +1 -1
  70. package/dist/packages/pipeline/src/deploy/cloudRun/index.js +2 -2
  71. package/dist/packages/pipeline/src/deploy/cloudRun/index.js.map +1 -1
  72. package/dist/packages/pipeline/src/deploy/cloudRun/utils/getServiceName.js +2 -2
  73. package/dist/packages/pipeline/src/deploy/cloudRun/utils/getServiceName.js.map +1 -1
  74. package/dist/packages/pipeline/src/deploy/kubernetes/index.js +3 -3
  75. package/dist/packages/pipeline/src/deploy/kubernetes/index.js.map +1 -1
  76. package/dist/packages/pipeline/src/deploy/pages/deployJob.js +3 -2
  77. package/dist/packages/pipeline/src/deploy/pages/deployJob.js.map +1 -1
  78. package/dist/packages/pipeline/src/deploy/types/googleCloudRun.d.ts +9 -0
  79. package/dist/packages/pipeline/src/types/config.d.ts +126 -9
  80. package/dist/packages/pipeline/src/types/config.js +11 -10
  81. package/dist/packages/pipeline/src/types/config.js.map +1 -1
  82. package/dist/packages/pipeline/src/types/context.d.ts +22 -3
  83. package/dist/packages/pipeline/src/types/context.js.map +1 -1
  84. package/dist/packages/pipeline/src/types/environmentContext.d.ts +29 -0
  85. package/dist/skills/catladder-config/SKILL.md +34 -2
  86. package/dist/skills/catladder-deploys/SKILL.md +13 -1
  87. package/dist/skills/catladder-deploys/references/deploy-types.md +1 -1
  88. package/dist/skills/catladder-migrate-release-method/SKILL.md +4 -3
  89. package/dist/skills/catladder-pipelines/SKILL.md +10 -1
  90. package/dist/skills/catladder-releases/SKILL.md +12 -7
  91. package/dist/skills/catladder-secrets/SKILL.md +6 -0
  92. package/dist/tsconfig.tsbuildinfo +1 -1
  93. package/package.json +1 -1
  94. package/src/commands/project/commandPortForward.ts +1 -1
  95. package/src/commands/project/secrets/scope.ts +38 -2
  96. package/src/config/getProjectConfig.ts +9 -1
  97. package/src/release/__tests__/changesetCheckJob.test.ts +68 -0
  98. package/src/release/changesetCheckJob.ts +18 -10
  99. package/src/secrets/github.ts +8 -5
  100. package/dist/packages/pipeline/src/context/getReviewSlug.d.ts +0 -4
  101. package/dist/packages/pipeline/src/context/getReviewSlug.js.map +0 -1
@@ -756,7 +756,10 @@ const getEnvironment = async (env, componentName) => {
756
756
  };
757
757
  exports.getEnvironment = getEnvironment;
758
758
  const getGitlabVar = async (io, env, componentName, variableName) => {
759
- const rawVariableName = (0, pipeline_1.getSecretVarName)(env, componentName, variableName);
759
+ const config = await (0, exports.getProjectConfig)();
760
+ // an env sharing another env's secrets (inherit) reads that env's variables
761
+ const secretsEnv = (0, pipeline_1.getSecretsEnv)(config === null || config === void 0 ? void 0 : config.environments, env);
762
+ const rawVariableName = (0, pipeline_1.getSecretVarName)(secretsEnv, componentName, variableName);
760
763
  return await (0, gitlab_1.getVariableValueByRawName)(io, rawVariableName);
761
764
  };
762
765
  exports.getGitlabVar = getGitlabVar;
@@ -2641,6 +2644,7 @@ const promises_1 = __nccwpck_require__(91943);
2641
2644
  const path_1 = __nccwpck_require__(16928);
2642
2645
  const createAllJobs_1 = __nccwpck_require__(83477);
2643
2646
  const config_1 = __nccwpck_require__(75591);
2647
+ const configruedEnvs_1 = __nccwpck_require__(38866);
2644
2648
  const ciVariables_1 = __nccwpck_require__(17300);
2645
2649
  const registryImage_1 = __nccwpck_require__(24333);
2646
2650
  const index_1 = __nccwpck_require__(62853);
@@ -2693,6 +2697,12 @@ const TRIGGER_WORKFLOWS = {
2693
2697
  },
2694
2698
  },
2695
2699
  };
2700
+ const getTriggerWorkflow = (trigger) => (0, config_1.isBranchTrigger)(trigger)
2701
+ ? {
2702
+ name: `🛠️ catladder ${trigger.branch}`,
2703
+ on: { push: { branches: [trigger.branch] } },
2704
+ }
2705
+ : TRIGGER_WORKFLOWS[trigger];
2696
2706
  class GithubBackend {
2697
2707
  constructor() {
2698
2708
  this.type = "github";
@@ -2753,7 +2763,13 @@ class GithubBackend {
2753
2763
  stop: { jobs: {}, conditions: {}, options: [], envTypes: [] },
2754
2764
  rollback: { jobs: {}, conditions: {}, options: [], envTypes: [] },
2755
2765
  };
2756
- for (const trigger of config_1.ALL_PIPELINE_TRIGGERS) {
2766
+ // branch triggers (envs with `on: { branch: ... }`) each get their
2767
+ // own push-triggered workflow next to the built-in ones
2768
+ const allTriggers = [
2769
+ ...config_1.ALL_PIPELINE_TRIGGERS,
2770
+ ...(0, configruedEnvs_1.getConfiguredBranchTriggers)(config),
2771
+ ];
2772
+ for (const trigger of allTriggers) {
2757
2773
  const allJobs = await (0, createAllJobs_1.createAllJobs)({
2758
2774
  config,
2759
2775
  trigger,
@@ -2880,7 +2896,7 @@ class GithubBackend {
2880
2896
  if (Object.keys(jobs).length > 0) {
2881
2897
  const workflowJobs = { ...(0, ensureImageJobs_1.makeEnsureImageGithubJobs)(images), ...jobs };
2882
2898
  workflows[`${GENERATED_FILE_PREFIX}${workflowFileName(trigger)}`] = {
2883
- ...TRIGGER_WORKFLOWS[trigger],
2899
+ ...getTriggerWorkflow(trigger),
2884
2900
  ...workflowPermissions(images),
2885
2901
  env: workflowEnv,
2886
2902
  // the review workflow additionally gets the aggregate job —
@@ -2980,6 +2996,11 @@ const workflowPermissions = (_images) => ({
2980
2996
  permissions: { contents: "read", packages: "write" },
2981
2997
  });
2982
2998
  const workflowFileName = (trigger) => {
2999
+ if ((0, config_1.isBranchTrigger)(trigger)) {
3000
+ // branch names may contain characters that don't belong in a file
3001
+ // name (e.g. "release/next")
3002
+ return `branch-${trigger.branch.replace(/[^a-zA-Z0-9]+/g, "-")}.yml`;
3003
+ }
2983
3004
  switch (trigger) {
2984
3005
  case "mr":
2985
3006
  return "review.yml";
@@ -2998,7 +3019,9 @@ const isReviewStopJob = (context, job) => {
2998
3019
  var _a;
2999
3020
  return ((_a = job.environment) === null || _a === void 0 ? void 0 : _a.action) === "stop" &&
3000
3021
  context.type === "component" &&
3001
- context.environment.envType === "review";
3022
+ // a review app (one instance per pull request) is torn down when its
3023
+ // pull request closes; stable envs get dispatch-triggered stop jobs
3024
+ context.environment.instance.type === "review";
3002
3025
  };
3003
3026
  /**
3004
3027
  * stop/rollback jobs of non-review environments have no automatic
@@ -3329,7 +3352,7 @@ const collectSecretKinds = (allJobs) => {
3329
3352
  ...((_a = context.environment.jobOnlyVars.build.secretEnvVarKeys) !== null && _a !== void 0 ? _a : []),
3330
3353
  ...((_b = context.environment.jobOnlyVars.deploy.secretEnvVarKeys) !== null && _b !== void 0 ? _b : []),
3331
3354
  ];
3332
- entries.forEach(({ key, kind }) => kinds.set((0, getEnvironmentVariables_1.getSecretVarName)(context.env, context.name, key), kind !== null && kind !== void 0 ? kind : "secret"));
3355
+ entries.forEach(({ key, kind }) => kinds.set((0, getEnvironmentVariables_1.getSecretVarName)(context.environment.secretsEnv, context.name, key), kind !== null && kind !== void 0 ? kind : "secret"));
3333
3356
  });
3334
3357
  return kinds;
3335
3358
  };
@@ -3342,7 +3365,7 @@ const getSecretsEnv = (context, kinds) => {
3342
3365
  ...((_b = context.environment.jobOnlyVars.deploy.secretEnvVarKeys) !== null && _b !== void 0 ? _b : []),
3343
3366
  ];
3344
3367
  return Object.fromEntries(keys.map(({ key }) => {
3345
- const name = (0, getEnvironmentVariables_1.getSecretVarName)(context.env, context.name, key);
3368
+ const name = (0, getEnvironmentVariables_1.getSecretVarName)(context.environment.secretsEnv, context.name, key);
3346
3369
  return [name, vaultValueExpression(name, kinds)];
3347
3370
  }));
3348
3371
  };
@@ -4141,6 +4164,7 @@ exports.GitlabBackend = void 0;
4141
4164
  const promises_1 = __nccwpck_require__(91943);
4142
4165
  const rules_1 = __nccwpck_require__(78503);
4143
4166
  const config_1 = __nccwpck_require__(75591);
4167
+ const configruedEnvs_1 = __nccwpck_require__(38866);
4144
4168
  const autoStop_1 = __nccwpck_require__(72792);
4145
4169
  const createAllJobs_1 = __nccwpck_require__(83477);
4146
4170
  const jobImagesPlan_1 = __nccwpck_require__(59623);
@@ -4248,8 +4272,15 @@ class GitlabBackend {
4248
4272
  // release jobs themselves are created afterwards — they need the
4249
4273
  // main-branch job list for the queued-release executor's needs.
4250
4274
  images.resolveRef({ catladderImage: (0, release_1.getReleaseMethod)(config).image });
4251
- // for all triggers create jobs and add base rules
4252
- const jobsPerTrigger = await Promise.all(config_1.ALL_PIPELINE_TRIGGERS.map(async (trigger) => ({
4275
+ // for all triggers create jobs and add base rules. Branch triggers
4276
+ // (envs with `on: { branch: ... }`) each get their own pipeline next
4277
+ // to the built-in ones.
4278
+ const branchTriggers = (0, configruedEnvs_1.getConfiguredBranchTriggers)(config);
4279
+ const allTriggers = [
4280
+ ...config_1.ALL_PIPELINE_TRIGGERS,
4281
+ ...branchTriggers,
4282
+ ];
4283
+ const jobsPerTrigger = await Promise.all(allTriggers.map(async (trigger) => ({
4253
4284
  trigger,
4254
4285
  jobs: await (0, createGitlabJobs_1.createGitlabJobs)(await (0, createAllJobs_1.createAllJobs)({ config, trigger, pipelineType: this.type }), images, getGitlabRulesForTrigger(trigger)),
4255
4286
  })));
@@ -4327,6 +4358,7 @@ class GitlabBackend {
4327
4358
  // per-pipeline-type variables (pipelines.gitlab.runnerVariables)
4328
4359
  ...(0, index_1.getPipelineOptions)(config, this.type).runnerVariables,
4329
4360
  },
4361
+ branchPipelines: branchTriggers.map(({ branch }) => branch),
4330
4362
  autoStop: (0, autoStop_1.getAutoStopConfig)(config),
4331
4363
  });
4332
4364
  }
@@ -4344,6 +4376,13 @@ function getGitlabRulesForTrigger(trigger) {
4344
4376
  // mainBranch: on push to main branch except it's a release commit
4345
4377
  // mr: on merge request
4346
4378
  // taggedRelease: on tag
4379
+ // { branch }: on push to that specific branch
4380
+ if ((0, config_1.isBranchTrigger)(trigger)) {
4381
+ return [
4382
+ rules_1.RULE_NEVER_ON_AGENT_TRIGGER,
4383
+ { if: `$CI_COMMIT_BRANCH == "${trigger.branch}"` },
4384
+ ];
4385
+ }
4347
4386
  switch (trigger) {
4348
4387
  case "mainBranch":
4349
4388
  return [
@@ -4596,16 +4635,21 @@ const addGitlabEnvironment = (context, catladderJobEnvironment, job, allJobs) =>
4596
4635
  return job;
4597
4636
  }
4598
4637
  const { env, name, environment } = context;
4599
- const { envVars, envType } = environment;
4638
+ const { envVars, instance } = environment;
4600
4639
  const { onStop, autoStopIn, action } = catladderJobEnvironment;
4601
4640
  // those can be dynamic, so we therefore have to do this: https://docs.gitlab.com/ee/ci/environments/#set-a-dynamic-environment-url
4602
- const dotEnvFile = "gitlab_environment.env";
4641
+ // absolute: deploy scripts may `cd` into the component dir (pages,
4642
+ // custom), while gitlab resolves `reports.dotenv` relative to the
4643
+ // project dir — a relative file would land in <dir>/ and never be
4644
+ // picked up ("no matching files"), leaving the environment without url
4645
+ const dotEnvFileName = "gitlab_environment.env";
4646
+ const dotEnvFile = `"$CI_PROJECT_DIR/${dotEnvFileName}"`;
4603
4647
  const createsJobEnv = !catladderJobEnvironment.action ||
4604
4648
  catladderJobEnvironment.action === "start";
4605
4649
  const artifacts = (0, lodash_es_1.merge)((_a = job.artifacts) !== null && _a !== void 0 ? _a : {}, createsJobEnv
4606
4650
  ? {
4607
4651
  reports: {
4608
- dotenv: dotEnvFile,
4652
+ dotenv: dotEnvFileName,
4609
4653
  },
4610
4654
  }
4611
4655
  : {});
@@ -4613,7 +4657,7 @@ const addGitlabEnvironment = (context, catladderJobEnvironment, job, allJobs) =>
4613
4657
  `echo "${exports.GITLAB_ENVIRONMENT_URL_VARIABLE}=${(0, bash_1.getBashVariable)("ROOT_URL")}" >> ${dotEnvFile}`,
4614
4658
  ];
4615
4659
  // this is NOT a bashVariable since it NEEDS to be used as a string in gitlab
4616
- const gitlabEnvironmentName = envType === "review"
4660
+ const gitlabEnvironmentName = instance.type === "review"
4617
4661
  ? `${env}/$CI_COMMIT_REF_NAME/${name}` // FIXME: should be replaced with mr name as well
4618
4662
  : `${env}/${name}`;
4619
4663
  return {
@@ -4781,7 +4825,7 @@ const rules_1 = __nccwpck_require__(78503);
4781
4825
  * build-free image (a catladder job image would drag in a build job).
4782
4826
  */
4783
4827
  const DEFAULT_PIPELINE_IMAGE = "node:22";
4784
- const createGitlabPipelineWithDefaults = ({ image, variables, before_script, autoStop, ...config }) => {
4828
+ const createGitlabPipelineWithDefaults = ({ image, variables, before_script, branchPipelines = [], autoStop, ...config }) => {
4785
4829
  const pinLabel = autoStop && autoStop.pinLabel;
4786
4830
  return {
4787
4831
  image: image !== null && image !== void 0 ? image : DEFAULT_PIPELINE_IMAGE,
@@ -4862,6 +4906,13 @@ const createGitlabPipelineWithDefaults = ({ image, variables, before_script, aut
4862
4906
  PIPELINE_NAME: "Main - $CI_COMMIT_TITLE",
4863
4907
  },
4864
4908
  },
4909
+ ...branchPipelines.map((branch) => ({
4910
+ if: `$CI_COMMIT_BRANCH == "${branch}"`,
4911
+ variables: {
4912
+ PIPELINE_ICON: "🐱🔨",
4913
+ PIPELINE_NAME: `${branch} - $CI_COMMIT_TITLE`,
4914
+ },
4915
+ })),
4865
4916
  {
4866
4917
  when: "always", // fallback
4867
4918
  variables: {
@@ -4987,8 +5038,10 @@ mainBranchJobNames) => {
4987
5038
  },
4988
5039
  };
4989
5040
  // informational MR check of the release method (e.g. the changeset
4990
- // check): warns via allow_failure, the report lands in the MR
4991
- // widget as an exposed artifact
5041
+ // check): the report lands in the MR widget as an exposed artifact.
5042
+ // The check script exits 0 even when it warns — gitlab only resolves
5043
+ // exposed artifacts of successful jobs, a failed (allow_failure) job
5044
+ // leaves the widget spinning on "Loading artifacts" forever
4992
5045
  const checkJob = method.checkScript
4993
5046
  ? {
4994
5047
  ["🦋 changeset check"]: {
@@ -5003,7 +5056,7 @@ mainBranchJobNames) => {
5003
5056
  artifacts: {
5004
5057
  paths: ["changeset-report.md"],
5005
5058
  expose_as: "changeset report",
5006
- // the report must survive the warning exit
5059
+ // keep the report should the check itself crash
5007
5060
  when: "always",
5008
5061
  },
5009
5062
  rules: [
@@ -7288,8 +7341,10 @@ exports.createCatenvContext = createCatenvContext;
7288
7341
  "use strict";
7289
7342
 
7290
7343
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7291
- exports.getAllEnvsByTrigger = exports.getAllEnvsInAllComponents = exports.getAllEnvs = void 0;
7344
+ exports.getConfiguredBranchTriggers = exports.getAllEnvsByTrigger = exports.getAllEnvsInAllComponents = exports.getAllEnvs = void 0;
7292
7345
  const types_1 = __nccwpck_require__(63557);
7346
+ const getEnvOn_1 = __nccwpck_require__(60601);
7347
+ const getEnvType_1 = __nccwpck_require__(46080);
7293
7348
  const getConfiguredAndDefaultEnvs = (config, componentName, envTypes) => {
7294
7349
  var _a, _b;
7295
7350
  const configuredEnvs = (_a = config.components[componentName].env) !== null && _a !== void 0 ? _a : {};
@@ -7297,13 +7352,33 @@ const getConfiguredAndDefaultEnvs = (config, componentName, envTypes) => {
7297
7352
  // these can be disabled with settimg them to `false`
7298
7353
  // this is the list of all not disabled envs. These are always returned
7299
7354
  const enabledDefaultEnvs = envTypes.filter((e) => configuredEnvs[e] !== false);
7300
- const configuredCustomEnvs = Object.entries((_b = config.components[componentName].env) !== null && _b !== void 0 ? _b : {})
7355
+ // envs declared project-wide (top-level `environments`): every
7356
+ // component deploys to them unless it opts out with `env.<name>: false`
7357
+ const declaredEnvs = Object.keys((_b = config.environments) !== null && _b !== void 0 ? _b : {})
7358
+ .filter((envName) => !(0, types_1.isKnowEnvType)(envName)) // default envs are already handled above
7359
+ .map((envName) => {
7360
+ const envType = (0, getEnvType_1.getDeclaredEnvType)(config.environments, envName);
7361
+ if (!envType) {
7362
+ throw new Error(`environment "${envName}" needs a type (dev, review, stage, prod) or an inherit`);
7363
+ }
7364
+ return [envName, envType];
7365
+ })
7366
+ .filter(([envName, envType]) => envTypes.includes(envType) && configuredEnvs[envName] !== false)
7367
+ .map(([envName]) => envName);
7368
+ // legacy: custom envs declared per component via their `type`
7369
+ const configuredCustomEnvs = Object.entries(configuredEnvs)
7301
7370
  .filter(([, config]) => config &&
7302
7371
  "type" in config &&
7303
7372
  config.type &&
7304
7373
  envTypes.includes(config.type))
7305
7374
  .map(([envName]) => envName);
7306
- return [...new Set([...enabledDefaultEnvs, ...configuredCustomEnvs])];
7375
+ return [
7376
+ ...new Set([
7377
+ ...enabledDefaultEnvs,
7378
+ ...declaredEnvs,
7379
+ ...configuredCustomEnvs,
7380
+ ]),
7381
+ ];
7307
7382
  };
7308
7383
  const getAllEnvs = (config, componentName) => {
7309
7384
  return getConfiguredAndDefaultEnvs(config, componentName, types_1.DEFAULT_ENV_TYPES);
@@ -7315,11 +7390,38 @@ const getAllEnvsInAllComponents = (config) => {
7315
7390
  ];
7316
7391
  };
7317
7392
  exports.getAllEnvsInAllComponents = getAllEnvsInAllComponents;
7393
+ /**
7394
+ * the resolved `on` of one env of a component (the project-wide `on`
7395
+ * of the env, falling back to the env type's default trigger)
7396
+ */
7397
+ const getEnvOnForComponentEnv = (config, componentName, env) => {
7398
+ var _a;
7399
+ const entry = (_a = config.components[componentName].env) === null || _a === void 0 ? void 0 : _a[env];
7400
+ return (0, getEnvOn_1.getEnvOn)(env, entry && entry !== false ? entry : {}, config.environments);
7401
+ };
7318
7402
  const getAllEnvsByTrigger = (config, componentName, trigger) => {
7319
- const envTypesByTrigger = (0, types_1.getEnvTypesByTrigger)(trigger);
7320
- return getConfiguredAndDefaultEnvs(config, componentName, envTypesByTrigger);
7403
+ return (0, exports.getAllEnvs)(config, componentName).filter((env) => (0, types_1.envTriggerEquals)(getEnvOnForComponentEnv(config, componentName, env), trigger));
7321
7404
  };
7322
7405
  exports.getAllEnvsByTrigger = getAllEnvsByTrigger;
7406
+ /**
7407
+ * all branch triggers declared by any env of any component (via
7408
+ * `on: { branch: "..." }`), deduplicated and sorted for deterministic
7409
+ * pipeline generation. Each gets its own pipeline next to the built-in
7410
+ * triggers.
7411
+ */
7412
+ const getConfiguredBranchTriggers = (config) => {
7413
+ const branches = new Set();
7414
+ for (const componentName of Object.keys(config.components)) {
7415
+ for (const env of (0, exports.getAllEnvs)(config, componentName)) {
7416
+ const on = getEnvOnForComponentEnv(config, componentName, env);
7417
+ if (on && (0, types_1.isBranchTrigger)(on)) {
7418
+ branches.add(on.branch);
7419
+ }
7420
+ }
7421
+ }
7422
+ return [...branches].sort().map((branch) => ({ branch }));
7423
+ };
7424
+ exports.getConfiguredBranchTriggers = getConfiguredBranchTriggers;
7323
7425
  //# sourceMappingURL=configruedEnvs.js.map
7324
7426
 
7325
7427
  /***/ }),
@@ -7650,53 +7752,237 @@ exports.getBuildInfoVariables = getBuildInfoVariables;
7650
7752
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7651
7753
  exports.getEnvConfig = void 0;
7652
7754
  const lodash_es_1 = __nccwpck_require__(50210);
7755
+ const getEnvInherit_1 = __nccwpck_require__(52181);
7653
7756
  const getEnvConfig = (config, componentName, env) => {
7654
- var _a, _b;
7757
+ var _a;
7655
7758
  const defaultConfig = config.components[componentName];
7656
7759
  if (!defaultConfig) {
7657
7760
  throw new Error("unknown component " + componentName);
7658
7761
  }
7659
- const envCustomizations = (_b = (_a = defaultConfig.env) === null || _a === void 0 ? void 0 : _a[env]) !== null && _b !== void 0 ? _b : {};
7660
- if (envCustomizations === false) {
7661
- // env is disabled, still return the default config
7662
- return defaultConfig;
7663
- }
7664
- /**
7665
- * env config is merged with default. Arrays are not merged.
7666
- * you can customize this by providing a function that takes the default value as argument
7667
- */
7668
- return (0, lodash_es_1.mergeWith)(
7762
+ // env config is layered onto the component config: the per-component
7763
+ // overrides of inherited envs first (oldest ancestor first, see
7764
+ // `environments.<name>.inherit`), the env's own overrides last
7765
+ const chain = [...(0, getEnvInherit_1.getInheritedConfigChain)(config.environments, env), env];
7669
7766
  // mergeWith unfortunatly mutates the first object, so we need to clone it.
7670
7767
  // Passing empty object also doesn't work for us, because that will mess with the customizer function (second argument isn't nessecary the customized value)
7671
- (0, lodash_es_1.cloneDeep)(defaultConfig), envCustomizations, (defaultValue, customValue, key, obj, source) => {
7672
- // check if custom value is a function (and default is not),
7673
- // we currently don't have config options, that are functions, but we might in the future (customJobs is an exception)
7674
- if (typeof customValue === "function" &&
7675
- typeof defaultValue !== "function") {
7676
- return customValue(defaultValue);
7768
+ const result = (0, lodash_es_1.cloneDeep)(defaultConfig);
7769
+ for (const chainEnv of chain) {
7770
+ const envCustomizations = (_a = defaultConfig.env) === null || _a === void 0 ? void 0 : _a[chainEnv];
7771
+ if (!envCustomizations || envCustomizations === false) {
7772
+ if (chainEnv === env && envCustomizations === false) {
7773
+ // env is disabled, still return the default config
7774
+ return defaultConfig;
7775
+ }
7776
+ continue;
7677
7777
  }
7678
- return undefined;
7679
- });
7778
+ /**
7779
+ * env config is merged with default. Arrays are not merged.
7780
+ * you can customize this by providing a function that takes the default value as argument
7781
+ */
7782
+ (0, lodash_es_1.mergeWith)(result,
7783
+ // `host` must stay unique per env and `type` is the inherited
7784
+ // env's identity — neither is inherited
7785
+ chainEnv === env
7786
+ ? envCustomizations
7787
+ : (0, lodash_es_1.omit)(envCustomizations, ["host", "type"]), (defaultValue, customValue, key, obj, source) => {
7788
+ // check if custom value is a function (and default is not),
7789
+ // we currently don't have config options, that are functions, but we might in the future (customJobs is an exception)
7790
+ if (typeof customValue === "function" &&
7791
+ typeof defaultValue !== "function") {
7792
+ return customValue(defaultValue);
7793
+ }
7794
+ return undefined;
7795
+ });
7796
+ }
7797
+ return result;
7680
7798
  };
7681
7799
  exports.getEnvConfig = getEnvConfig;
7682
7800
  //# sourceMappingURL=getEnvConfig.js.map
7683
7801
 
7684
7802
  /***/ }),
7685
7803
 
7804
+ /***/ 52181:
7805
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7806
+
7807
+ "use strict";
7808
+
7809
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
7810
+ exports.getSecretsEnv = exports.getInheritedConfigChain = exports.normalizeEnvInherit = void 0;
7811
+ const config_1 = __nccwpck_require__(75591);
7812
+ const normalizeEnvInherit = (inherit) => {
7813
+ if (!inherit)
7814
+ return {};
7815
+ if (typeof inherit === "string") {
7816
+ return { config: inherit, secrets: inherit };
7817
+ }
7818
+ return {
7819
+ config: inherit.config,
7820
+ secrets: inherit.secrets === false ? undefined : inherit.secrets,
7821
+ };
7822
+ };
7823
+ exports.normalizeEnvInherit = normalizeEnvInherit;
7824
+ const assertValidInheritTarget = (environments, env, target) => {
7825
+ if (target === "local") {
7826
+ throw new Error(`environment "${env}" cannot inherit from "local" — local is not a deployment environment`);
7827
+ }
7828
+ if (!(0, config_1.isKnowEnvType)(target) && !(environments === null || environments === void 0 ? void 0 : environments[target])) {
7829
+ throw new Error(`environment "${env}" inherits from unknown environment "${target}"`);
7830
+ }
7831
+ };
7832
+ /**
7833
+ * the chain of envs whose per-component config overrides feed into
7834
+ * `env`, oldest ancestor first (env itself not included). Cycles and
7835
+ * unknown/`local` targets are an error.
7836
+ */
7837
+ const getInheritedConfigChain = (environments, env) => {
7838
+ var _a;
7839
+ const chain = [];
7840
+ const seen = new Set([env]);
7841
+ let current = env;
7842
+ for (;;) {
7843
+ const target = (0, exports.normalizeEnvInherit)((_a = environments === null || environments === void 0 ? void 0 : environments[current]) === null || _a === void 0 ? void 0 : _a.inherit).config;
7844
+ if (!target)
7845
+ break;
7846
+ assertValidInheritTarget(environments, current, target);
7847
+ if (seen.has(target)) {
7848
+ throw new Error(`environment "${env}" has a cyclic config inheritance via "${target}"`);
7849
+ }
7850
+ seen.add(target);
7851
+ chain.unshift(target);
7852
+ current = target;
7853
+ }
7854
+ return chain;
7855
+ };
7856
+ exports.getInheritedConfigChain = getInheritedConfigChain;
7857
+ /**
7858
+ * the env whose secret values `env` uses (follows `inherit` secret
7859
+ * sharing transitively; the env itself when it has its own secrets).
7860
+ * All secret variable names must be built with this env.
7861
+ */
7862
+ const getSecretsEnv = (environments, env) => {
7863
+ var _a;
7864
+ const seen = new Set([env]);
7865
+ let current = env;
7866
+ for (;;) {
7867
+ const target = (0, exports.normalizeEnvInherit)((_a = environments === null || environments === void 0 ? void 0 : environments[current]) === null || _a === void 0 ? void 0 : _a.inherit).secrets;
7868
+ if (!target)
7869
+ return current;
7870
+ assertValidInheritTarget(environments, current, target);
7871
+ if (seen.has(target)) {
7872
+ throw new Error(`environment "${env}" has a cyclic secrets inheritance via "${target}"`);
7873
+ }
7874
+ seen.add(target);
7875
+ current = target;
7876
+ }
7877
+ };
7878
+ exports.getSecretsEnv = getSecretsEnv;
7879
+ //# sourceMappingURL=getEnvInherit.js.map
7880
+
7881
+ /***/ }),
7882
+
7883
+ /***/ 13055:
7884
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7885
+
7886
+ "use strict";
7887
+
7888
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
7889
+ exports.getEnvInstance = void 0;
7890
+ const bash_1 = __nccwpck_require__(94143);
7891
+ const bashExpressionPerPipelineType_1 = __nccwpck_require__(6495);
7892
+ const getEnvOn_1 = __nccwpck_require__(60601);
7893
+ const REVIEW_SLUG = {
7894
+ default: "unknown-review-slug",
7895
+ gitlab: new bash_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"; })`),
7896
+ // CL_PR_NUMBER is injected by the github backend at the workflow level
7897
+ github: new bash_1.BashExpression(`$([ -n "$CL_PR_NUMBER" ] && echo "pr$CL_PR_NUMBER" || echo "unknown")`),
7898
+ };
7899
+ const getEnvInstance = (envConfig, env, pipelineType, environments) => {
7900
+ // an env deploying per merge request is a review app — one dynamic
7901
+ // instance per MR, identified by the review slug
7902
+ if ((0, getEnvOn_1.getEnvOn)(env, envConfig, environments) === "mr") {
7903
+ return {
7904
+ type: "review",
7905
+ reviewSlug: (0, bashExpressionPerPipelineType_1.getBashExpressionPerPipelineType)(REVIEW_SLUG, pipelineType),
7906
+ };
7907
+ }
7908
+ return { type: "stable" };
7909
+ };
7910
+ exports.getEnvInstance = getEnvInstance;
7911
+ //# sourceMappingURL=getEnvInstance.js.map
7912
+
7913
+ /***/ }),
7914
+
7915
+ /***/ 60601:
7916
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7917
+
7918
+ "use strict";
7919
+
7920
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
7921
+ exports.getEnvOn = void 0;
7922
+ const types_1 = __nccwpck_require__(63557);
7923
+ const getEnvType_1 = __nccwpck_require__(46080);
7924
+ const getDefaultOnForType = (envType) => {
7925
+ var _a;
7926
+ const triggers = types_1.ENV_TYPES[envType].triggers;
7927
+ return (_a = triggers[0]) !== null && _a !== void 0 ? _a : false;
7928
+ };
7929
+ /**
7930
+ * resolves when an env deploys: the project-wide `on` config of the env
7931
+ * (top-level `environments`), falling back to the default of its env
7932
+ * type (dev → mainBranch, review → mr, stage/prod → taggedRelease,
7933
+ * local → false).
7934
+ *
7935
+ * `on` is deliberately not configurable per component — an environment
7936
+ * deploys at one point in time for the whole project.
7937
+ */
7938
+ const getEnvOn = (env, envConfig, environments) => {
7939
+ var _a;
7940
+ const on = (_a = environments === null || environments === void 0 ? void 0 : environments[env]) === null || _a === void 0 ? void 0 : _a.on;
7941
+ if (on !== undefined)
7942
+ return on;
7943
+ return getDefaultOnForType((0, getEnvType_1.getEnvType)(env, envConfig, environments));
7944
+ };
7945
+ exports.getEnvOn = getEnvOn;
7946
+ //# sourceMappingURL=getEnvOn.js.map
7947
+
7948
+ /***/ }),
7949
+
7686
7950
  /***/ 46080:
7687
7951
  /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7688
7952
 
7689
7953
  "use strict";
7690
7954
 
7691
7955
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7692
- exports.getEnvType = void 0;
7956
+ exports.getEnvType = exports.getDeclaredEnvType = void 0;
7693
7957
  const types_1 = __nccwpck_require__(63557);
7694
- const getEnvType = (env, envConfig) => {
7695
- if (envConfig.type)
7696
- return envConfig.type;
7697
- if ((0, types_1.isKnowEnvType)(env)) {
7958
+ const getEnvInherit_1 = __nccwpck_require__(52181);
7959
+ /**
7960
+ * the type of a project-wide declared env: its explicit `type`, its
7961
+ * name (when it is itself an env type), or — for envs that inherit —
7962
+ * the type of the env they inherit their config from
7963
+ */
7964
+ const getDeclaredEnvType = (environments, env, seen = new Set()) => {
7965
+ const declared = environments === null || environments === void 0 ? void 0 : environments[env];
7966
+ if (declared === null || declared === void 0 ? void 0 : declared.type)
7967
+ return declared.type;
7968
+ if ((0, types_1.isKnowEnvType)(env))
7698
7969
  return env;
7970
+ const inheritTarget = (0, getEnvInherit_1.normalizeEnvInherit)(declared === null || declared === void 0 ? void 0 : declared.inherit).config;
7971
+ if (inheritTarget && !seen.has(inheritTarget)) {
7972
+ seen.add(inheritTarget);
7973
+ return (0, exports.getDeclaredEnvType)(environments, inheritTarget, seen);
7699
7974
  }
7975
+ return undefined;
7976
+ };
7977
+ exports.getDeclaredEnvType = getDeclaredEnvType;
7978
+ const getEnvType = (env, envConfig, environments) => {
7979
+ // legacy: per-component custom envs declare their type themselves
7980
+ if (envConfig.type)
7981
+ return envConfig.type;
7982
+ // project-wide declaration (top-level `environments`)
7983
+ const declaredType = (0, exports.getDeclaredEnvType)(environments, env);
7984
+ if (declaredType)
7985
+ return declaredType;
7700
7986
  throw new Error("unknown env type: " + env);
7701
7987
  };
7702
7988
  exports.getEnvType = getEnvType;
@@ -7722,8 +8008,11 @@ const getEnvironment = async (ctx) => {
7722
8008
  envType,
7723
8009
  fullName: envContext.fullName,
7724
8010
  slugPrefix: envContext.environmentSlugPrefix,
8011
+ instance: envContext.instance,
7725
8012
  reviewSlug: envContext.reviewSlug,
7726
8013
  slug: envContext.environmentSlug,
8014
+ autoStop: envContext.autoStop,
8015
+ secretsEnv: envContext.secretsEnv,
7727
8016
  ...variables,
7728
8017
  };
7729
8018
  };
@@ -7741,19 +8030,26 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
7741
8030
  exports.getEnvironmentContext = void 0;
7742
8031
  const bash_1 = __nccwpck_require__(94143);
7743
8032
  const getEnvConfig_1 = __nccwpck_require__(69578);
8033
+ const getEnvInstance_1 = __nccwpck_require__(13055);
8034
+ const getEnvInherit_1 = __nccwpck_require__(52181);
7744
8035
  const getEnvType_1 = __nccwpck_require__(46080);
7745
- const getReviewSlug_1 = __nccwpck_require__(77360);
7746
- const getEnvironmentSlugPrefix = (env, reviewSlug) => {
7747
- if (reviewSlug) {
7748
- return (0, bash_1.joinBashExpressions)([env, reviewSlug], "-");
8036
+ const getEnvironmentSlugPrefix = (env, instance) => {
8037
+ if (instance.type === "review") {
8038
+ return (0, bash_1.joinBashExpressions)([env, instance.reviewSlug], "-");
7749
8039
  }
7750
8040
  return env;
7751
8041
  };
7752
8042
  const getEnvironmentContext = ({ env, componentName, config, pipelineType, }) => {
8043
+ var _a, _b;
7753
8044
  const envConfigRaw = (0, getEnvConfig_1.getEnvConfig)(config, componentName, env);
7754
- const envType = (0, getEnvType_1.getEnvType)(env, envConfigRaw);
7755
- const reviewSlug = (0, getReviewSlug_1.getReviewSlug)(envConfigRaw, env, pipelineType);
7756
- const environmentSlugPrefix = getEnvironmentSlugPrefix(env, reviewSlug);
8045
+ const envType = (0, getEnvType_1.getEnvType)(env, envConfigRaw, config.environments);
8046
+ const instance = (0, getEnvInstance_1.getEnvInstance)(envConfigRaw, env, pipelineType, config.environments);
8047
+ // component-level autoStop overrides the project-wide environment
8048
+ // config; undefined means the env type's default applies
8049
+ const autoStop = envConfigRaw.autoStop !== undefined
8050
+ ? envConfigRaw.autoStop
8051
+ : (_b = (_a = config.environments) === null || _a === void 0 ? void 0 : _a[env]) === null || _b === void 0 ? void 0 : _b.autoStop;
8052
+ const environmentSlugPrefix = getEnvironmentSlugPrefix(env, instance);
7757
8053
  const environmentSlug = environmentSlugPrefix.concat(`-${componentName}`);
7758
8054
  const fullName = (0, bash_1.joinBashExpressions)([config.customerName, config.appName, environmentSlug], "-");
7759
8055
  return {
@@ -7762,10 +8058,13 @@ const getEnvironmentContext = ({ env, componentName, config, pipelineType, }) =>
7762
8058
  buildConfigRaw: envConfigRaw.build,
7763
8059
  environmentSlugPrefix,
7764
8060
  environmentSlug,
7765
- reviewSlug,
8061
+ instance,
8062
+ reviewSlug: instance.type === "review" ? instance.reviewSlug : null,
7766
8063
  pipelineType,
7767
8064
  fullName,
7768
8065
  envType,
8066
+ autoStop,
8067
+ secretsEnv: (0, getEnvInherit_1.getSecretsEnv)(config.environments, env),
7769
8068
  componentName,
7770
8069
  env,
7771
8070
  fullConfig: config,
@@ -7850,7 +8149,7 @@ const getEnvironmentVariables = async (ctx, options = {}) => {
7850
8149
  ...(0, envVars_1.normalizeSecretVarsConfig)((_f = envConfigRaw.vars) === null || _f === void 0 ? void 0 : _f.secret),
7851
8150
  ...additionalSecretKeys,
7852
8151
  ];
7853
- const secretEnvVars = (0, envVars_1.makeSecretEnvVarMapping)(env, componentName, secretEnvVarKeys);
8152
+ const secretEnvVars = (0, envVars_1.makeSecretEnvVarMapping)(environmentContext.secretsEnv, componentName, secretEnvVarKeys);
7854
8153
  const publicEnvVarsRawSanitized = (0, envVars_1.stringifyValues)(publicEnvVarsRaw);
7855
8154
  const publicEnvVarsUnresolved = Object.fromEntries(Object.entries(publicEnvVarsRawSanitized).map(([key, value]) => [
7856
8155
  key,
@@ -7884,11 +8183,11 @@ const getEnvironmentVariables = async (ctx, options = {}) => {
7884
8183
  envVars,
7885
8184
  secretEnvVarKeys,
7886
8185
  jobOnlyVars: {
7887
- build: await (0, transformJobOnlyVars_1.transformJobOnlyVars)(env, componentName, (buildConfigRaw &&
8186
+ build: await (0, transformJobOnlyVars_1.transformJobOnlyVars)(environmentContext.secretsEnv, componentName, (buildConfigRaw &&
7888
8187
  (0, types_1.isStandaloneBuildConfig)(buildConfigRaw) &&
7889
8188
  buildConfigRaw.jobVars) ||
7890
8189
  null),
7891
- deploy: await (0, transformJobOnlyVars_1.transformJobOnlyVars)(env, componentName, (deployConfigRaw && deployConfigRaw.jobVars) || null),
8190
+ deploy: await (0, transformJobOnlyVars_1.transformJobOnlyVars)(environmentContext.secretsEnv, componentName, (deployConfigRaw && deployConfigRaw.jobVars) || null),
7892
8191
  },
7893
8192
  };
7894
8193
  };
@@ -7900,7 +8199,7 @@ const addIndexVar = (vars) => ({
7900
8199
  ...vars,
7901
8200
  _ALL_ENV_VAR_KEYS: JSON.stringify(Object.keys(vars)),
7902
8201
  });
7903
- const getSecretVarNameForContext = (context, key) => (0, exports.getSecretVarName)(context.env, context.name, key);
8202
+ const getSecretVarNameForContext = (context, key) => (0, exports.getSecretVarName)(context.environment.secretsEnv, context.name, key);
7904
8203
  exports.getSecretVarNameForContext = getSecretVarNameForContext;
7905
8204
  //# sourceMappingURL=getEnvironmentVariables.js.map
7906
8205
 
@@ -7944,34 +8243,6 @@ exports.getLabels = getLabels;
7944
8243
 
7945
8244
  /***/ }),
7946
8245
 
7947
- /***/ 77360:
7948
- /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7949
-
7950
- "use strict";
7951
-
7952
- Object.defineProperty(exports, "__esModule", ({ value: true }));
7953
- exports.getReviewSlug = void 0;
7954
- const bash_1 = __nccwpck_require__(94143);
7955
- const bashExpressionPerPipelineType_1 = __nccwpck_require__(6495);
7956
- const getEnvType_1 = __nccwpck_require__(46080);
7957
- const REVIEW_SLUG = {
7958
- default: "unknown-review-slug",
7959
- gitlab: new bash_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"; })`),
7960
- // CL_PR_NUMBER is injected by the github backend at the workflow level
7961
- github: new bash_1.BashExpression(`$([ -n "$CL_PR_NUMBER" ] && echo "pr$CL_PR_NUMBER" || echo "unknown")`),
7962
- };
7963
- const getReviewSlug = (envConfig, env, pipelineType) => {
7964
- const envType = (0, getEnvType_1.getEnvType)(env, envConfig);
7965
- if (envType === "review") {
7966
- return (0, bashExpressionPerPipelineType_1.getBashExpressionPerPipelineType)(REVIEW_SLUG, pipelineType);
7967
- }
7968
- return null; // not a review app;
7969
- };
7970
- exports.getReviewSlug = getReviewSlug;
7971
- //# sourceMappingURL=getReviewSlug.js.map
7972
-
7973
- /***/ }),
7974
-
7975
8246
  /***/ 15707:
7976
8247
  /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
7977
8248
 
@@ -7994,6 +8265,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
7994
8265
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7995
8266
  __exportStar(__nccwpck_require__(53373), exports);
7996
8267
  __exportStar(__nccwpck_require__(69578), exports);
8268
+ __exportStar(__nccwpck_require__(52181), exports);
7997
8269
  __exportStar(__nccwpck_require__(21494), exports);
7998
8270
  __exportStar(__nccwpck_require__(17429), exports);
7999
8271
  //# sourceMappingURL=index.js.map
@@ -8603,8 +8875,11 @@ class DeployJob extends jobs_1.CatladderJob {
8603
8875
  var _a, _b, _c, _d, _e, _f, _g;
8604
8876
  const hasDocker = (0, docker_1.requiresDockerBuild)(context);
8605
8877
  const isStoppable = (0, utils_1.contextIsStoppable)(context);
8878
+ // env-level autoStop config wins; the env type only supplies the
8879
+ // default (via the project-wide `autoStop` durations)
8880
+ const autoStopConfigured = context.environment.autoStop;
8606
8881
  const autoStopConfig = (0, autoStop_1.getAutoStopConfig)(context.fullConfig);
8607
- const autoStop = context.environment.envType === "review"
8882
+ const autoStopDefault = context.environment.envType === "review"
8608
8883
  ? // review envs read the lifetime from a pipeline variable, so
8609
8884
  // the pin label's workflow rule can override it to "never"
8610
8885
  autoStopConfig.pinLabel === false
@@ -8613,6 +8888,13 @@ class DeployJob extends jobs_1.CatladderJob {
8613
8888
  : context.environment.envType === "dev"
8614
8889
  ? autoStopConfig.dev
8615
8890
  : undefined;
8891
+ // NOTE: an explicit env-level autoStop is a literal — a review env
8892
+ // overriding it opts out of the pin-label variable indirection
8893
+ const autoStop = autoStopConfigured === undefined
8894
+ ? autoStopDefault
8895
+ : autoStopConfigured === false
8896
+ ? undefined
8897
+ : autoStopConfigured;
8616
8898
  const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
8617
8899
  // if auto or manual is configured explicitly, use that
8618
8900
  const whenDeployDefined = deployConfig && deployConfig.when ? deployConfig.when : undefined;
@@ -8880,7 +9162,8 @@ exports.getArtifactsRegistryDockerUrl = getArtifactsRegistryDockerUrl;
8880
9162
  * lecacyReviewImageName is only temporary. In old versions the images had no reviewslug in review apps, which makes cleanup harder. We delete all those images now, but need the path
8881
9163
  */
8882
9164
  const getArtifactsRegistryImageName = (context, lecacyReviewImageName = false) => {
8883
- if (lecacyReviewImageName && context.environment.envType !== "review") {
9165
+ const { instance } = context.environment;
9166
+ if (lecacyReviewImageName && instance.type !== "review") {
8884
9167
  throw new Error("lecacyReviewImageName is only allowed for review app");
8885
9168
  }
8886
9169
  const dockerUrl = (0, exports.getArtifactsRegistryDockerUrl)(context);
@@ -8888,8 +9171,8 @@ const getArtifactsRegistryImageName = (context, lecacyReviewImageName = false) =
8888
9171
  dockerUrl,
8889
9172
  context.env,
8890
9173
  context.name,
8891
- ...(context.environment.reviewSlug && !lecacyReviewImageName
8892
- ? [context.environment.reviewSlug]
9174
+ ...(instance.type === "review" && !lecacyReviewImageName
9175
+ ? [instance.reviewSlug]
8893
9176
  : []),
8894
9177
  ];
8895
9178
  return (0, bash_1.joinBashExpressions)(gcloudImagePath, "/");
@@ -8939,7 +9222,7 @@ const getDeleteUnusedImagesCommands = (context, keep = 0) => {
8939
9222
  ...getDeleteImageCommands(buildCacheImageName, 1),
8940
9223
  // because a recent version of catladder had no review-slug in the image name, we have to delete those as well
8941
9224
  // we can later remove this line in some months
8942
- ...(context.environment.envType === "review"
9225
+ ...(context.environment.instance.type === "review"
8943
9226
  ? (0, gitlab_1.allowFailureInScripts)(getDeleteImageCommands((0, exports.getArtifactsRegistryImageName)(context, true), 0))
8944
9227
  : []),
8945
9228
  ];
@@ -8960,12 +9243,18 @@ const gitlab_1 = __nccwpck_require__(86962);
8960
9243
  const artifactsRegistry_1 = __nccwpck_require__(44330);
8961
9244
  const cloudRunRevisions_1 = __nccwpck_require__(55698);
8962
9245
  const getRemoveOldRevisionsAndImagesCommand = (context, when) => {
9246
+ var _a;
8963
9247
  if (when === "onStop") {
8964
9248
  // service is already deleted, so we don't need to delete old revisions, just delete all images
8965
9249
  return (0, artifactsRegistry_1.getDeleteUnusedImagesCommands)(context);
8966
9250
  }
8967
- // this number only targets inactive revisions
8968
- const revisionsToKeep = context.environment.envType === "prod" ? 5 : 0;
9251
+ const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
9252
+ const configuredRevisionsToKeep = deployConfig && deployConfig.type === "google-cloudrun"
9253
+ ? deployConfig.revisionsToKeep
9254
+ : undefined;
9255
+ // this number only targets inactive revisions; the env type only
9256
+ // supplies the default (prod keeps a rollback history)
9257
+ const revisionsToKeep = configuredRevisionsToKeep !== null && configuredRevisionsToKeep !== void 0 ? configuredRevisionsToKeep : (context.environment.envType === "prod" ? 5 : 0);
8969
9258
  // this number needs to be higher than inactive after deploy, so we add one
8970
9259
  const imagesToKeep = revisionsToKeep + 1;
8971
9260
  const deleteOldRevisionsCommands = (0, cloudRunRevisions_1.getDeleteUnusedRevisionsCommands)(context, revisionsToKeep);
@@ -9872,7 +10161,7 @@ const cloudRunExecutionUrl_1 = __nccwpck_require__(49963);
9872
10161
  const database_1 = __nccwpck_require__(11595);
9873
10162
  const getServiceName_1 = __nccwpck_require__(33102);
9874
10163
  exports.GCLOUD_DEPLOY_CREDENTIALS_KEY = "GCLOUD_DEPLOY_credentialsKey";
9875
- const getCloudSqlVariables = ({ deployConfigRaw, environmentSlugPrefix, env, componentName, fullConfig, }) => {
10164
+ const getCloudSqlVariables = ({ deployConfigRaw, environmentSlugPrefix, secretsEnv, componentName, fullConfig, }) => {
9876
10165
  var _a, _b, _c;
9877
10166
  if (deployConfigRaw && deployConfigRaw.cloudSql) {
9878
10167
  const DB_NAME = (0, utils_1.getFullDbName)(deployConfigRaw.cloudSql, fullConfig, environmentSlugPrefix, componentName);
@@ -9883,7 +10172,7 @@ const getCloudSqlVariables = ({ deployConfigRaw, environmentSlugPrefix, env, com
9883
10172
  CLOUD_SQL_INSTANCE_CONNECTION_NAME: deployConfigRaw.cloudSql.instanceConnectionName,
9884
10173
  DB_NAME: DB_NAME,
9885
10174
  DB_USER: (_b = deployConfigRaw.cloudSql.dbUser) !== null && _b !== void 0 ? _b : "postgres",
9886
- DB_PASSWORD: "$" + (0, context_1.getSecretVarName)(env, componentName, "DB_PASSWORD"),
10175
+ DB_PASSWORD: "$" + (0, context_1.getSecretVarName)(secretsEnv, componentName, "DB_PASSWORD"),
9887
10176
  };
9888
10177
  return {
9889
10178
  ...dbVars,
@@ -10356,7 +10645,7 @@ const fromComponentContext = (context) => {
10356
10645
  environmentSlugPrefix: context.environment.slugPrefix,
10357
10646
  componentName: context.name,
10358
10647
  env: context.env,
10359
- isReviewEnv: context.environment.envType === "review",
10648
+ isReviewEnv: context.environment.instance.type === "review",
10360
10649
  deployConfig: deployConfig && deployConfig.type === "google-cloudrun"
10361
10650
  ? deployConfig
10362
10651
  : null,
@@ -10368,7 +10657,7 @@ const fromEnvironmentContext = (context) => ({
10368
10657
  environmentSlugPrefix: context.environmentSlugPrefix,
10369
10658
  componentName: context.componentName,
10370
10659
  env: context.env,
10371
- isReviewEnv: context.envType === "review",
10660
+ isReviewEnv: context.instance.type === "review",
10372
10661
  deployConfig: context.deployConfigRaw || null,
10373
10662
  config: context.fullConfig,
10374
10663
  });
@@ -10822,9 +11111,9 @@ exports.KUBERNETES_DEPLOY_TYPE = {
10822
11111
  jobs: deployJob_1.createKubernetesDeployJobs,
10823
11112
  defaults: () => ({}),
10824
11113
  additionalSecretKeys: additionalSecretKeys_1.additionalKubernetesSecretKeys,
10825
- getAdditionalEnvVars: ({ componentName, fullConfig, deployConfigRaw, env, reviewSlug, envType, }) => {
11114
+ getAdditionalEnvVars: ({ componentName, fullConfig, deployConfigRaw, env, instance, }) => {
10826
11115
  var _a;
10827
- const KUBE_APP_NAME_PREFIX = envType === "review" && reviewSlug ? reviewSlug.concat("-") : "";
11116
+ const KUBE_APP_NAME_PREFIX = instance.type === "review" ? instance.reviewSlug.concat("-") : "";
10828
11117
  const KUBE_APP_NAME = KUBE_APP_NAME_PREFIX.concat(componentName);
10829
11118
  const KUBE_NAMESPACE = (0, __1.getKubernetesNamespace)(fullConfig, env);
10830
11119
  const componentSlug = (0, slugify_1.default)(componentName);
@@ -10833,7 +11122,7 @@ exports.KUBERNETES_DEPLOY_TYPE = {
10833
11122
  "panter.cloud";
10834
11123
  const HOSTNAME_INTERNAL = (0, bash_1.joinBashExpressions)([
10835
11124
  componentSlug,
10836
- ...(envType === "review" && reviewSlug ? [reviewSlug] : []),
11125
+ ...(instance.type === "review" ? [instance.reviewSlug] : []),
10837
11126
  env,
10838
11127
  fullConfig.appName,
10839
11128
  fullConfig.customerName,
@@ -11191,7 +11480,8 @@ const createPagesDeployJobs = async (context) => {
11191
11480
  throw new Error("deploy config is not pages");
11192
11481
  }
11193
11482
  const onGithub = context.pipelineType === "github";
11194
- if (onGithub && context.environment.envType === "review") {
11483
+ const isReviewApp = context.environment.instance.type === "review";
11484
+ if (onGithub && isReviewApp) {
11195
11485
  // github pages serves ONE site per repository and deploy-pages
11196
11486
  // replaces all of it — there is no path_prefix equivalent, so per-PR
11197
11487
  // previews cannot exist (deploy-pages has a `preview` input, but it
@@ -11202,7 +11492,7 @@ const createPagesDeployJobs = async (context) => {
11202
11492
  }
11203
11493
  // review environments publish under their own path prefix (gitlab
11204
11494
  // parallel deployments) — every merge request gets a site preview
11205
- const pathPrefix = context.environment.envType === "review" ? "mr-$CI_MERGE_REQUEST_IID" : "";
11495
+ const pathPrefix = isReviewApp ? "mr-$CI_MERGE_REQUEST_IID" : "";
11206
11496
  const publishDir = (_b = deployConfig.publishDir) !== null && _b !== void 0 ? _b : "public";
11207
11497
  const packageManagerInstall = await (0, packageManagerInstall_1.getPackageManagerInstall)(context, {
11208
11498
  noCustomPostInstall: true,
@@ -12899,12 +13189,22 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
12899
13189
  "use strict";
12900
13190
 
12901
13191
  Object.defineProperty(exports, "__esModule", ({ value: true }));
12902
- exports.isKnowEnvType = exports.DEFAULT_ENV_TYPES = exports.DEFAULT_ENVS = exports.getEnvTypesByTrigger = exports.ENV_TYPES = exports.ALL_PIPELINE_TRIGGERS = void 0;
13192
+ exports.isKnowEnvType = exports.DEFAULT_ENV_TYPES = exports.DEFAULT_ENVS = exports.ENV_TYPES = exports.envTriggerEquals = exports.isBranchTrigger = exports.ALL_PIPELINE_TRIGGERS = void 0;
12903
13193
  exports.ALL_PIPELINE_TRIGGERS = [
12904
13194
  "mainBranch",
12905
13195
  "mr",
12906
13196
  "taggedRelease",
12907
13197
  ];
13198
+ const isBranchTrigger = (trigger) => typeof trigger === "object" && trigger !== null && "branch" in trigger;
13199
+ exports.isBranchTrigger = isBranchTrigger;
13200
+ const envTriggerEquals = (a, b) => {
13201
+ if (a === undefined || a === false)
13202
+ return false;
13203
+ if ((0, exports.isBranchTrigger)(b))
13204
+ return (0, exports.isBranchTrigger)(a) && a.branch === b.branch;
13205
+ return a === b;
13206
+ };
13207
+ exports.envTriggerEquals = envTriggerEquals;
12908
13208
  /**
12909
13209
  * all env types with their trigger.
12910
13210
  * Each env type has a default env with the same name which is always included
@@ -12926,15 +13226,6 @@ exports.ENV_TYPES = {
12926
13226
  triggers: [],
12927
13227
  },
12928
13228
  };
12929
- /**
12930
- *
12931
- * @param trigger a trigger
12932
- * @returns array of env types for that trigger. this is also the list of default envs
12933
- */
12934
- const getEnvTypesByTrigger = (trigger) => Object.entries(exports.ENV_TYPES)
12935
- .filter(([, e]) => e.triggers.includes(trigger))
12936
- .map(([e]) => e);
12937
- exports.getEnvTypesByTrigger = getEnvTypesByTrigger;
12938
13229
  exports.DEFAULT_ENVS = Object.keys(exports.ENV_TYPES);
12939
13230
  exports.DEFAULT_ENV_TYPES = exports.DEFAULT_ENVS;
12940
13231
  const isKnowEnvType = (env) => {