@catladder/cli 5.1.3 → 5.3.0

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 (92) 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/secrets/github.js +4 -2
  8. package/dist/apps/cli/src/secrets/github.js.map +1 -1
  9. package/dist/bundles/catenv/index.js +419 -106
  10. package/dist/bundles/cli/index.js +449 -111
  11. package/dist/bundles/skills/catladder-config/SKILL.md +34 -2
  12. package/dist/bundles/skills/catladder-deploys/SKILL.md +5 -0
  13. package/dist/bundles/skills/catladder-pipelines/SKILL.md +42 -1
  14. package/dist/bundles/skills/catladder-secrets/SKILL.md +6 -0
  15. package/dist/packages/pipeline/src/backends/github/GithubBackend.js +23 -3
  16. package/dist/packages/pipeline/src/backends/github/GithubBackend.js.map +1 -1
  17. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js +2 -2
  18. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js.map +1 -1
  19. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js +18 -2
  20. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
  21. package/dist/packages/pipeline/src/backends/gitlab/createGitlabJobs.js +2 -2
  22. package/dist/packages/pipeline/src/backends/gitlab/createGitlabJobs.js.map +1 -1
  23. package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.d.ts +6 -1
  24. package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.js +24 -1
  25. package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.js.map +1 -1
  26. package/dist/packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.d.ts +17 -0
  27. package/dist/packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.js +13 -0
  28. package/dist/packages/pipeline/src/backends/gitlab/gitlabReleaseJobs.js.map +1 -1
  29. package/dist/packages/pipeline/src/config/configruedEnvs.d.ts +9 -2
  30. package/dist/packages/pipeline/src/config/configruedEnvs.js +54 -5
  31. package/dist/packages/pipeline/src/config/configruedEnvs.js.map +1 -1
  32. package/dist/packages/pipeline/src/context/createAllComponentsContext.d.ts +2 -2
  33. package/dist/packages/pipeline/src/context/createComponentContext.d.ts +2 -2
  34. package/dist/packages/pipeline/src/context/createWorkspaceContext.d.ts +2 -2
  35. package/dist/packages/pipeline/src/context/getEnvConfig.js +35 -19
  36. package/dist/packages/pipeline/src/context/getEnvConfig.js.map +1 -1
  37. package/dist/packages/pipeline/src/context/getEnvInherit.d.ts +20 -0
  38. package/dist/packages/pipeline/src/context/getEnvInherit.js +72 -0
  39. package/dist/packages/pipeline/src/context/getEnvInherit.js.map +1 -0
  40. package/dist/packages/pipeline/src/context/getEnvInstance.d.ts +4 -0
  41. package/dist/packages/pipeline/src/context/{getReviewSlug.js → getEnvInstance.js} +13 -9
  42. package/dist/packages/pipeline/src/context/getEnvInstance.js.map +1 -0
  43. package/dist/packages/pipeline/src/context/getEnvOn.d.ts +13 -0
  44. package/dist/packages/pipeline/src/context/getEnvOn.js +28 -0
  45. package/dist/packages/pipeline/src/context/getEnvOn.js.map +1 -0
  46. package/dist/packages/pipeline/src/context/getEnvType.d.ts +8 -2
  47. package/dist/packages/pipeline/src/context/getEnvType.js +27 -5
  48. package/dist/packages/pipeline/src/context/getEnvType.js.map +1 -1
  49. package/dist/packages/pipeline/src/context/getEnvironment.js +3 -0
  50. package/dist/packages/pipeline/src/context/getEnvironment.js.map +1 -1
  51. package/dist/packages/pipeline/src/context/getEnvironmentContext.js +18 -8
  52. package/dist/packages/pipeline/src/context/getEnvironmentContext.js.map +1 -1
  53. package/dist/packages/pipeline/src/context/getEnvironmentVariables.d.ts +1 -1
  54. package/dist/packages/pipeline/src/context/getEnvironmentVariables.js +4 -4
  55. package/dist/packages/pipeline/src/context/getEnvironmentVariables.js.map +1 -1
  56. package/dist/packages/pipeline/src/context/index.d.ts +1 -0
  57. package/dist/packages/pipeline/src/context/index.js +1 -0
  58. package/dist/packages/pipeline/src/context/index.js.map +1 -1
  59. package/dist/packages/pipeline/src/deploy/base/deploy.js +11 -1
  60. package/dist/packages/pipeline/src/deploy/base/deploy.js.map +1 -1
  61. package/dist/packages/pipeline/src/deploy/cloudRun/artifactsRegistry.js +5 -4
  62. package/dist/packages/pipeline/src/deploy/cloudRun/artifactsRegistry.js.map +1 -1
  63. package/dist/packages/pipeline/src/deploy/cloudRun/cleanup.js +8 -2
  64. package/dist/packages/pipeline/src/deploy/cloudRun/cleanup.js.map +1 -1
  65. package/dist/packages/pipeline/src/deploy/cloudRun/index.js +2 -2
  66. package/dist/packages/pipeline/src/deploy/cloudRun/index.js.map +1 -1
  67. package/dist/packages/pipeline/src/deploy/cloudRun/utils/getServiceName.js +2 -2
  68. package/dist/packages/pipeline/src/deploy/cloudRun/utils/getServiceName.js.map +1 -1
  69. package/dist/packages/pipeline/src/deploy/kubernetes/index.js +3 -3
  70. package/dist/packages/pipeline/src/deploy/kubernetes/index.js.map +1 -1
  71. package/dist/packages/pipeline/src/deploy/pages/deployJob.js +3 -2
  72. package/dist/packages/pipeline/src/deploy/pages/deployJob.js.map +1 -1
  73. package/dist/packages/pipeline/src/deploy/types/googleCloudRun.d.ts +9 -0
  74. package/dist/packages/pipeline/src/types/config.d.ts +126 -9
  75. package/dist/packages/pipeline/src/types/config.js +11 -10
  76. package/dist/packages/pipeline/src/types/config.js.map +1 -1
  77. package/dist/packages/pipeline/src/types/context.d.ts +22 -3
  78. package/dist/packages/pipeline/src/types/context.js.map +1 -1
  79. package/dist/packages/pipeline/src/types/environmentContext.d.ts +29 -0
  80. package/dist/packages/pipeline/src/types/gitlab-types.d.ts +29 -1
  81. package/dist/skills/catladder-config/SKILL.md +34 -2
  82. package/dist/skills/catladder-deploys/SKILL.md +5 -0
  83. package/dist/skills/catladder-pipelines/SKILL.md +42 -1
  84. package/dist/skills/catladder-secrets/SKILL.md +6 -0
  85. package/dist/tsconfig.tsbuildinfo +1 -1
  86. package/package.json +1 -1
  87. package/src/commands/project/commandPortForward.ts +1 -1
  88. package/src/commands/project/secrets/scope.ts +38 -2
  89. package/src/config/getProjectConfig.ts +9 -1
  90. package/src/secrets/github.ts +8 -5
  91. package/dist/packages/pipeline/src/context/getReviewSlug.d.ts +0 -4
  92. 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,7 +4635,7 @@ 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
4641
  const dotEnvFile = "gitlab_environment.env";
@@ -4613,7 +4652,7 @@ const addGitlabEnvironment = (context, catladderJobEnvironment, job, allJobs) =>
4613
4652
  `echo "${exports.GITLAB_ENVIRONMENT_URL_VARIABLE}=${(0, bash_1.getBashVariable)("ROOT_URL")}" >> ${dotEnvFile}`,
4614
4653
  ];
4615
4654
  // this is NOT a bashVariable since it NEEDS to be used as a string in gitlab
4616
- const gitlabEnvironmentName = envType === "review"
4655
+ const gitlabEnvironmentName = instance.type === "review"
4617
4656
  ? `${env}/$CI_COMMIT_REF_NAME/${name}` // FIXME: should be replaced with mr name as well
4618
4657
  : `${env}/${name}`;
4619
4658
  return {
@@ -4781,7 +4820,7 @@ const rules_1 = __nccwpck_require__(78503);
4781
4820
  * build-free image (a catladder job image would drag in a build job).
4782
4821
  */
4783
4822
  const DEFAULT_PIPELINE_IMAGE = "node:22";
4784
- const createGitlabPipelineWithDefaults = ({ image, variables, before_script, autoStop, ...config }) => {
4823
+ const createGitlabPipelineWithDefaults = ({ image, variables, before_script, branchPipelines = [], autoStop, ...config }) => {
4785
4824
  const pinLabel = autoStop && autoStop.pinLabel;
4786
4825
  return {
4787
4826
  image: image !== null && image !== void 0 ? image : DEFAULT_PIPELINE_IMAGE,
@@ -4803,9 +4842,20 @@ const createGitlabPipelineWithDefaults = ({ image, variables, before_script, aut
4803
4842
  ],
4804
4843
  workflow: {
4805
4844
  name: "$PIPELINE_ICON $PIPELINE_NAME",
4845
+ // superseded pipelines must actually die: "interruptible" cancels
4846
+ // every interruptible job, while gitlab's default "conservative"
4847
+ // lets one started `interruptible: false` job shield the whole
4848
+ // pipeline from cancellation. The rules below opt the pipelines
4849
+ // that must run to completion back out.
4850
+ // NOTE: this only tunes the project setting "Auto-cancel
4851
+ // redundant pipelines" — with that setting off nothing cancels.
4852
+ auto_cancel: { on_new_commit: "interruptible" },
4806
4853
  rules: [
4807
4854
  {
4808
4855
  if: '$CI_PIPELINE_SOURCE == "trigger"',
4856
+ // an agent run is not redundant work: a commit landing while
4857
+ // it thinks must not kill it
4858
+ auto_cancel: { on_new_commit: "none" },
4809
4859
  variables: {
4810
4860
  PIPELINE_ICON: "🤖",
4811
4861
  PIPELINE_NAME: "Thinking...",
@@ -4834,6 +4884,11 @@ const createGitlabPipelineWithDefaults = ({ image, variables, before_script, aut
4834
4884
  },
4835
4885
  {
4836
4886
  if: rules_1.RULE_IS_TAGGED_RELEASE.if,
4887
+ // a release pipeline always runs through: tags are immutable,
4888
+ // so this only bites when someone force-moves one — and a
4889
+ // release cancelled halfway leaves the version published in
4890
+ // some places and missing in others
4891
+ auto_cancel: { on_new_commit: "none" },
4837
4892
  variables: {
4838
4893
  PIPELINE_ICON: "🐱📦",
4839
4894
  PIPELINE_NAME: "Release $CI_COMMIT_TAG",
@@ -4846,6 +4901,13 @@ const createGitlabPipelineWithDefaults = ({ image, variables, before_script, aut
4846
4901
  PIPELINE_NAME: "Main - $CI_COMMIT_TITLE",
4847
4902
  },
4848
4903
  },
4904
+ ...branchPipelines.map((branch) => ({
4905
+ if: `$CI_COMMIT_BRANCH == "${branch}"`,
4906
+ variables: {
4907
+ PIPELINE_ICON: "🐱🔨",
4908
+ PIPELINE_NAME: `${branch} - $CI_COMMIT_TITLE`,
4909
+ },
4910
+ })),
4849
4911
  {
4850
4912
  when: "always", // fallback
4851
4913
  variables: {
@@ -4950,6 +5012,12 @@ mainBranchJobNames) => {
4950
5012
  image: releaseImage,
4951
5013
  script: [method.script],
4952
5014
  after_script: [EXPIRED_TOKEN_HELP],
5015
+ // a release in flight must never be killed by a new commit — a
5016
+ // half-published version (tag pushed, npm publish missing) is not
5017
+ // recoverable by re-running. Under gitlab's default "conservative"
5018
+ // auto-cancel this also shields the rest of the pipeline, but only
5019
+ // once the release actually started, which is late by construction.
5020
+ interruptible: false,
4953
5021
  };
4954
5022
  const forceReleaseJob = {
4955
5023
  ["⚠️ force create release"]: {
@@ -4973,6 +5041,10 @@ mainBranchJobNames) => {
4973
5041
  stage: "test",
4974
5042
  image: releaseImage,
4975
5043
  script: [method.checkScript],
5044
+ // a redundant report is worthless: without this the job
5045
+ // defaults to interruptible: false and, once started, stops
5046
+ // gitlab from auto-cancelling the superseded MR pipeline
5047
+ interruptible: true,
4976
5048
  allow_failure: true,
4977
5049
  artifacts: {
4978
5050
  paths: ["changeset-report.md"],
@@ -5042,6 +5114,9 @@ mainBranchJobNames) => {
5042
5114
  script: [
5043
5115
  `echo "release queued — '${exports.RELEASE_EXECUTOR_JOB_NAME}' runs it as soon as every other job in this pipeline succeeded"`,
5044
5116
  ],
5117
+ // the recorded intent must survive a new commit: cancelling it
5118
+ // would silently drop the queued release
5119
+ interruptible: false,
5045
5120
  needs: [],
5046
5121
  // allow_failure keeps the unclicked button from blocking the
5047
5122
  // pipeline AND makes the executor's needs treat it as optional
@@ -7259,8 +7334,10 @@ exports.createCatenvContext = createCatenvContext;
7259
7334
  "use strict";
7260
7335
 
7261
7336
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7262
- exports.getAllEnvsByTrigger = exports.getAllEnvsInAllComponents = exports.getAllEnvs = void 0;
7337
+ exports.getConfiguredBranchTriggers = exports.getAllEnvsByTrigger = exports.getAllEnvsInAllComponents = exports.getAllEnvs = void 0;
7263
7338
  const types_1 = __nccwpck_require__(63557);
7339
+ const getEnvOn_1 = __nccwpck_require__(60601);
7340
+ const getEnvType_1 = __nccwpck_require__(46080);
7264
7341
  const getConfiguredAndDefaultEnvs = (config, componentName, envTypes) => {
7265
7342
  var _a, _b;
7266
7343
  const configuredEnvs = (_a = config.components[componentName].env) !== null && _a !== void 0 ? _a : {};
@@ -7268,13 +7345,33 @@ const getConfiguredAndDefaultEnvs = (config, componentName, envTypes) => {
7268
7345
  // these can be disabled with settimg them to `false`
7269
7346
  // this is the list of all not disabled envs. These are always returned
7270
7347
  const enabledDefaultEnvs = envTypes.filter((e) => configuredEnvs[e] !== false);
7271
- const configuredCustomEnvs = Object.entries((_b = config.components[componentName].env) !== null && _b !== void 0 ? _b : {})
7348
+ // envs declared project-wide (top-level `environments`): every
7349
+ // component deploys to them unless it opts out with `env.<name>: false`
7350
+ const declaredEnvs = Object.keys((_b = config.environments) !== null && _b !== void 0 ? _b : {})
7351
+ .filter((envName) => !(0, types_1.isKnowEnvType)(envName)) // default envs are already handled above
7352
+ .map((envName) => {
7353
+ const envType = (0, getEnvType_1.getDeclaredEnvType)(config.environments, envName);
7354
+ if (!envType) {
7355
+ throw new Error(`environment "${envName}" needs a type (dev, review, stage, prod) or an inherit`);
7356
+ }
7357
+ return [envName, envType];
7358
+ })
7359
+ .filter(([envName, envType]) => envTypes.includes(envType) && configuredEnvs[envName] !== false)
7360
+ .map(([envName]) => envName);
7361
+ // legacy: custom envs declared per component via their `type`
7362
+ const configuredCustomEnvs = Object.entries(configuredEnvs)
7272
7363
  .filter(([, config]) => config &&
7273
7364
  "type" in config &&
7274
7365
  config.type &&
7275
7366
  envTypes.includes(config.type))
7276
7367
  .map(([envName]) => envName);
7277
- return [...new Set([...enabledDefaultEnvs, ...configuredCustomEnvs])];
7368
+ return [
7369
+ ...new Set([
7370
+ ...enabledDefaultEnvs,
7371
+ ...declaredEnvs,
7372
+ ...configuredCustomEnvs,
7373
+ ]),
7374
+ ];
7278
7375
  };
7279
7376
  const getAllEnvs = (config, componentName) => {
7280
7377
  return getConfiguredAndDefaultEnvs(config, componentName, types_1.DEFAULT_ENV_TYPES);
@@ -7286,11 +7383,38 @@ const getAllEnvsInAllComponents = (config) => {
7286
7383
  ];
7287
7384
  };
7288
7385
  exports.getAllEnvsInAllComponents = getAllEnvsInAllComponents;
7386
+ /**
7387
+ * the resolved `on` of one env of a component (the project-wide `on`
7388
+ * of the env, falling back to the env type's default trigger)
7389
+ */
7390
+ const getEnvOnForComponentEnv = (config, componentName, env) => {
7391
+ var _a;
7392
+ const entry = (_a = config.components[componentName].env) === null || _a === void 0 ? void 0 : _a[env];
7393
+ return (0, getEnvOn_1.getEnvOn)(env, entry && entry !== false ? entry : {}, config.environments);
7394
+ };
7289
7395
  const getAllEnvsByTrigger = (config, componentName, trigger) => {
7290
- const envTypesByTrigger = (0, types_1.getEnvTypesByTrigger)(trigger);
7291
- return getConfiguredAndDefaultEnvs(config, componentName, envTypesByTrigger);
7396
+ return (0, exports.getAllEnvs)(config, componentName).filter((env) => (0, types_1.envTriggerEquals)(getEnvOnForComponentEnv(config, componentName, env), trigger));
7292
7397
  };
7293
7398
  exports.getAllEnvsByTrigger = getAllEnvsByTrigger;
7399
+ /**
7400
+ * all branch triggers declared by any env of any component (via
7401
+ * `on: { branch: "..." }`), deduplicated and sorted for deterministic
7402
+ * pipeline generation. Each gets its own pipeline next to the built-in
7403
+ * triggers.
7404
+ */
7405
+ const getConfiguredBranchTriggers = (config) => {
7406
+ const branches = new Set();
7407
+ for (const componentName of Object.keys(config.components)) {
7408
+ for (const env of (0, exports.getAllEnvs)(config, componentName)) {
7409
+ const on = getEnvOnForComponentEnv(config, componentName, env);
7410
+ if (on && (0, types_1.isBranchTrigger)(on)) {
7411
+ branches.add(on.branch);
7412
+ }
7413
+ }
7414
+ }
7415
+ return [...branches].sort().map((branch) => ({ branch }));
7416
+ };
7417
+ exports.getConfiguredBranchTriggers = getConfiguredBranchTriggers;
7294
7418
  //# sourceMappingURL=configruedEnvs.js.map
7295
7419
 
7296
7420
  /***/ }),
@@ -7621,53 +7745,237 @@ exports.getBuildInfoVariables = getBuildInfoVariables;
7621
7745
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7622
7746
  exports.getEnvConfig = void 0;
7623
7747
  const lodash_es_1 = __nccwpck_require__(50210);
7748
+ const getEnvInherit_1 = __nccwpck_require__(52181);
7624
7749
  const getEnvConfig = (config, componentName, env) => {
7625
- var _a, _b;
7750
+ var _a;
7626
7751
  const defaultConfig = config.components[componentName];
7627
7752
  if (!defaultConfig) {
7628
7753
  throw new Error("unknown component " + componentName);
7629
7754
  }
7630
- const envCustomizations = (_b = (_a = defaultConfig.env) === null || _a === void 0 ? void 0 : _a[env]) !== null && _b !== void 0 ? _b : {};
7631
- if (envCustomizations === false) {
7632
- // env is disabled, still return the default config
7633
- return defaultConfig;
7634
- }
7635
- /**
7636
- * env config is merged with default. Arrays are not merged.
7637
- * you can customize this by providing a function that takes the default value as argument
7638
- */
7639
- return (0, lodash_es_1.mergeWith)(
7755
+ // env config is layered onto the component config: the per-component
7756
+ // overrides of inherited envs first (oldest ancestor first, see
7757
+ // `environments.<name>.inherit`), the env's own overrides last
7758
+ const chain = [...(0, getEnvInherit_1.getInheritedConfigChain)(config.environments, env), env];
7640
7759
  // mergeWith unfortunatly mutates the first object, so we need to clone it.
7641
7760
  // 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)
7642
- (0, lodash_es_1.cloneDeep)(defaultConfig), envCustomizations, (defaultValue, customValue, key, obj, source) => {
7643
- // check if custom value is a function (and default is not),
7644
- // we currently don't have config options, that are functions, but we might in the future (customJobs is an exception)
7645
- if (typeof customValue === "function" &&
7646
- typeof defaultValue !== "function") {
7647
- return customValue(defaultValue);
7761
+ const result = (0, lodash_es_1.cloneDeep)(defaultConfig);
7762
+ for (const chainEnv of chain) {
7763
+ const envCustomizations = (_a = defaultConfig.env) === null || _a === void 0 ? void 0 : _a[chainEnv];
7764
+ if (!envCustomizations || envCustomizations === false) {
7765
+ if (chainEnv === env && envCustomizations === false) {
7766
+ // env is disabled, still return the default config
7767
+ return defaultConfig;
7768
+ }
7769
+ continue;
7648
7770
  }
7649
- return undefined;
7650
- });
7771
+ /**
7772
+ * env config is merged with default. Arrays are not merged.
7773
+ * you can customize this by providing a function that takes the default value as argument
7774
+ */
7775
+ (0, lodash_es_1.mergeWith)(result,
7776
+ // `host` must stay unique per env and `type` is the inherited
7777
+ // env's identity — neither is inherited
7778
+ chainEnv === env
7779
+ ? envCustomizations
7780
+ : (0, lodash_es_1.omit)(envCustomizations, ["host", "type"]), (defaultValue, customValue, key, obj, source) => {
7781
+ // check if custom value is a function (and default is not),
7782
+ // we currently don't have config options, that are functions, but we might in the future (customJobs is an exception)
7783
+ if (typeof customValue === "function" &&
7784
+ typeof defaultValue !== "function") {
7785
+ return customValue(defaultValue);
7786
+ }
7787
+ return undefined;
7788
+ });
7789
+ }
7790
+ return result;
7651
7791
  };
7652
7792
  exports.getEnvConfig = getEnvConfig;
7653
7793
  //# sourceMappingURL=getEnvConfig.js.map
7654
7794
 
7655
7795
  /***/ }),
7656
7796
 
7797
+ /***/ 52181:
7798
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7799
+
7800
+ "use strict";
7801
+
7802
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
7803
+ exports.getSecretsEnv = exports.getInheritedConfigChain = exports.normalizeEnvInherit = void 0;
7804
+ const config_1 = __nccwpck_require__(75591);
7805
+ const normalizeEnvInherit = (inherit) => {
7806
+ if (!inherit)
7807
+ return {};
7808
+ if (typeof inherit === "string") {
7809
+ return { config: inherit, secrets: inherit };
7810
+ }
7811
+ return {
7812
+ config: inherit.config,
7813
+ secrets: inherit.secrets === false ? undefined : inherit.secrets,
7814
+ };
7815
+ };
7816
+ exports.normalizeEnvInherit = normalizeEnvInherit;
7817
+ const assertValidInheritTarget = (environments, env, target) => {
7818
+ if (target === "local") {
7819
+ throw new Error(`environment "${env}" cannot inherit from "local" — local is not a deployment environment`);
7820
+ }
7821
+ if (!(0, config_1.isKnowEnvType)(target) && !(environments === null || environments === void 0 ? void 0 : environments[target])) {
7822
+ throw new Error(`environment "${env}" inherits from unknown environment "${target}"`);
7823
+ }
7824
+ };
7825
+ /**
7826
+ * the chain of envs whose per-component config overrides feed into
7827
+ * `env`, oldest ancestor first (env itself not included). Cycles and
7828
+ * unknown/`local` targets are an error.
7829
+ */
7830
+ const getInheritedConfigChain = (environments, env) => {
7831
+ var _a;
7832
+ const chain = [];
7833
+ const seen = new Set([env]);
7834
+ let current = env;
7835
+ for (;;) {
7836
+ const target = (0, exports.normalizeEnvInherit)((_a = environments === null || environments === void 0 ? void 0 : environments[current]) === null || _a === void 0 ? void 0 : _a.inherit).config;
7837
+ if (!target)
7838
+ break;
7839
+ assertValidInheritTarget(environments, current, target);
7840
+ if (seen.has(target)) {
7841
+ throw new Error(`environment "${env}" has a cyclic config inheritance via "${target}"`);
7842
+ }
7843
+ seen.add(target);
7844
+ chain.unshift(target);
7845
+ current = target;
7846
+ }
7847
+ return chain;
7848
+ };
7849
+ exports.getInheritedConfigChain = getInheritedConfigChain;
7850
+ /**
7851
+ * the env whose secret values `env` uses (follows `inherit` secret
7852
+ * sharing transitively; the env itself when it has its own secrets).
7853
+ * All secret variable names must be built with this env.
7854
+ */
7855
+ const getSecretsEnv = (environments, env) => {
7856
+ var _a;
7857
+ const seen = new Set([env]);
7858
+ let current = env;
7859
+ for (;;) {
7860
+ const target = (0, exports.normalizeEnvInherit)((_a = environments === null || environments === void 0 ? void 0 : environments[current]) === null || _a === void 0 ? void 0 : _a.inherit).secrets;
7861
+ if (!target)
7862
+ return current;
7863
+ assertValidInheritTarget(environments, current, target);
7864
+ if (seen.has(target)) {
7865
+ throw new Error(`environment "${env}" has a cyclic secrets inheritance via "${target}"`);
7866
+ }
7867
+ seen.add(target);
7868
+ current = target;
7869
+ }
7870
+ };
7871
+ exports.getSecretsEnv = getSecretsEnv;
7872
+ //# sourceMappingURL=getEnvInherit.js.map
7873
+
7874
+ /***/ }),
7875
+
7876
+ /***/ 13055:
7877
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7878
+
7879
+ "use strict";
7880
+
7881
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
7882
+ exports.getEnvInstance = void 0;
7883
+ const bash_1 = __nccwpck_require__(94143);
7884
+ const bashExpressionPerPipelineType_1 = __nccwpck_require__(6495);
7885
+ const getEnvOn_1 = __nccwpck_require__(60601);
7886
+ const REVIEW_SLUG = {
7887
+ default: "unknown-review-slug",
7888
+ 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"; })`),
7889
+ // CL_PR_NUMBER is injected by the github backend at the workflow level
7890
+ github: new bash_1.BashExpression(`$([ -n "$CL_PR_NUMBER" ] && echo "pr$CL_PR_NUMBER" || echo "unknown")`),
7891
+ };
7892
+ const getEnvInstance = (envConfig, env, pipelineType, environments) => {
7893
+ // an env deploying per merge request is a review app — one dynamic
7894
+ // instance per MR, identified by the review slug
7895
+ if ((0, getEnvOn_1.getEnvOn)(env, envConfig, environments) === "mr") {
7896
+ return {
7897
+ type: "review",
7898
+ reviewSlug: (0, bashExpressionPerPipelineType_1.getBashExpressionPerPipelineType)(REVIEW_SLUG, pipelineType),
7899
+ };
7900
+ }
7901
+ return { type: "stable" };
7902
+ };
7903
+ exports.getEnvInstance = getEnvInstance;
7904
+ //# sourceMappingURL=getEnvInstance.js.map
7905
+
7906
+ /***/ }),
7907
+
7908
+ /***/ 60601:
7909
+ /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7910
+
7911
+ "use strict";
7912
+
7913
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
7914
+ exports.getEnvOn = void 0;
7915
+ const types_1 = __nccwpck_require__(63557);
7916
+ const getEnvType_1 = __nccwpck_require__(46080);
7917
+ const getDefaultOnForType = (envType) => {
7918
+ var _a;
7919
+ const triggers = types_1.ENV_TYPES[envType].triggers;
7920
+ return (_a = triggers[0]) !== null && _a !== void 0 ? _a : false;
7921
+ };
7922
+ /**
7923
+ * resolves when an env deploys: the project-wide `on` config of the env
7924
+ * (top-level `environments`), falling back to the default of its env
7925
+ * type (dev → mainBranch, review → mr, stage/prod → taggedRelease,
7926
+ * local → false).
7927
+ *
7928
+ * `on` is deliberately not configurable per component — an environment
7929
+ * deploys at one point in time for the whole project.
7930
+ */
7931
+ const getEnvOn = (env, envConfig, environments) => {
7932
+ var _a;
7933
+ const on = (_a = environments === null || environments === void 0 ? void 0 : environments[env]) === null || _a === void 0 ? void 0 : _a.on;
7934
+ if (on !== undefined)
7935
+ return on;
7936
+ return getDefaultOnForType((0, getEnvType_1.getEnvType)(env, envConfig, environments));
7937
+ };
7938
+ exports.getEnvOn = getEnvOn;
7939
+ //# sourceMappingURL=getEnvOn.js.map
7940
+
7941
+ /***/ }),
7942
+
7657
7943
  /***/ 46080:
7658
7944
  /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7659
7945
 
7660
7946
  "use strict";
7661
7947
 
7662
7948
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7663
- exports.getEnvType = void 0;
7949
+ exports.getEnvType = exports.getDeclaredEnvType = void 0;
7664
7950
  const types_1 = __nccwpck_require__(63557);
7665
- const getEnvType = (env, envConfig) => {
7666
- if (envConfig.type)
7667
- return envConfig.type;
7668
- if ((0, types_1.isKnowEnvType)(env)) {
7951
+ const getEnvInherit_1 = __nccwpck_require__(52181);
7952
+ /**
7953
+ * the type of a project-wide declared env: its explicit `type`, its
7954
+ * name (when it is itself an env type), or — for envs that inherit —
7955
+ * the type of the env they inherit their config from
7956
+ */
7957
+ const getDeclaredEnvType = (environments, env, seen = new Set()) => {
7958
+ const declared = environments === null || environments === void 0 ? void 0 : environments[env];
7959
+ if (declared === null || declared === void 0 ? void 0 : declared.type)
7960
+ return declared.type;
7961
+ if ((0, types_1.isKnowEnvType)(env))
7669
7962
  return env;
7963
+ const inheritTarget = (0, getEnvInherit_1.normalizeEnvInherit)(declared === null || declared === void 0 ? void 0 : declared.inherit).config;
7964
+ if (inheritTarget && !seen.has(inheritTarget)) {
7965
+ seen.add(inheritTarget);
7966
+ return (0, exports.getDeclaredEnvType)(environments, inheritTarget, seen);
7670
7967
  }
7968
+ return undefined;
7969
+ };
7970
+ exports.getDeclaredEnvType = getDeclaredEnvType;
7971
+ const getEnvType = (env, envConfig, environments) => {
7972
+ // legacy: per-component custom envs declare their type themselves
7973
+ if (envConfig.type)
7974
+ return envConfig.type;
7975
+ // project-wide declaration (top-level `environments`)
7976
+ const declaredType = (0, exports.getDeclaredEnvType)(environments, env);
7977
+ if (declaredType)
7978
+ return declaredType;
7671
7979
  throw new Error("unknown env type: " + env);
7672
7980
  };
7673
7981
  exports.getEnvType = getEnvType;
@@ -7693,8 +8001,11 @@ const getEnvironment = async (ctx) => {
7693
8001
  envType,
7694
8002
  fullName: envContext.fullName,
7695
8003
  slugPrefix: envContext.environmentSlugPrefix,
8004
+ instance: envContext.instance,
7696
8005
  reviewSlug: envContext.reviewSlug,
7697
8006
  slug: envContext.environmentSlug,
8007
+ autoStop: envContext.autoStop,
8008
+ secretsEnv: envContext.secretsEnv,
7698
8009
  ...variables,
7699
8010
  };
7700
8011
  };
@@ -7712,19 +8023,26 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
7712
8023
  exports.getEnvironmentContext = void 0;
7713
8024
  const bash_1 = __nccwpck_require__(94143);
7714
8025
  const getEnvConfig_1 = __nccwpck_require__(69578);
8026
+ const getEnvInstance_1 = __nccwpck_require__(13055);
8027
+ const getEnvInherit_1 = __nccwpck_require__(52181);
7715
8028
  const getEnvType_1 = __nccwpck_require__(46080);
7716
- const getReviewSlug_1 = __nccwpck_require__(77360);
7717
- const getEnvironmentSlugPrefix = (env, reviewSlug) => {
7718
- if (reviewSlug) {
7719
- return (0, bash_1.joinBashExpressions)([env, reviewSlug], "-");
8029
+ const getEnvironmentSlugPrefix = (env, instance) => {
8030
+ if (instance.type === "review") {
8031
+ return (0, bash_1.joinBashExpressions)([env, instance.reviewSlug], "-");
7720
8032
  }
7721
8033
  return env;
7722
8034
  };
7723
8035
  const getEnvironmentContext = ({ env, componentName, config, pipelineType, }) => {
8036
+ var _a, _b;
7724
8037
  const envConfigRaw = (0, getEnvConfig_1.getEnvConfig)(config, componentName, env);
7725
- const envType = (0, getEnvType_1.getEnvType)(env, envConfigRaw);
7726
- const reviewSlug = (0, getReviewSlug_1.getReviewSlug)(envConfigRaw, env, pipelineType);
7727
- const environmentSlugPrefix = getEnvironmentSlugPrefix(env, reviewSlug);
8038
+ const envType = (0, getEnvType_1.getEnvType)(env, envConfigRaw, config.environments);
8039
+ const instance = (0, getEnvInstance_1.getEnvInstance)(envConfigRaw, env, pipelineType, config.environments);
8040
+ // component-level autoStop overrides the project-wide environment
8041
+ // config; undefined means the env type's default applies
8042
+ const autoStop = envConfigRaw.autoStop !== undefined
8043
+ ? envConfigRaw.autoStop
8044
+ : (_b = (_a = config.environments) === null || _a === void 0 ? void 0 : _a[env]) === null || _b === void 0 ? void 0 : _b.autoStop;
8045
+ const environmentSlugPrefix = getEnvironmentSlugPrefix(env, instance);
7728
8046
  const environmentSlug = environmentSlugPrefix.concat(`-${componentName}`);
7729
8047
  const fullName = (0, bash_1.joinBashExpressions)([config.customerName, config.appName, environmentSlug], "-");
7730
8048
  return {
@@ -7733,10 +8051,13 @@ const getEnvironmentContext = ({ env, componentName, config, pipelineType, }) =>
7733
8051
  buildConfigRaw: envConfigRaw.build,
7734
8052
  environmentSlugPrefix,
7735
8053
  environmentSlug,
7736
- reviewSlug,
8054
+ instance,
8055
+ reviewSlug: instance.type === "review" ? instance.reviewSlug : null,
7737
8056
  pipelineType,
7738
8057
  fullName,
7739
8058
  envType,
8059
+ autoStop,
8060
+ secretsEnv: (0, getEnvInherit_1.getSecretsEnv)(config.environments, env),
7740
8061
  componentName,
7741
8062
  env,
7742
8063
  fullConfig: config,
@@ -7821,7 +8142,7 @@ const getEnvironmentVariables = async (ctx, options = {}) => {
7821
8142
  ...(0, envVars_1.normalizeSecretVarsConfig)((_f = envConfigRaw.vars) === null || _f === void 0 ? void 0 : _f.secret),
7822
8143
  ...additionalSecretKeys,
7823
8144
  ];
7824
- const secretEnvVars = (0, envVars_1.makeSecretEnvVarMapping)(env, componentName, secretEnvVarKeys);
8145
+ const secretEnvVars = (0, envVars_1.makeSecretEnvVarMapping)(environmentContext.secretsEnv, componentName, secretEnvVarKeys);
7825
8146
  const publicEnvVarsRawSanitized = (0, envVars_1.stringifyValues)(publicEnvVarsRaw);
7826
8147
  const publicEnvVarsUnresolved = Object.fromEntries(Object.entries(publicEnvVarsRawSanitized).map(([key, value]) => [
7827
8148
  key,
@@ -7855,11 +8176,11 @@ const getEnvironmentVariables = async (ctx, options = {}) => {
7855
8176
  envVars,
7856
8177
  secretEnvVarKeys,
7857
8178
  jobOnlyVars: {
7858
- build: await (0, transformJobOnlyVars_1.transformJobOnlyVars)(env, componentName, (buildConfigRaw &&
8179
+ build: await (0, transformJobOnlyVars_1.transformJobOnlyVars)(environmentContext.secretsEnv, componentName, (buildConfigRaw &&
7859
8180
  (0, types_1.isStandaloneBuildConfig)(buildConfigRaw) &&
7860
8181
  buildConfigRaw.jobVars) ||
7861
8182
  null),
7862
- deploy: await (0, transformJobOnlyVars_1.transformJobOnlyVars)(env, componentName, (deployConfigRaw && deployConfigRaw.jobVars) || null),
8183
+ deploy: await (0, transformJobOnlyVars_1.transformJobOnlyVars)(environmentContext.secretsEnv, componentName, (deployConfigRaw && deployConfigRaw.jobVars) || null),
7863
8184
  },
7864
8185
  };
7865
8186
  };
@@ -7871,7 +8192,7 @@ const addIndexVar = (vars) => ({
7871
8192
  ...vars,
7872
8193
  _ALL_ENV_VAR_KEYS: JSON.stringify(Object.keys(vars)),
7873
8194
  });
7874
- const getSecretVarNameForContext = (context, key) => (0, exports.getSecretVarName)(context.env, context.name, key);
8195
+ const getSecretVarNameForContext = (context, key) => (0, exports.getSecretVarName)(context.environment.secretsEnv, context.name, key);
7875
8196
  exports.getSecretVarNameForContext = getSecretVarNameForContext;
7876
8197
  //# sourceMappingURL=getEnvironmentVariables.js.map
7877
8198
 
@@ -7915,34 +8236,6 @@ exports.getLabels = getLabels;
7915
8236
 
7916
8237
  /***/ }),
7917
8238
 
7918
- /***/ 77360:
7919
- /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
7920
-
7921
- "use strict";
7922
-
7923
- Object.defineProperty(exports, "__esModule", ({ value: true }));
7924
- exports.getReviewSlug = void 0;
7925
- const bash_1 = __nccwpck_require__(94143);
7926
- const bashExpressionPerPipelineType_1 = __nccwpck_require__(6495);
7927
- const getEnvType_1 = __nccwpck_require__(46080);
7928
- const REVIEW_SLUG = {
7929
- default: "unknown-review-slug",
7930
- 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"; })`),
7931
- // CL_PR_NUMBER is injected by the github backend at the workflow level
7932
- github: new bash_1.BashExpression(`$([ -n "$CL_PR_NUMBER" ] && echo "pr$CL_PR_NUMBER" || echo "unknown")`),
7933
- };
7934
- const getReviewSlug = (envConfig, env, pipelineType) => {
7935
- const envType = (0, getEnvType_1.getEnvType)(env, envConfig);
7936
- if (envType === "review") {
7937
- return (0, bashExpressionPerPipelineType_1.getBashExpressionPerPipelineType)(REVIEW_SLUG, pipelineType);
7938
- }
7939
- return null; // not a review app;
7940
- };
7941
- exports.getReviewSlug = getReviewSlug;
7942
- //# sourceMappingURL=getReviewSlug.js.map
7943
-
7944
- /***/ }),
7945
-
7946
8239
  /***/ 15707:
7947
8240
  /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
7948
8241
 
@@ -7965,6 +8258,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
7965
8258
  Object.defineProperty(exports, "__esModule", ({ value: true }));
7966
8259
  __exportStar(__nccwpck_require__(53373), exports);
7967
8260
  __exportStar(__nccwpck_require__(69578), exports);
8261
+ __exportStar(__nccwpck_require__(52181), exports);
7968
8262
  __exportStar(__nccwpck_require__(21494), exports);
7969
8263
  __exportStar(__nccwpck_require__(17429), exports);
7970
8264
  //# sourceMappingURL=index.js.map
@@ -8574,8 +8868,11 @@ class DeployJob extends jobs_1.CatladderJob {
8574
8868
  var _a, _b, _c, _d, _e, _f, _g;
8575
8869
  const hasDocker = (0, docker_1.requiresDockerBuild)(context);
8576
8870
  const isStoppable = (0, utils_1.contextIsStoppable)(context);
8871
+ // env-level autoStop config wins; the env type only supplies the
8872
+ // default (via the project-wide `autoStop` durations)
8873
+ const autoStopConfigured = context.environment.autoStop;
8577
8874
  const autoStopConfig = (0, autoStop_1.getAutoStopConfig)(context.fullConfig);
8578
- const autoStop = context.environment.envType === "review"
8875
+ const autoStopDefault = context.environment.envType === "review"
8579
8876
  ? // review envs read the lifetime from a pipeline variable, so
8580
8877
  // the pin label's workflow rule can override it to "never"
8581
8878
  autoStopConfig.pinLabel === false
@@ -8584,6 +8881,13 @@ class DeployJob extends jobs_1.CatladderJob {
8584
8881
  : context.environment.envType === "dev"
8585
8882
  ? autoStopConfig.dev
8586
8883
  : undefined;
8884
+ // NOTE: an explicit env-level autoStop is a literal — a review env
8885
+ // overriding it opts out of the pin-label variable indirection
8886
+ const autoStop = autoStopConfigured === undefined
8887
+ ? autoStopDefault
8888
+ : autoStopConfigured === false
8889
+ ? undefined
8890
+ : autoStopConfigured;
8587
8891
  const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
8588
8892
  // if auto or manual is configured explicitly, use that
8589
8893
  const whenDeployDefined = deployConfig && deployConfig.when ? deployConfig.when : undefined;
@@ -8851,7 +9155,8 @@ exports.getArtifactsRegistryDockerUrl = getArtifactsRegistryDockerUrl;
8851
9155
  * 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
8852
9156
  */
8853
9157
  const getArtifactsRegistryImageName = (context, lecacyReviewImageName = false) => {
8854
- if (lecacyReviewImageName && context.environment.envType !== "review") {
9158
+ const { instance } = context.environment;
9159
+ if (lecacyReviewImageName && instance.type !== "review") {
8855
9160
  throw new Error("lecacyReviewImageName is only allowed for review app");
8856
9161
  }
8857
9162
  const dockerUrl = (0, exports.getArtifactsRegistryDockerUrl)(context);
@@ -8859,8 +9164,8 @@ const getArtifactsRegistryImageName = (context, lecacyReviewImageName = false) =
8859
9164
  dockerUrl,
8860
9165
  context.env,
8861
9166
  context.name,
8862
- ...(context.environment.reviewSlug && !lecacyReviewImageName
8863
- ? [context.environment.reviewSlug]
9167
+ ...(instance.type === "review" && !lecacyReviewImageName
9168
+ ? [instance.reviewSlug]
8864
9169
  : []),
8865
9170
  ];
8866
9171
  return (0, bash_1.joinBashExpressions)(gcloudImagePath, "/");
@@ -8910,7 +9215,7 @@ const getDeleteUnusedImagesCommands = (context, keep = 0) => {
8910
9215
  ...getDeleteImageCommands(buildCacheImageName, 1),
8911
9216
  // because a recent version of catladder had no review-slug in the image name, we have to delete those as well
8912
9217
  // we can later remove this line in some months
8913
- ...(context.environment.envType === "review"
9218
+ ...(context.environment.instance.type === "review"
8914
9219
  ? (0, gitlab_1.allowFailureInScripts)(getDeleteImageCommands((0, exports.getArtifactsRegistryImageName)(context, true), 0))
8915
9220
  : []),
8916
9221
  ];
@@ -8931,12 +9236,18 @@ const gitlab_1 = __nccwpck_require__(86962);
8931
9236
  const artifactsRegistry_1 = __nccwpck_require__(44330);
8932
9237
  const cloudRunRevisions_1 = __nccwpck_require__(55698);
8933
9238
  const getRemoveOldRevisionsAndImagesCommand = (context, when) => {
9239
+ var _a;
8934
9240
  if (when === "onStop") {
8935
9241
  // service is already deleted, so we don't need to delete old revisions, just delete all images
8936
9242
  return (0, artifactsRegistry_1.getDeleteUnusedImagesCommands)(context);
8937
9243
  }
8938
- // this number only targets inactive revisions
8939
- const revisionsToKeep = context.environment.envType === "prod" ? 5 : 0;
9244
+ const deployConfig = (_a = context.deploy) === null || _a === void 0 ? void 0 : _a.config;
9245
+ const configuredRevisionsToKeep = deployConfig && deployConfig.type === "google-cloudrun"
9246
+ ? deployConfig.revisionsToKeep
9247
+ : undefined;
9248
+ // this number only targets inactive revisions; the env type only
9249
+ // supplies the default (prod keeps a rollback history)
9250
+ const revisionsToKeep = configuredRevisionsToKeep !== null && configuredRevisionsToKeep !== void 0 ? configuredRevisionsToKeep : (context.environment.envType === "prod" ? 5 : 0);
8940
9251
  // this number needs to be higher than inactive after deploy, so we add one
8941
9252
  const imagesToKeep = revisionsToKeep + 1;
8942
9253
  const deleteOldRevisionsCommands = (0, cloudRunRevisions_1.getDeleteUnusedRevisionsCommands)(context, revisionsToKeep);
@@ -9843,7 +10154,7 @@ const cloudRunExecutionUrl_1 = __nccwpck_require__(49963);
9843
10154
  const database_1 = __nccwpck_require__(11595);
9844
10155
  const getServiceName_1 = __nccwpck_require__(33102);
9845
10156
  exports.GCLOUD_DEPLOY_CREDENTIALS_KEY = "GCLOUD_DEPLOY_credentialsKey";
9846
- const getCloudSqlVariables = ({ deployConfigRaw, environmentSlugPrefix, env, componentName, fullConfig, }) => {
10157
+ const getCloudSqlVariables = ({ deployConfigRaw, environmentSlugPrefix, secretsEnv, componentName, fullConfig, }) => {
9847
10158
  var _a, _b, _c;
9848
10159
  if (deployConfigRaw && deployConfigRaw.cloudSql) {
9849
10160
  const DB_NAME = (0, utils_1.getFullDbName)(deployConfigRaw.cloudSql, fullConfig, environmentSlugPrefix, componentName);
@@ -9854,7 +10165,7 @@ const getCloudSqlVariables = ({ deployConfigRaw, environmentSlugPrefix, env, com
9854
10165
  CLOUD_SQL_INSTANCE_CONNECTION_NAME: deployConfigRaw.cloudSql.instanceConnectionName,
9855
10166
  DB_NAME: DB_NAME,
9856
10167
  DB_USER: (_b = deployConfigRaw.cloudSql.dbUser) !== null && _b !== void 0 ? _b : "postgres",
9857
- DB_PASSWORD: "$" + (0, context_1.getSecretVarName)(env, componentName, "DB_PASSWORD"),
10168
+ DB_PASSWORD: "$" + (0, context_1.getSecretVarName)(secretsEnv, componentName, "DB_PASSWORD"),
9858
10169
  };
9859
10170
  return {
9860
10171
  ...dbVars,
@@ -10327,7 +10638,7 @@ const fromComponentContext = (context) => {
10327
10638
  environmentSlugPrefix: context.environment.slugPrefix,
10328
10639
  componentName: context.name,
10329
10640
  env: context.env,
10330
- isReviewEnv: context.environment.envType === "review",
10641
+ isReviewEnv: context.environment.instance.type === "review",
10331
10642
  deployConfig: deployConfig && deployConfig.type === "google-cloudrun"
10332
10643
  ? deployConfig
10333
10644
  : null,
@@ -10339,7 +10650,7 @@ const fromEnvironmentContext = (context) => ({
10339
10650
  environmentSlugPrefix: context.environmentSlugPrefix,
10340
10651
  componentName: context.componentName,
10341
10652
  env: context.env,
10342
- isReviewEnv: context.envType === "review",
10653
+ isReviewEnv: context.instance.type === "review",
10343
10654
  deployConfig: context.deployConfigRaw || null,
10344
10655
  config: context.fullConfig,
10345
10656
  });
@@ -10793,9 +11104,9 @@ exports.KUBERNETES_DEPLOY_TYPE = {
10793
11104
  jobs: deployJob_1.createKubernetesDeployJobs,
10794
11105
  defaults: () => ({}),
10795
11106
  additionalSecretKeys: additionalSecretKeys_1.additionalKubernetesSecretKeys,
10796
- getAdditionalEnvVars: ({ componentName, fullConfig, deployConfigRaw, env, reviewSlug, envType, }) => {
11107
+ getAdditionalEnvVars: ({ componentName, fullConfig, deployConfigRaw, env, instance, }) => {
10797
11108
  var _a;
10798
- const KUBE_APP_NAME_PREFIX = envType === "review" && reviewSlug ? reviewSlug.concat("-") : "";
11109
+ const KUBE_APP_NAME_PREFIX = instance.type === "review" ? instance.reviewSlug.concat("-") : "";
10799
11110
  const KUBE_APP_NAME = KUBE_APP_NAME_PREFIX.concat(componentName);
10800
11111
  const KUBE_NAMESPACE = (0, __1.getKubernetesNamespace)(fullConfig, env);
10801
11112
  const componentSlug = (0, slugify_1.default)(componentName);
@@ -10804,7 +11115,7 @@ exports.KUBERNETES_DEPLOY_TYPE = {
10804
11115
  "panter.cloud";
10805
11116
  const HOSTNAME_INTERNAL = (0, bash_1.joinBashExpressions)([
10806
11117
  componentSlug,
10807
- ...(envType === "review" && reviewSlug ? [reviewSlug] : []),
11118
+ ...(instance.type === "review" ? [instance.reviewSlug] : []),
10808
11119
  env,
10809
11120
  fullConfig.appName,
10810
11121
  fullConfig.customerName,
@@ -11162,7 +11473,8 @@ const createPagesDeployJobs = async (context) => {
11162
11473
  throw new Error("deploy config is not pages");
11163
11474
  }
11164
11475
  const onGithub = context.pipelineType === "github";
11165
- if (onGithub && context.environment.envType === "review") {
11476
+ const isReviewApp = context.environment.instance.type === "review";
11477
+ if (onGithub && isReviewApp) {
11166
11478
  // github pages serves ONE site per repository and deploy-pages
11167
11479
  // replaces all of it — there is no path_prefix equivalent, so per-PR
11168
11480
  // previews cannot exist (deploy-pages has a `preview` input, but it
@@ -11173,7 +11485,7 @@ const createPagesDeployJobs = async (context) => {
11173
11485
  }
11174
11486
  // review environments publish under their own path prefix (gitlab
11175
11487
  // parallel deployments) — every merge request gets a site preview
11176
- const pathPrefix = context.environment.envType === "review" ? "mr-$CI_MERGE_REQUEST_IID" : "";
11488
+ const pathPrefix = isReviewApp ? "mr-$CI_MERGE_REQUEST_IID" : "";
11177
11489
  const publishDir = (_b = deployConfig.publishDir) !== null && _b !== void 0 ? _b : "public";
11178
11490
  const packageManagerInstall = await (0, packageManagerInstall_1.getPackageManagerInstall)(context, {
11179
11491
  noCustomPostInstall: true,
@@ -12870,12 +13182,22 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
12870
13182
  "use strict";
12871
13183
 
12872
13184
  Object.defineProperty(exports, "__esModule", ({ value: true }));
12873
- exports.isKnowEnvType = exports.DEFAULT_ENV_TYPES = exports.DEFAULT_ENVS = exports.getEnvTypesByTrigger = exports.ENV_TYPES = exports.ALL_PIPELINE_TRIGGERS = void 0;
13185
+ exports.isKnowEnvType = exports.DEFAULT_ENV_TYPES = exports.DEFAULT_ENVS = exports.ENV_TYPES = exports.envTriggerEquals = exports.isBranchTrigger = exports.ALL_PIPELINE_TRIGGERS = void 0;
12874
13186
  exports.ALL_PIPELINE_TRIGGERS = [
12875
13187
  "mainBranch",
12876
13188
  "mr",
12877
13189
  "taggedRelease",
12878
13190
  ];
13191
+ const isBranchTrigger = (trigger) => typeof trigger === "object" && trigger !== null && "branch" in trigger;
13192
+ exports.isBranchTrigger = isBranchTrigger;
13193
+ const envTriggerEquals = (a, b) => {
13194
+ if (a === undefined || a === false)
13195
+ return false;
13196
+ if ((0, exports.isBranchTrigger)(b))
13197
+ return (0, exports.isBranchTrigger)(a) && a.branch === b.branch;
13198
+ return a === b;
13199
+ };
13200
+ exports.envTriggerEquals = envTriggerEquals;
12879
13201
  /**
12880
13202
  * all env types with their trigger.
12881
13203
  * Each env type has a default env with the same name which is always included
@@ -12897,15 +13219,6 @@ exports.ENV_TYPES = {
12897
13219
  triggers: [],
12898
13220
  },
12899
13221
  };
12900
- /**
12901
- *
12902
- * @param trigger a trigger
12903
- * @returns array of env types for that trigger. this is also the list of default envs
12904
- */
12905
- const getEnvTypesByTrigger = (trigger) => Object.entries(exports.ENV_TYPES)
12906
- .filter(([, e]) => e.triggers.includes(trigger))
12907
- .map(([e]) => e);
12908
- exports.getEnvTypesByTrigger = getEnvTypesByTrigger;
12909
13222
  exports.DEFAULT_ENVS = Object.keys(exports.ENV_TYPES);
12910
13223
  exports.DEFAULT_ENV_TYPES = exports.DEFAULT_ENVS;
12911
13224
  const isKnowEnvType = (env) => {