@catladder/cli 0.0.0-fix-materialize-binary-image-files-37469f1f → 0.0.0-fix-github-artifact-symlinks-3a2c1c28

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 (90) hide show
  1. package/dist/bundles/catenv/index.js +454 -60
  2. package/dist/bundles/catenv/xdg-open +0 -0
  3. package/dist/bundles/cli/clipboard_i686.exe +0 -0
  4. package/dist/bundles/cli/clipboard_x86_64.exe +0 -0
  5. package/dist/bundles/cli/index.js +454 -60
  6. package/dist/bundles/cli/xdg-open +0 -0
  7. package/dist/bundles/cli/xsel +0 -0
  8. package/dist/bundles/runner-images/changesets/scripts/changesetsRelease +0 -0
  9. package/dist/bundles/runner-images/kubernetes/scripts/kubernetesCreateSecret +0 -0
  10. package/dist/bundles/runner-images/kubernetes/scripts/kubernetesDelete +0 -0
  11. package/dist/bundles/runner-images/kubernetes/scripts/kubernetesDeploy +0 -0
  12. package/dist/bundles/runner-images/kubernetes/scripts/kubernetesRollback +0 -0
  13. package/dist/bundles/skills/catladder-builds/SKILL.md +54 -2
  14. package/dist/bundles/skills/catladder-builds/references/build-types.md +11 -2
  15. package/dist/bundles/skills/catladder-config/SKILL.md +18 -7
  16. package/dist/bundles/skills/catladder-pipelines/SKILL.md +39 -20
  17. package/dist/packages/pipeline/src/backends/github/artifactArchive.d.ts +22 -0
  18. package/dist/packages/pipeline/src/backends/github/artifactArchive.js +84 -0
  19. package/dist/packages/pipeline/src/backends/github/artifactArchive.js.map +1 -0
  20. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js +12 -29
  21. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js.map +1 -1
  22. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js +3 -1
  23. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
  24. package/dist/packages/pipeline/src/backends/gitlab/getPipelineStages.d.ts +4 -1
  25. package/dist/packages/pipeline/src/backends/gitlab/getPipelineStages.js +11 -2
  26. package/dist/packages/pipeline/src/backends/gitlab/getPipelineStages.js.map +1 -1
  27. package/dist/packages/pipeline/src/build/docker.d.ts +6 -0
  28. package/dist/packages/pipeline/src/build/docker.js +49 -2
  29. package/dist/packages/pipeline/src/build/docker.js.map +1 -1
  30. package/dist/packages/pipeline/src/build/types.d.ts +33 -3
  31. package/dist/packages/pipeline/src/build/types.js.map +1 -1
  32. package/dist/packages/pipeline/src/config/configruedEnvs.js +7 -1
  33. package/dist/packages/pipeline/src/config/configruedEnvs.js.map +1 -1
  34. package/dist/packages/pipeline/src/context/getEnvInherit.d.ts +2 -2
  35. package/dist/packages/pipeline/src/context/getEnvInherit.js +5 -2
  36. package/dist/packages/pipeline/src/context/getEnvInherit.js.map +1 -1
  37. package/dist/packages/pipeline/src/context/getEnvInstance.d.ts +2 -2
  38. package/dist/packages/pipeline/src/context/getEnvInstance.js.map +1 -1
  39. package/dist/packages/pipeline/src/context/getEnvOn.d.ts +2 -2
  40. package/dist/packages/pipeline/src/context/getEnvOn.js +1 -1
  41. package/dist/packages/pipeline/src/context/getEnvOn.js.map +1 -1
  42. package/dist/packages/pipeline/src/context/getEnvType.d.ts +3 -3
  43. package/dist/packages/pipeline/src/context/getEnvType.js +1 -1
  44. package/dist/packages/pipeline/src/context/getEnvType.js.map +1 -1
  45. package/dist/packages/pipeline/src/context/getEnvironmentContext.js +3 -2
  46. package/dist/packages/pipeline/src/context/getEnvironmentContext.js.map +1 -1
  47. package/dist/packages/pipeline/src/deploy/base/deploy.js +15 -9
  48. package/dist/packages/pipeline/src/deploy/base/deploy.js.map +1 -1
  49. package/dist/packages/pipeline/src/deploy/cloudRun/createJobs/execute/schedules.js +3 -1
  50. package/dist/packages/pipeline/src/deploy/cloudRun/createJobs/execute/schedules.js.map +1 -1
  51. package/dist/packages/pipeline/src/deploy/cloudRun/utils/cloudRunExecutionUrl.d.ts +1 -1
  52. package/dist/packages/pipeline/src/deploy/cloudRun/utils/cloudRunExecutionUrl.js +6 -1
  53. package/dist/packages/pipeline/src/deploy/cloudRun/utils/cloudRunExecutionUrl.js.map +1 -1
  54. package/dist/packages/pipeline/src/index.d.ts +1 -0
  55. package/dist/packages/pipeline/src/index.js +1 -0
  56. package/dist/packages/pipeline/src/index.js.map +1 -1
  57. package/dist/packages/pipeline/src/pipeline/createJobsForComponent.js +12 -2
  58. package/dist/packages/pipeline/src/pipeline/createJobsForComponent.js.map +1 -1
  59. package/dist/packages/pipeline/src/pipeline/createJobsForWorkspace.js +7 -2
  60. package/dist/packages/pipeline/src/pipeline/createJobsForWorkspace.js.map +1 -1
  61. package/dist/packages/pipeline/src/pipeline/packageManager.js +6 -3
  62. package/dist/packages/pipeline/src/pipeline/packageManager.js.map +1 -1
  63. package/dist/packages/pipeline/src/pipeline/resolveRequirements.js +1 -0
  64. package/dist/packages/pipeline/src/pipeline/resolveRequirements.js.map +1 -1
  65. package/dist/packages/pipeline/src/postBuildTest/createPostBuildTestJobs.d.ts +16 -0
  66. package/dist/packages/pipeline/src/postBuildTest/createPostBuildTestJobs.js +167 -0
  67. package/dist/packages/pipeline/src/postBuildTest/createPostBuildTestJobs.js.map +1 -0
  68. package/dist/packages/pipeline/src/postBuildTest/index.d.ts +2 -0
  69. package/dist/packages/pipeline/src/postBuildTest/index.js +19 -0
  70. package/dist/packages/pipeline/src/postBuildTest/index.js.map +1 -0
  71. package/dist/packages/pipeline/src/postBuildTest/types.d.ts +61 -0
  72. package/dist/packages/pipeline/src/postBuildTest/types.js +3 -0
  73. package/dist/packages/pipeline/src/postBuildTest/types.js.map +1 -0
  74. package/dist/packages/pipeline/src/types/config.d.ts +20 -2
  75. package/dist/packages/pipeline/src/types/config.js +9 -1
  76. package/dist/packages/pipeline/src/types/config.js.map +1 -1
  77. package/dist/packages/pipeline/src/types/jobs.d.ts +2 -2
  78. package/dist/packages/pipeline/src/types/jobs.js +1 -0
  79. package/dist/packages/pipeline/src/types/jobs.js.map +1 -1
  80. package/dist/runner-images/changesets/scripts/changesetsRelease +0 -0
  81. package/dist/runner-images/kubernetes/scripts/kubernetesCreateSecret +0 -0
  82. package/dist/runner-images/kubernetes/scripts/kubernetesDelete +0 -0
  83. package/dist/runner-images/kubernetes/scripts/kubernetesDeploy +0 -0
  84. package/dist/runner-images/kubernetes/scripts/kubernetesRollback +0 -0
  85. package/dist/skills/catladder-builds/SKILL.md +54 -2
  86. package/dist/skills/catladder-builds/references/build-types.md +11 -2
  87. package/dist/skills/catladder-config/SKILL.md +18 -7
  88. package/dist/skills/catladder-pipelines/SKILL.md +39 -20
  89. package/dist/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: catladder-builds
3
- description: Configuring how a component is built in a catladder project — the `build` config in catladder.ts (build types node / rails / meteor / custom, build & start commands, artifacts, caching, lint/test/audit jobs, the Docker image, project-declared job images, and shared workspace builds). Use when adding or changing a component's build, choosing a build type, wiring a Dockerfile/nginx image, declaring a custom CI job image (`images` config), tuning the build/test/lint jobs, or setting up a monorepo workspace build. Triggers on "build config", "buildCommand", "build type", "Dockerfile", "docker image", "job image", "jobImage", "custom image", "project image", "rails build", "monorepo build", "artifacts".
3
+ description: Configuring how a component is built in a catladder project — the `build` config in catladder.ts (build types node / rails / meteor / custom, build & start commands, artifacts, caching, lint/test/audit jobs, the Docker image, project-declared job images, and shared workspace builds). Use when adding or changing a component's build, choosing a build type, wiring a Dockerfile/nginx image, declaring a custom CI job image (`images` config), tuning the build/test/lint jobs, adding e2e tests against the build (`postBuildTests`), or setting up a monorepo workspace build. Triggers on "build config", "postBuildTests", "post-build test", "e2e", "playwright", "buildCommand", "build type", "Dockerfile", "docker image", "job image", "jobImage", "custom image", "project image", "rails build", "monorepo build", "artifacts".
4
4
  ---
5
5
 
6
6
  # Component builds with catladder
@@ -66,6 +66,10 @@ type: `build: { from: "web" }` (see workspace builds below).
66
66
  won't run).
67
67
  - `lint` / `test` / `audit` — customize (`{ command, jobImage, … }`) or
68
68
  set to `false` to disable that job.
69
+ - `postBuildTests` — named tests against the **build output** (e.g. an
70
+ e2e suite against the production build with a Postgres service). Each
71
+ entry becomes a job in the `post-build` stage between build and deploy
72
+ and blocks the deploy when it fails (see below).
69
73
  - `artifactsPaths` / `artifactsExcludePaths` — extra build artifacts
70
74
  (`dist` and `.next` are always included).
71
75
  - `cache` — build caching (see the `catladder-pipelines` skill for the
@@ -74,15 +78,63 @@ type: `build: { from: "web" }` (see workspace builds below).
74
78
  runner tags, build-only env vars, and extra runner variables. A
75
79
  `jobImage` is a concrete image url or `{ image: "<name>" }`
76
80
  referencing a project image (see below).
81
+ - `reuseMainBranchImage` — in release pipelines, stage/prod copy the
82
+ image the main branch (`dev`) built for the released commit instead of
83
+ rebuilding it (falls back to a build). Only for images that don't
84
+ depend on the env, e.g. Rails via Cloud Native Buildpacks.
77
85
  - `docker` — the image build strategy: a built-in
78
86
  (`{ type: "nginx" | "node" | "meteor" }`) or
79
87
  `{ type: "custom" }` (expects a `Dockerfile`).
80
88
 
89
+ ## Post-build tests (e2e against the build)
90
+
91
+ `lint`/`test` run against the sources, in parallel with the build. Tests
92
+ that need the built app go into `postBuildTests`:
93
+
94
+ ```ts
95
+ build: {
96
+ type: "node",
97
+ postBuildTests: {
98
+ e2e: {
99
+ command: "pnpm test:e2e", // runs in the build dir
100
+ jobImage: "mcr.microsoft.com/playwright:v1.56.0-noble",
101
+ services: [{ name: "postgres:17", alias: "postgres",
102
+ variables: { POSTGRES_PASSWORD: "postgres" } }],
103
+ vars: { DATABASE_URL: "postgres://postgres:postgres@postgres:5432/postgres" },
104
+ artifacts: { paths: ["apps/web/playwright-report"] }, // repo-root relative
105
+ },
106
+ },
107
+ }
108
+ ```
109
+
110
+ - The job (`🔬 e2e`, stage `post-build <env>`) downloads the build
111
+ artifacts (`.next`, `dist`, `artifactsPaths`), installs dependencies
112
+ for node builds, then runs `command`. The command starts the app
113
+ itself, e.g. playwright `webServer: { command: "pnpm start" }`.
114
+ Builds without artifacts (`rails`, `buildCommand: false`) just run
115
+ it after the build.
116
+ - It is a quality gate: the env's deploy waits for it; on github it is
117
+ part of the `catladder ✅` required check. `allowFailure: true` makes
118
+ it report-only.
119
+ - It gets the build vars plus `vars`, **not** the deployed env's
120
+ runtime vars/secrets — use services instead of the real database.
121
+ - Artifacts are uploaded also when the job fails.
122
+ - Not run in tagged releases. Disable one per env:
123
+ `env: { dev: { build: { postBuildTests: { e2e: false } } } }`.
124
+ - Names must not clash with other jobs of the component (e.g. `test`,
125
+ `lint`) — generation fails with a clear error.
126
+ - Workspace builds: on `builds.<ws>` they block the deploys of all
127
+ components in the workspace; on `build: { from: "<ws>", postBuildTests }`
128
+ only that component's deploy.
129
+ - To test the **deployed** env instead (smoke tests on dev / review
130
+ apps), use the component's `verify` (post-deploy, does not block the
131
+ deploy). The same suite can serve both, with `BASE_URL` as the switch.
132
+
81
133
  ## Project images (custom CI job images)
82
134
 
83
135
  When a job needs a toolchain catladder doesn't ship (Java, Playwright,
84
136
  …), declare a Docker image at the top level under `images` and reference
85
- it in any `jobImage` field (build, `test.jobImage`, custom/pages deploy,
137
+ it in any `jobImage` field (build, `test.jobImage`, `postBuildTests`, custom/pages deploy,
86
138
  verify):
87
139
 
88
140
  ```ts
@@ -12,6 +12,7 @@ generated pipeline files.
12
12
  | `startCommand` | `string` | runtime start command |
13
13
  | `postInstall` | `string \| string[]` | runs after the package-manager install (node family) |
14
14
  | `lint` / `test` / `audit` | `false \| TestJobCustom` | customize or disable the job |
15
+ | `postBuildTests` | `Record<string, PostBuildTestConfig \| false>` | named tests against the build output in the `post-build` stage; block the deploy |
15
16
  | `artifactsPaths` | `string[]` | extra artifacts (`dist`, `.next` always included) |
16
17
  | `artifactsExcludePaths` | `string[]` | artifact excludes |
17
18
  | `artifactsReports` | `{ junit?: string[] }` | CI test report paths |
@@ -20,12 +21,20 @@ generated pipeline files.
20
21
  | `runnerVariables` | `Record<string,string>` | extra runner vars (also for `services:`) |
21
22
  | `jobTags` | `string[]` | runner tags |
22
23
  | `jobImage` | `JobImageConfig` | CI image for the build: a concrete image or `{ image: "<name>" }` referencing a project image |
24
+ | `reuseMainBranchImage` | `boolean \| { releaseFiles?: string[] }` | release envs (stage/prod) copy the main branch (`dev`) image of the released commit instead of rebuilding; falls back to a build. Only for env-independent images; not for `google-cloudrun`. `true` = `{ releaseFiles: ["CHANGELOG.md"] }` |
23
25
  | `docker` | see below | the deployable image strategy |
24
26
 
25
27
  `TestJobCustom` (for `lint`/`test`/`audit`): `command`, `jobImage`,
26
28
  `artifactsReports`, `artifacts`, `runnerVariables`, `allowFailure`
27
29
  (`allowFailure` defaults to `true` for `audit`).
28
30
 
31
+ `PostBuildTestConfig` (for `postBuildTests` entries): `TestJobCustom` with
32
+ a required `command`, plus `services?: Services` (gitlab shape, reachable
33
+ by alias) and `vars?: Record<string,string>`. The job gets the build
34
+ artifacts, the build vars and `vars` (not the deployed env's runtime
35
+ vars), installs dependencies for node builds, and uploads `artifacts`
36
+ also on failure.
37
+
29
38
  `audit` additionally takes `level`: `"info" | "low" | "moderate" | "high" |
30
39
  "critical"` (default `"critical"`) — the lowest severity that fails the job,
31
40
  translated to the package manager's own flag (`pnpm audit --audit-level`,
@@ -80,5 +89,5 @@ defaulted `buildCommand: "yarn build-storybook --quiet -o ./dist"`.
80
89
  Top-level `builds: Record<string, WorkspaceBuildConfig>`. Only
81
90
  `type: "node"` is supported.
82
91
 
83
- - Node workspace build: `dir?`, `buildCommand?` (default `<pm> build`), `dockerDefaults?: { yarnRebuildEnabled }`, plus shared `lint?` (default `{ command: "<pm> lint" }`), `test?` (default `{ command: "<pm> test" }`), `audit?`, `runnerVariables?`, `artifactsReports?`, `jobImage?`, `jobTags?`, `cache?` (`<pm>` = `yarn`/`pnpm` per detection).
84
- - A component references it via `build: { from: "<name>", docker?, startCommand?, artifactsPaths?, artifactsExcludePaths?, cache? }` — the per-component overrides layer on top of the shared build.
92
+ - Node workspace build: `dir?`, `buildCommand?` (default `<pm> build`), `dockerDefaults?: { yarnRebuildEnabled }`, plus shared `lint?` (default `{ command: "<pm> lint" }`), `test?` (default `{ command: "<pm> test" }`), `audit?`, `postBuildTests?` (block the deploys of all its components), `runnerVariables?`, `artifactsReports?`, `jobImage?`, `jobTags?`, `cache?` (`<pm>` = `yarn`/`pnpm` per detection).
93
+ - A component references it via `build: { from: "<name>", docker?, startCommand?, artifactsPaths?, artifactsExcludePaths?, cache?, postBuildTests? }` — the per-component overrides layer on top of the shared build.
@@ -33,20 +33,23 @@ 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
36
+ environments: {
37
+ // optional: project-wide env declarations/tuning
37
38
  review: { autoStop: "3 days" },
39
+ stage: false, // the project has no stage env (any component)
38
40
  next: { type: "dev", on: { branch: "next" } }, // extra branch-tracking env
39
41
  },
40
42
  components: {
41
43
  www: {
42
- dir: "frontend", // working directory of this component
43
- vars: { public: {}, secret: [] }, // env vars (see catladder-secrets skill)
44
- build: { type: "node" }, // node | rails | meteor | custom — see catladder-builds
44
+ dir: "frontend", // working directory of this component
45
+ vars: { public: {}, secret: [] }, // env vars (see catladder-secrets skill)
46
+ build: { type: "node" }, // node | rails | meteor | custom — see catladder-builds
45
47
  deploy: { type: "kubernetes" }, // kubernetes | google-cloudrun | dockerTag | custom — see catladder-deploys
46
- env: { // enable/customize per environment
48
+ env: {
49
+ // enable/customize per environment
47
50
  review: {},
48
51
  dev: {},
49
- stage: false, // false disables the env for this component
52
+ stage: false, // false disables the env for this component only
50
53
  prod: {},
51
54
  },
52
55
  },
@@ -68,9 +71,17 @@ Key concepts:
68
71
  per-component `env.<name>` entries only carry component-local
69
72
  overrides (vars, deploy settings, host, autoStop) or `false` to opt
70
73
  the component out. In `environments`:
74
+ - `<name>: false` — disables the env for the whole project: no
75
+ component has it, so no setup contexts (`catladder project setup`),
76
+ secrets, pipeline jobs/workflows or catenv for it. This is how to
77
+ say "this project has no stage": `environments: { stage: false }`
78
+ (not `on: false`). `local` cannot be disabled; inheriting from a
79
+ disabled env is an error.
71
80
  - `on` — when the env deploys: `"mainBranch"`, `"mr"`,
72
81
  `"taggedRelease"`, `{ branch: "next" }` (a stable env deploying on
73
- pushes to that branch), or `false` (in no pipeline). `on: "mr"`
82
+ pushes to that branch), or `false` (never deployed by a pipeline —
83
+ the env still exists for setup, secrets and catenv; use
84
+ `environments.<name>: false` to remove it). `on: "mr"`
74
85
  makes an env a review app (one instance per MR/PR, torn down on
75
86
  close). Defaults from the env type.
76
87
  - `autoStop` — how long a stoppable environment stays up after its
@@ -11,12 +11,12 @@ generated YAML.
11
11
 
12
12
  ## Triggers and environments
13
13
 
14
- | Trigger | Runs on | Deploys to (default) |
15
- |---|---|---|
16
- | `mainBranch` | push to the main branch | `dev` |
17
- | `mr` | merge/pull requests | `review` (one app per MR/PR) |
18
- | `taggedRelease` | git tags | `stage`, `prod` |
19
- | `{ branch: "<name>" }` | push to that branch | envs declaring it via `on` |
14
+ | Trigger | Runs on | Deploys to (default) |
15
+ | ---------------------- | ----------------------- | ---------------------------- |
16
+ | `mainBranch` | push to the main branch | `dev` |
17
+ | `mr` | merge/pull requests | `review` (one app per MR/PR) |
18
+ | `taggedRelease` | git tags | `stage`, `prod` |
19
+ | `{ branch: "<name>" }` | push to that branch | envs declaring it via `on` |
20
20
 
21
21
  The trigger of each env is its `on` in the top-level `environments`
22
22
  config (project-wide — components cannot diverge), defaulting from the
@@ -25,6 +25,9 @@ own pipeline (gitlab: rules on `$CI_COMMIT_BRANCH`; github: a
25
25
  `catladder-branch-<name>.yml` workflow) and deploys as one stable,
26
26
  branch-tracking environment — unlike review apps, it is not
27
27
  per-instance and is stopped via the manual stop job/workflow.
28
+ `on: false` keeps an env out of every pipeline but the env still exists
29
+ (setup, secrets, catenv); `environments: { <name>: false }` removes it
30
+ entirely.
28
31
 
29
32
  Generated layout:
30
33
 
@@ -34,39 +37,40 @@ Generated layout:
34
37
  "generated by catladder" header; others are unmanaged). Manual
35
38
  actions are per-kind `workflow_dispatch` workflows, visually grouped
36
39
  by their emoji prefix in the Actions sidebar: `🚀 catladder create
37
- release`, `▶️ catladder deploy` (manual-gated deploys), `🛑 catladder
38
- stop`, `↩️ catladder rollback` — when all of a kind's tasks target one
40
+ release`, `▶️ catladder deploy` (manual-gated deploys), `🛑 catladder
41
+ stop`, `↩️ catladder rollback` — when all of a kind's tasks target one
39
42
  env the name carries it (e.g. `▶️ catladder deploy prod`); otherwise
40
43
  pick the task from the workflow's dropdown. Review apps are stopped
41
44
  automatically when their pull request closes (`🛑 catladder stop
42
- review app`); the same workflow can be dispatched with a PR number to
45
+ review app`); the same workflow can be dispatched with a PR number to
43
46
  tear one down while the pull request is still open (gitlab runs these as manual jobs inside the pipeline
44
47
  instead).
45
48
 
46
- Stages: setup → test → build → deploy → verify (post-deploy checks),
47
- plus stop jobs for review-app teardown.
49
+ Stages: setup → test → build → post-build (`postBuildTests` against
50
+ the build output, block the deploy) → deploy → verify (post-deploy
51
+ checks), plus stop jobs for review-app teardown.
48
52
 
49
53
  ## Superseded pipelines are cancelled
50
54
 
51
55
  Pushing a new commit cancels the pipeline of the previous one, so the
52
56
  runners are not busy with results nobody will read.
53
57
 
54
- | Pipeline | On a new commit |
55
- |---|---|
56
- | `mr` | cancelled |
57
- | `mainBranch` (dev) | cancelled, except a release already running |
58
- | `taggedRelease` | **runs through** — never cancelled |
59
- | agent runs (`trigger`) | **runs through** — never cancelled |
58
+ | Pipeline | On a new commit |
59
+ | ---------------------- | ------------------------------------------- |
60
+ | `mr` | cancelled |
61
+ | `mainBranch` (dev) | cancelled, except a release already running |
62
+ | `taggedRelease` | **runs through** — never cancelled |
63
+ | agent runs (`trigger`) | **runs through** — never cancelled |
60
64
 
61
65
  - **GitHub**: the generated MR workflow sets `concurrency` with
62
66
  `cancel-in-progress: true`.
63
67
  - **GitLab**: generated `workflow:auto_cancel:on_new_commit:
64
- interruptible`, with per-rule `none` for tags and agent runs. Every
68
+ interruptible`, with per-rule `none` for tags and agent runs. Every
65
69
  job carries an explicit `interruptible`, jobs that must finish
66
70
  (release jobs, agent jobs) carry `interruptible: false`.
67
71
 
68
72
  **GitLab requires the project setting too.** The generated YAML only
69
- tunes *how* redundant pipelines are cancelled — it does not switch the
73
+ tunes _how_ redundant pipelines are cancelled — it does not switch the
70
74
  feature on. If old pipelines keep running, check **Settings > CI/CD >
71
75
  General pipelines > Auto-cancel redundant pipelines**; with that
72
76
  checkbox off nothing is ever cancelled. (`catladder project-doctor`
@@ -74,7 +78,7 @@ does not check this.)
74
78
 
75
79
  **Adding a hand-written GitLab job?** Set `interruptible` explicitly.
76
80
  GitLab defaults it to `false`, and a non-interruptible job that has
77
- started keeps *itself* alive — under gitlab's own default
81
+ started keeps _itself_ alive — under gitlab's own default
78
82
  (`conservative`, which catladder overrides) it would shield the whole
79
83
  pipeline from cancellation.
80
84
 
@@ -148,6 +152,21 @@ pipelines: { github: { repository: "AcmeCorp/Nautilus" } },
148
152
  `yarn catladder project doctor` reports a mixed-case repository whose
149
153
  generated workflows still carry the expression.
150
154
 
155
+ ### Artifacts between jobs (GitHub)
156
+
157
+ A job's `artifacts.paths` are handed to the jobs that need them as one
158
+ tar archive (`catladder-artifacts-<job-id>.tar`): an "Archive
159
+ artifacts" step tars them after the job, `upload-artifact` uploads the
160
+ archive under the job id, and the consumers get a matching "Extract
161
+ artifacts" step after `download-artifact`. The tar keeps symlinks, file
162
+ modes and repo-relative paths, as GitLab artifacts do. Plain
163
+ `upload-artifact` loses them, which breaks Next.js/Turbopack builds in
164
+ pnpm workspaces: `.next/node_modules/<pkg>-<hash>` are symlinks into
165
+ the pnpm store, and as copied directories they fail at runtime with
166
+ `ERR_MODULE_NOT_FOUND`. If a deployed app shows that error, check that
167
+ the committed workflows contain the archive steps and regenerate if
168
+ they don't.
169
+
151
170
  ## Caching
152
171
 
153
172
  Cache configuration is generated per build type. **yarn** node builds