@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
@@ -13,6 +13,24 @@ import type { ProjectImageConfig } from "../customImages/projectImages";
13
13
  import type { VerifyConfig } from "../verify/types";
14
14
  export declare const ALL_PIPELINE_TRIGGERS: readonly ["mainBranch", "mr", "taggedRelease"];
15
15
  export type PipelineTrigger = (typeof ALL_PIPELINE_TRIGGERS)[number];
16
+ /**
17
+ * a pipeline that runs on pushes to one specific branch (in addition to
18
+ * the built-in triggers). Declared by an env via its `on` config.
19
+ */
20
+ export type BranchPipelineTrigger = {
21
+ branch: string;
22
+ };
23
+ /**
24
+ * everything a pipeline (and therefore an env's jobs) can run on
25
+ */
26
+ export type EnvPipelineTrigger = PipelineTrigger | BranchPipelineTrigger;
27
+ /**
28
+ * the `on` config of an env: a trigger, or `false` for an env that is
29
+ * not part of any pipeline (like `local`)
30
+ */
31
+ export type EnvOnConfig = EnvPipelineTrigger | false;
32
+ export declare const isBranchTrigger: (trigger: EnvPipelineTrigger) => trigger is BranchPipelineTrigger;
33
+ export declare const envTriggerEquals: (a: EnvOnConfig | undefined, b: EnvPipelineTrigger) => boolean;
16
34
  /**
17
35
  * all env types with their trigger.
18
36
  * Each env type has a default env with the same name which is always included
@@ -34,16 +52,10 @@ export declare const ENV_TYPES: {
34
52
  readonly triggers: readonly [];
35
53
  };
36
54
  };
37
- /**
38
- *
39
- * @param trigger a trigger
40
- * @returns array of env types for that trigger. this is also the list of default envs
41
- */
42
- export declare const getEnvTypesByTrigger: (trigger: PipelineTrigger) => ("stage" | "prod" | "local" | "dev" | "review")[];
43
55
  export declare const DEFAULT_ENVS: string[];
44
- export declare const DEFAULT_ENV_TYPES: ("stage" | "prod" | "local" | "dev" | "review")[];
56
+ export declare const DEFAULT_ENV_TYPES: ("stage" | "prod" | "local" | "review" | "dev")[];
45
57
  export type EnvType = keyof typeof ENV_TYPES;
46
- export declare const isKnowEnvType: (env: string) => env is "stage" | "prod" | "local" | "dev" | "review";
58
+ export declare const isKnowEnvType: (env: string) => env is "stage" | "prod" | "local" | "review" | "dev";
47
59
  export type EnvVars = {
48
60
  /**
49
61
  * public env vars (means: they are checked in the repo).
@@ -120,7 +132,100 @@ export type EnvConfig<E extends EnvType = EnvType> = {
120
132
  * host that is used. If not set, a "canonical" url is created
121
133
  */
122
134
  host?: string;
135
+ /**
136
+ * per-component override of the environment's autoStop (see
137
+ * {@link EnvironmentConfig.autoStop} — each component has its own
138
+ * gitlab environment, so the duration may differ per component)
139
+ */
140
+ autoStop?: string | false;
123
141
  } & PartialDeep<DefaultEnvConfig>;
142
+ /**
143
+ * project-wide declaration and tuning of an environment (the top-level
144
+ * `environments` config). Environments are a project-wide concept —
145
+ * every component deploys to a declared env unless it opts out with
146
+ * `env.<name>: false`. Anything that must be consistent across
147
+ * components (which envs exist, when they deploy) lives here; the
148
+ * per-component `env.<name>` entries only override component-local
149
+ * things (vars, deploy settings, host, autoStop).
150
+ */
151
+ export type EnvironmentConfig = {
152
+ /**
153
+ * the type of env this behaves like (dev, review, stage, prod) —
154
+ * think of it as a preset: it supplies all defaults (when the env
155
+ * deploys, autoStop, deploy policy like rollback history and manual
156
+ * prod deploys) and the env's identity for tooling (the `ENV_TYPE`
157
+ * env var / `env-type` label). Everything it implies can be
158
+ * overridden explicitly. Required for envs whose name is not itself
159
+ * an env type.
160
+ */
161
+ type?: EnvType;
162
+ /**
163
+ * when this env deploys. Defaults from the env type:
164
+ * - dev: "mainBranch" (pushes to the default branch)
165
+ * - review: "mr" (merge requests / pull requests; the env is created
166
+ * per MR and torn down when it closes)
167
+ * - stage / prod: "taggedRelease" (release tags)
168
+ * - local: false (not part of any pipeline)
169
+ *
170
+ * `{ branch: "next" }` deploys the env on pushes to that branch —
171
+ * one stable environment tracking a long-lived branch.
172
+ *
173
+ * `false` removes the env from all pipelines.
174
+ */
175
+ on?: EnvOnConfig;
176
+ /**
177
+ * how long the environment stays up after its last deployment before
178
+ * gitlab stops it automatically (gitlab `auto_stop_in`, e.g. "3 days").
179
+ * `false` disables auto-stopping. Defaults from the env type, tunable
180
+ * project-wide via the top-level `autoStop` durations: review
181
+ * "1 week", dev "4 weeks", everything else never.
182
+ *
183
+ * Only applies to stoppable deployments, and only on gitlab (github
184
+ * review apps stop when their pull request closes). Components can
185
+ * override it per env (`env.<name>.autoStop`).
186
+ *
187
+ * NOTE: an explicit value here is a literal — setting it on a review
188
+ * env opts that env out of the pin-label mechanism (the top-level
189
+ * `autoStop.pinLabel`), which only steers the default review lifetime.
190
+ */
191
+ autoStop?: string | false;
192
+ /**
193
+ * inherit from another environment (see {@link EnvironmentInheritConfig}):
194
+ *
195
+ * `inherit: "dev"` makes this env use dev's per-component config
196
+ * overrides AND dev's secret values. The object form controls the two
197
+ * axes separately.
198
+ */
199
+ inherit?: EnvironmentInheritConfig;
200
+ };
201
+ /**
202
+ * what an environment inherits from another environment.
203
+ *
204
+ * The string shorthand `inherit: "dev"` means
205
+ * `{ config: "dev", secrets: "dev" }`.
206
+ *
207
+ * - `config`: the named env's per-component overrides (`env.<name>` in
208
+ * each component — vars, deploy/build settings, autoStop) are merged
209
+ * in below this env's own overrides: component base → inherited env's
210
+ * overrides → own overrides. `host` and `type` are never inherited
211
+ * (a host must stay unique per env). The env's `type` defaults to the
212
+ * inherited env's type.
213
+ * - `secrets`: this env uses the named env's secret VALUES — all or
214
+ * nothing: its jobs reference the other env's secret variables
215
+ * (`CL_<OTHERENV>_...`) and it has no secret store of its own, so the
216
+ * secrets CLI manages them via the other env and rotating them
217
+ * affects both envs. Set to `false` (or omit in the object form) for
218
+ * own secrets.
219
+ *
220
+ * Inheriting from `local` is not possible, chains are followed, cycles
221
+ * are an error.
222
+ */
223
+ export type EnvironmentInheritConfig = string | {
224
+ /** env whose per-component config overrides are inherited */
225
+ config?: string;
226
+ /** env whose secret values are used (all-or-nothing); false = own secrets */
227
+ secrets?: string | false;
228
+ };
124
229
  export type EnvConfigWithComponent = EnvConfig<EnvType> & ComponentConfig;
125
230
  export type CustomEnv = EnvConfigWithOverride & {
126
231
  type: EnvType;
@@ -134,7 +239,7 @@ export type Env<C extends ConfigProps = never> = {
134
239
  stage?: EnvConfigWithOverride<"stage"> | false;
135
240
  review?: EnvConfigWithOverride<"review"> | false;
136
241
  prod?: EnvConfigWithOverride<"prod"> | false;
137
- } & Record<C["CustomEnvs"], CustomEnv> & Record<string, any>;
242
+ } & Partial<Record<C["CustomEnvs"], EnvConfigWithOverride | false>> & Record<string, any>;
138
243
  export type ComponentConfig<C extends ConfigProps = never> = {
139
244
  /**
140
245
  * specify environment configurations
@@ -315,6 +420,18 @@ export type Config<C extends ConfigProps = never> = {
315
420
  */
316
421
  images?: Record<string, ProjectImageConfig>;
317
422
  builds?: Record<string, WorkspaceBuildConfig>;
423
+ /**
424
+ * project-wide environment declarations and tuning. Environments are
425
+ * shared across all components, so everything that must be consistent
426
+ * between them (which envs exist, their type, when they deploy) is
427
+ * declared here — components only carry per-component overrides.
428
+ *
429
+ * - tune a default env: `environments: { review: { autoStop: "3 days" } }`
430
+ * - declare an extra env (every component deploys to it unless it
431
+ * opts out with `env.<name>: false`):
432
+ * `environments: { next: { type: "dev", on: { branch: "next" } } }`
433
+ */
434
+ environments?: Record<string, EnvironmentConfig>;
318
435
  /**
319
436
  * components (sub apps)
320
437
  */
@@ -1,11 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isKnowEnvType = exports.DEFAULT_ENV_TYPES = exports.DEFAULT_ENVS = exports.getEnvTypesByTrigger = exports.ENV_TYPES = exports.ALL_PIPELINE_TRIGGERS = void 0;
3
+ exports.isKnowEnvType = exports.DEFAULT_ENV_TYPES = exports.DEFAULT_ENVS = exports.ENV_TYPES = exports.envTriggerEquals = exports.isBranchTrigger = exports.ALL_PIPELINE_TRIGGERS = void 0;
4
4
  exports.ALL_PIPELINE_TRIGGERS = [
5
5
  "mainBranch",
6
6
  "mr",
7
7
  "taggedRelease",
8
8
  ];
9
+ const isBranchTrigger = (trigger) => typeof trigger === "object" && trigger !== null && "branch" in trigger;
10
+ exports.isBranchTrigger = isBranchTrigger;
11
+ const envTriggerEquals = (a, b) => {
12
+ if (a === undefined || a === false)
13
+ return false;
14
+ if ((0, exports.isBranchTrigger)(b))
15
+ return (0, exports.isBranchTrigger)(a) && a.branch === b.branch;
16
+ return a === b;
17
+ };
18
+ exports.envTriggerEquals = envTriggerEquals;
9
19
  /**
10
20
  * all env types with their trigger.
11
21
  * Each env type has a default env with the same name which is always included
@@ -27,15 +37,6 @@ exports.ENV_TYPES = {
27
37
  triggers: [],
28
38
  },
29
39
  };
30
- /**
31
- *
32
- * @param trigger a trigger
33
- * @returns array of env types for that trigger. this is also the list of default envs
34
- */
35
- const getEnvTypesByTrigger = (trigger) => Object.entries(exports.ENV_TYPES)
36
- .filter(([, e]) => e.triggers.includes(trigger))
37
- .map(([e]) => e);
38
- exports.getEnvTypesByTrigger = getEnvTypesByTrigger;
39
40
  exports.DEFAULT_ENVS = Object.keys(exports.ENV_TYPES);
40
41
  exports.DEFAULT_ENV_TYPES = exports.DEFAULT_ENVS;
41
42
  const isKnowEnvType = (env) => {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/types/config.ts"],"names":[],"mappings":";;;AAea,QAAA,qBAAqB,GAAG;IACnC,YAAY;IACZ,IAAI;IACJ,eAAe;CACP,CAAC;AAGX;;;GAGG;AACU,QAAA,SAAS,GAAG;IACvB,GAAG,EAAE;QACH,QAAQ,EAAE,CAAC,YAAY,CAAC;KACzB;IACD,MAAM,EAAE;QACN,QAAQ,EAAE,CAAC,IAAI,CAAC;KACjB;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,CAAC,eAAe,CAAC;KAC5B;IACD,IAAI,EAAE;QACJ,QAAQ,EAAE,CAAC,eAAe,CAAC;KAC5B;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,EAAE;KACb;CACO,CAAC;AAEX;;;;GAIG;AACI,MAAM,oBAAoB,GAAG,CAAC,OAAwB,EAAE,EAAE,CAC/D,MAAM,CAAC,OAAO,CAAC,iBAAS,CAAC;KACtB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CACf,CAAC,CAAC,QAAuC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAC7D;KACA,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAY,CAAC,CAAC;AALnB,QAAA,oBAAoB,wBAKD;AAEnB,QAAA,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAS,CAAC,CAAC;AACtC,QAAA,iBAAiB,GAAG,oBAAyB,CAAC;AAGpD,MAAM,aAAa,GAAG,CAAC,GAAW,EAAkB,EAAE;IAC3D,OAAO,GAAG,IAAI,iBAAS,CAAC;AAC1B,CAAC,CAAC;AAFW,QAAA,aAAa,iBAExB"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/types/config.ts"],"names":[],"mappings":";;;AAea,QAAA,qBAAqB,GAAG;IACnC,YAAY;IACZ,IAAI;IACJ,eAAe;CACP,CAAC;AAoBJ,MAAM,eAAe,GAAG,CAC7B,OAA2B,EACO,EAAE,CACpC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,QAAQ,IAAI,OAAO,CAAC;AAH5D,QAAA,eAAe,mBAG6C;AAElE,MAAM,gBAAgB,GAAG,CAC9B,CAA0B,EAC1B,CAAqB,EACZ,EAAE;IACX,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACjD,IAAI,IAAA,uBAAe,EAAC,CAAC,CAAC;QAAE,OAAO,IAAA,uBAAe,EAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC;IAC3E,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC,CAAC;AAPW,QAAA,gBAAgB,oBAO3B;AAEF;;;GAGG;AACU,QAAA,SAAS,GAAG;IACvB,GAAG,EAAE;QACH,QAAQ,EAAE,CAAC,YAAY,CAAC;KACzB;IACD,MAAM,EAAE;QACN,QAAQ,EAAE,CAAC,IAAI,CAAC;KACjB;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,CAAC,eAAe,CAAC;KAC5B;IACD,IAAI,EAAE;QACJ,QAAQ,EAAE,CAAC,eAAe,CAAC;KAC5B;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,EAAE;KACb;CACO,CAAC;AAEE,QAAA,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAS,CAAC,CAAC;AACtC,QAAA,iBAAiB,GAAG,oBAAyB,CAAC;AAGpD,MAAM,aAAa,GAAG,CAAC,GAAW,EAAkB,EAAE;IAC3D,OAAO,GAAG,IAAI,iBAAS,CAAC;AAC1B,CAAC,CAAC;AAFW,QAAA,aAAa,iBAExB"}
@@ -3,7 +3,8 @@ import type { BuildConfigFromWorkspace, BuildConfigStandalone, WorkspaceBuildCon
3
3
  import type { PredefinedVariables, SecretEnvVar } from "../context";
4
4
  import type { DeployConfig } from "../deploy";
5
5
  import type { VariableValue } from "../../../bash/src/index.js";
6
- import type { ComponentConfig, Config, EnvType, PipelineTrigger } from "./config";
6
+ import type { ComponentConfig, Config, EnvPipelineTrigger, EnvType } from "./config";
7
+ import type { EnvironmentInstance } from "./environmentContext";
7
8
  import type { BaseStage, CatladderJob, CatladderJobSpec } from "./jobs";
8
9
  import type { PipelineType } from "./pipeline";
9
10
  export type UnspecifiedEnvVars = Record<string, VariableValue | undefined | null>;
@@ -29,8 +30,14 @@ export type Environment = {
29
30
  * the environment slug without component name.
30
31
  */
31
32
  slugPrefix: StringOrBashExpression;
33
+ /**
34
+ * how the env is instantiated — `instance.type === "review"` is the
35
+ * way to find out whether this is a review app
36
+ */
37
+ instance: EnvironmentInstance;
32
38
  /**
33
39
  * the review slug, if it is a review app, null otherwise
40
+ * @deprecated use `instance` — the review variant carries the slug
34
41
  */
35
42
  reviewSlug: StringOrBashExpression | null;
36
43
  /**
@@ -38,6 +45,18 @@ export type Environment = {
38
45
  */
39
46
  slug: StringOrBashExpression;
40
47
  envType: EnvType;
48
+ /**
49
+ * the resolved `autoStop` config (component override, then the
50
+ * project-wide environment config — see {@link EnvironmentConfig.autoStop});
51
+ * undefined means the env type's default applies
52
+ */
53
+ autoStop?: string | false;
54
+ /**
55
+ * the env whose secret values this env uses — the env itself unless
56
+ * it shares another env's secrets via `inherit`. All secret variable
57
+ * names are built with this env.
58
+ */
59
+ secretsEnv: string;
41
60
  } & EnvironmentEnvVarPart;
42
61
  export type YarnWorkspace = {
43
62
  name: string;
@@ -136,7 +155,7 @@ export type ComponentContext<BC extends BuildContextComponent = BuildContextComp
136
155
  deploy?: DeployContext | null;
137
156
  fullConfig: Config;
138
157
  environment: Environment;
139
- trigger?: PipelineTrigger;
158
+ trigger?: EnvPipelineTrigger;
140
159
  pipelineType?: PipelineType;
141
160
  packageManagerInfo: Promise<PackageManagerInfoComponent>;
142
161
  customJobs?: CatladderJobSpec[];
@@ -159,7 +178,7 @@ export type WorkspaceContext = {
159
178
  packageManagerInfo: Promise<PackageManagerInfoBase>;
160
179
  components: Array<ComponentContext>;
161
180
  build: BuildContextWorkspace;
162
- trigger: PipelineTrigger;
181
+ trigger: EnvPipelineTrigger;
163
182
  pipelineType: PipelineType;
164
183
  env: string;
165
184
  };
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/types/context.ts"],"names":[],"mappings":";;;AAiNO,MAAM,iCAAiC,GAAG,CAC/C,OAAgD,EACK,EAAE;IACvD,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC;AAC7C,CAAC,CAAC;AAJW,QAAA,iCAAiC,qCAI5C;AAEK,MAAM,iCAAiC,GAAG,CAC/C,OAAgD,EACQ,EAAE;IAC1D,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC;AAChD,CAAC,CAAC;AAJW,QAAA,iCAAiC,qCAI5C"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/types/context.ts"],"names":[],"mappings":";;;AAsOO,MAAM,iCAAiC,GAAG,CAC/C,OAAgD,EACK,EAAE;IACvD,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC;AAC7C,CAAC,CAAC;AAJW,QAAA,iCAAiC,qCAI5C;AAEK,MAAM,iCAAiC,GAAG,CAC/C,OAAgD,EACQ,EAAE;IAC1D,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,eAAe,CAAC;AAChD,CAAC,CAAC;AAJW,QAAA,iCAAiC,qCAI5C"}
@@ -3,20 +3,49 @@ import type { BuildConfig } from "../build";
3
3
  import type { DeployConfig } from "../deploy";
4
4
  import type { Config, EnvConfigWithComponent, EnvType } from "./config";
5
5
  import type { PipelineType } from "./pipeline";
6
+ /**
7
+ * how an environment is instantiated:
8
+ * - "stable": one long-lived instance (dev, stage, prod, branch envs)
9
+ * - "review": one instance per merge/pull request (`on: "mr"`),
10
+ * addressed by the runtime review slug (mr<iid> / pr<number>)
11
+ */
12
+ export type EnvironmentInstance = {
13
+ type: "stable";
14
+ } | {
15
+ type: "review";
16
+ reviewSlug: StringOrBashExpression;
17
+ };
6
18
  export type EnvironmentContext<B extends BuildConfig = BuildConfig, D extends DeployConfig = DeployConfig> = {
7
19
  envConfigRaw: EnvConfigWithComponent;
8
20
  buildConfigRaw: false | B;
9
21
  deployConfigRaw: false | D;
10
22
  env: string;
11
23
  envType: EnvType;
24
+ /**
25
+ * the resolved autoStop config (component override, then project-wide
26
+ * environment config); undefined means the env type's default applies
27
+ */
28
+ autoStop?: string | false;
29
+ /**
30
+ * the env whose secret values this env uses — the env itself unless
31
+ * it shares another env's secrets via `inherit`. All secret variable
32
+ * names are built with this env.
33
+ */
34
+ secretsEnv: string;
12
35
  componentName: string;
13
36
  fullName: StringOrBashExpression;
14
37
  /**
15
38
  * the environment slug without component name.
16
39
  */
17
40
  environmentSlugPrefix: StringOrBashExpression;
41
+ /**
42
+ * how the env is instantiated — `instance.type === "review"` is the
43
+ * way to find out whether this is a review app
44
+ */
45
+ instance: EnvironmentInstance;
18
46
  /**
19
47
  * the review slug, if it is a review app, null otherwise
48
+ * @deprecated use `instance` — the review variant carries the slug
20
49
  */
21
50
  reviewSlug: StringOrBashExpression | null;
22
51
  /**
@@ -33,6 +33,10 @@ const config = {
33
33
  appName: "my-app",
34
34
  customerName: "pan",
35
35
  pipelines: { gitlab: true, github: true }, // which CI systems to generate
36
+ environments: { // optional: project-wide env declarations/tuning
37
+ review: { autoStop: "3 days" },
38
+ next: { type: "dev", on: { branch: "next" } }, // extra branch-tracking env
39
+ },
36
40
  components: {
37
41
  www: {
38
42
  dir: "frontend", // working directory of this component
@@ -59,8 +63,36 @@ Key concepts:
59
63
  - **Environments**: `dev` (deployed on push to the main branch),
60
64
  `review` (per merge/pull request), `stage` and `prod` (deployed on
61
65
  tagged releases), `local` (only for local development via catenv).
62
- Per-env overrides live under `env.<name>` and can override vars,
63
- deploy settings, and more.
66
+ Environments are project-wide: the top-level `environments` config
67
+ declares and tunes them consistently for all components, while
68
+ per-component `env.<name>` entries only carry component-local
69
+ overrides (vars, deploy settings, host, autoStop) or `false` to opt
70
+ the component out. In `environments`:
71
+ - `on` — when the env deploys: `"mainBranch"`, `"mr"`,
72
+ `"taggedRelease"`, `{ branch: "next" }` (a stable env deploying on
73
+ pushes to that branch), or `false` (in no pipeline). `on: "mr"`
74
+ makes an env a review app (one instance per MR/PR, torn down on
75
+ close). Defaults from the env type.
76
+ - `autoStop` — how long a stoppable environment stays up after its
77
+ last deploy before gitlab stops it (e.g. `"3 days"`; `false`
78
+ disables). Defaults: review `"1 week"`, dev `"4 weeks"`, others
79
+ never. GitLab only — github review apps stop when their PR closes.
80
+ Components can override it per env (`env.<name>.autoStop`).
81
+ - Extra envs are declared with any name plus a `type` — the env type
82
+ acts as a preset: it supplies all defaults (trigger, autoStop,
83
+ deploy policy) and the env's identity for tooling (`ENV_TYPE`),
84
+ everything overridable. Every component deploys to a declared env
85
+ unless it opts out:
86
+ `environments: { next: { type: "dev", on: { branch: "next" } } }`.
87
+ - `inherit` — make an env inherit from another env:
88
+ `inherit: "dev"` gives it dev's per-component config overrides
89
+ (merged below its own; `host` and `type` never inherit, the env
90
+ type is implied from the inherited env) AND dev's secret values —
91
+ all-or-nothing: its jobs reference dev's `CL_DEV_*` variables and
92
+ it has no secret store of its own (manage secrets via dev; rotating
93
+ affects both). The object form separates the axes:
94
+ `inherit: { config: "dev" }` inherits config only,
95
+ `inherit: { config: "dev", secrets: "dev" }` both.
64
96
  - **Pipelines**: `pipelines: { gitlab: true, github: true }` selects
65
97
  which CI systems get generated files. Options objects instead of
66
98
  `true` allow per-pipeline settings (e.g. `runnerVariables`,
@@ -78,6 +78,11 @@ Everything app-level lives under `values`:
78
78
  completion jobs, and always-on background worker pools.
79
79
  - `cloudSql` — attach an (unmanaged) CloudSQL instance; choose the
80
80
  connection-string format (`prisma` default, `rails`, `jdbc`).
81
+ `deleteDatabaseOnStop` controls whether the database is dropped when
82
+ the environment stops (default: true for review envs, false else).
83
+ - `revisionsToKeep` — how many inactive revisions (the rollback
84
+ history) the post-deploy cleanup keeps; older revisions and their
85
+ images are deleted. Default: 5 on prod envs, 0 everywhere else.
81
86
  - `execute` — run a script/job/HTTP call at a deploy lifecycle point
82
87
  (`preDeploy`/`postDeploy`/`preStop`/`postStop`) or on a `schedule`.
83
88
  Prefer this over the deprecated `when`/`schedule` fields on `jobs`.
@@ -119,7 +124,14 @@ publishes `publishDir` (default `"public"`). Review environments
119
124
  automatically publish under an `mr-<iid>` path prefix — every merge
120
125
  request gets its own site preview (the prefix is exposed to the build
121
126
  as `$PAGES_PREFIX`). The gitlab environment url points at the
122
- published site. GitLab-only for now.
127
+ published site.
128
+
129
+ **MR previews need GitLab Premium/Ultimate** (parallel deployments /
130
+ `pages.path_prefix`). On GitLab CE/Free the prefix is ignored and the
131
+ review job publishes to the site root, silently overwriting the main
132
+ site — on such instances set `env: { review: false }` on the pages
133
+ component. Ask which tier the instance runs when unsure (a self-hosted
134
+ `git.<company>` instance is often CE).
123
135
 
124
136
  ```ts
125
137
  docs: {
@@ -65,7 +65,7 @@ resources with `yarn catladder project setup`; detect drift with
65
65
  - `publishDir?: string` — output directory relative to the repo root, default `"public"`.
66
66
  - `requiresInstall?: boolean` — run the package-manager install (yarn/pnpm) first (`requiresYarnInstall` is a deprecated alias).
67
67
  - `jobImage?: GitlabJobImage`; also accepts `cache`.
68
- - Review envs publish under an `mr-<iid>` path prefix (parallel deployments → MR previews; exposed as `$PAGES_PREFIX`); other envs publish at the root. The environment url is the published pages url.
68
+ - Review envs publish under an `mr-<iid>` path prefix (parallel deployments → MR previews; exposed as `$PAGES_PREFIX`); other envs publish at the root. Parallel deployments are GitLab Premium/Ultimate — on CE/Free the prefix is ignored and a review deploy overwrites the main site, so set `env: { review: false }` there. The environment url is the published pages url.
69
69
  - Defaults to `allowFailure: true`.
70
70
 
71
71
  ## `dockerTag`
@@ -184,9 +184,10 @@ changesets — see the `catladder-config` skill.
184
184
  pending bump = next release `vA.B.C`*. If that is not what the user
185
185
  expects, the bump levels are wrong.
186
186
  - The merge request now runs the **`🦋 changeset check`** job. It should
187
- report the pending changesets and that same version. A yellow check
188
- only means "this MR adds no changeset" — for the migration MR itself
189
- that is not the case, so expect it green.
187
+ report the pending changesets and that same version. A "⚠️ adds no
188
+ changeset" warning in the report only means "this MR adds no
189
+ changeset" — for the migration MR itself that is not the case, so
190
+ expect it to list the backfilled changesets.
190
191
  - Do **not** hand-write `CHANGELOG.md`. The release job prepends the new
191
192
  section; anything you write by hand there gets duplicated.
192
193
  - Leave any `.releaserc` / `release.config.js` alone if the project has
@@ -11,11 +11,20 @@ generated YAML.
11
11
 
12
12
  ## Triggers and environments
13
13
 
14
- | Trigger | Runs on | Deploys to |
14
+ | Trigger | Runs on | Deploys to (default) |
15
15
  |---|---|---|
16
16
  | `mainBranch` | push to the main branch | `dev` |
17
17
  | `mr` | merge/pull requests | `review` (one app per MR/PR) |
18
18
  | `taggedRelease` | git tags | `stage`, `prod` |
19
+ | `{ branch: "<name>" }` | push to that branch | envs declaring it via `on` |
20
+
21
+ The trigger of each env is its `on` in the top-level `environments`
22
+ config (project-wide — components cannot diverge), defaulting from the
23
+ env type as in the table. An env with `on: { branch: "next" }` gets its
24
+ own pipeline (gitlab: rules on `$CI_COMMIT_BRANCH`; github: a
25
+ `catladder-branch-<name>.yml` workflow) and deploys as one stable,
26
+ branch-tracking environment — unlike review apps, it is not
27
+ per-instance and is stopped via the manual stop job/workflow.
19
28
 
20
29
  Generated layout:
21
30
 
@@ -96,18 +96,23 @@ Changesets projects get a **`🦋 changeset check`** job in every
96
96
  merge-request pipeline. It reports what merging would do — the
97
97
  changesets this MR adds, everything pending, and the version the next
98
98
  release would get (with a changelog preview) — and **warns without
99
- blocking** (`allow_failure`) when the MR adds no changeset:
99
+ blocking** when the MR adds no changeset. The job itself stays green on
100
+ both platforms: the warning lives in the report, the job log and the
101
+ sticky comment.
100
102
 
101
103
  - **GitLab**: report in the job log and as an exposed artifact
102
104
  (`changeset-report.md`) in the MR widget. If the project makes
103
105
  `GL_TOKEN` available to MR pipelines it also maintains a sticky MR
104
106
  comment (opt-in — an api-scope token in MR pipelines is a security
105
- trade-off).
106
- - **GitHub**: maintains a sticky PR comment via the workflow token; the
107
- job stays green and reports a warning annotation (github has no
108
- yellow job state, and a red job would read like a real failure).
109
-
110
- A yellow changeset-check job on an MR is a prompt to ask: is this
107
+ trade-off). The job deliberately does not turn yellow: gitlab only
108
+ resolves exposed artifacts of successful jobs, so a failed
109
+ `allow_failure` job leaves the MR widget spinning on "Loading
110
+ artifacts".
111
+ - **GitHub**: maintains a sticky PR comment via the workflow token and
112
+ reports a warning annotation (github has no yellow job state, and a
113
+ red job would read like a real failure).
114
+
115
+ A "⚠️ adds no changeset" report on an MR is a prompt to ask: is this
111
116
  change user-facing? If yes, add a changeset; if not, ignore it.
112
117
 
113
118
  ## The security-audit gate
@@ -38,6 +38,12 @@ files in the repo. All secrets commands accept a **scope**:
38
38
  `dev:web` (one env of one component), `dev:` (one env, all
39
39
  components), `:web` (all envs of one component), or nothing (everything).
40
40
 
41
+ An env that shares another env's secrets (top-level
42
+ `environments.<name>.inherit`, e.g. a `next` branch env inheriting from
43
+ dev) has **no secret store of its own** — its jobs reference the source
44
+ env's variables directly, so it never appears in secrets scopes: manage
45
+ (and rotate) the values via the source env, which affects both.
46
+
41
47
  Check what is declared and what is still unset (never prints values
42
48
  unless `--reveal` is passed):
43
49