@catladder/cli 0.0.0-next-d71e41ba → 0.0.0-next-dccc0a36

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 (91) hide show
  1. package/dist/apps/cli/src/scripts/generateCliSkillReference.js +3 -2
  2. package/dist/apps/cli/src/scripts/generateCliSkillReference.js.map +1 -1
  3. package/dist/bundles/catenv/index.js +790 -272
  4. package/dist/bundles/cli/index.js +790 -272
  5. package/dist/bundles/runner-images/docker-build/scripts/ensureNodeDockerfile +8 -1
  6. package/dist/bundles/runner-images/jobs-default/Dockerfile +4 -0
  7. package/dist/bundles/skills/catladder-builds/SKILL.md +68 -5
  8. package/dist/bundles/skills/catladder-builds/references/build-types.md +8 -6
  9. package/dist/bundles/skills/catladder-cli/references/commands.md +3 -2
  10. package/dist/bundles/skills/catladder-config/SKILL.md +5 -0
  11. package/dist/bundles/skills/catladder-deploys/SKILL.md +1 -1
  12. package/dist/bundles/skills/catladder-deploys/references/deploy-types.md +2 -2
  13. package/dist/bundles/skills/catladder-pipelines/SKILL.md +16 -4
  14. package/dist/packages/pipeline/src/backends/github/GithubBackend.js +4 -4
  15. package/dist/packages/pipeline/src/backends/github/GithubBackend.js.map +1 -1
  16. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js +4 -4
  17. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
  18. package/dist/packages/pipeline/src/build/base/createAppBuildJob.js +2 -2
  19. package/dist/packages/pipeline/src/build/base/createAppBuildJob.js.map +1 -1
  20. package/dist/packages/pipeline/src/build/index.d.ts +3 -3
  21. package/dist/packages/pipeline/src/build/index.js +16 -11
  22. package/dist/packages/pipeline/src/build/index.js.map +1 -1
  23. package/dist/packages/pipeline/src/build/node/buildJob.js +49 -8
  24. package/dist/packages/pipeline/src/build/node/buildJob.js.map +1 -1
  25. package/dist/packages/pipeline/src/build/node/cache.d.ts +5 -0
  26. package/dist/packages/pipeline/src/build/node/cache.js +58 -19
  27. package/dist/packages/pipeline/src/build/node/cache.js.map +1 -1
  28. package/dist/packages/pipeline/src/build/node/meteor.js +9 -4
  29. package/dist/packages/pipeline/src/build/node/meteor.js.map +1 -1
  30. package/dist/packages/pipeline/src/build/node/packageManagerInstall.d.ts +14 -0
  31. package/dist/packages/pipeline/src/build/node/packageManagerInstall.js +145 -0
  32. package/dist/packages/pipeline/src/build/node/packageManagerInstall.js.map +1 -0
  33. package/dist/packages/pipeline/src/build/node/testJob.js +9 -11
  34. package/dist/packages/pipeline/src/build/node/testJob.js.map +1 -1
  35. package/dist/packages/pipeline/src/build/types.d.ts +6 -5
  36. package/dist/packages/pipeline/src/build/types.js.map +1 -1
  37. package/dist/packages/pipeline/src/context/createComponentContext.js +3 -2
  38. package/dist/packages/pipeline/src/context/createComponentContext.js.map +1 -1
  39. package/dist/packages/pipeline/src/context/createWorkspaceContext.js +3 -2
  40. package/dist/packages/pipeline/src/context/createWorkspaceContext.js.map +1 -1
  41. package/dist/packages/pipeline/src/customImages/hash.d.ts +9 -0
  42. package/dist/packages/pipeline/src/customImages/hash.js +41 -16
  43. package/dist/packages/pipeline/src/customImages/hash.js.map +1 -1
  44. package/dist/packages/pipeline/src/customImages/jobImagesPlan.d.ts +23 -5
  45. package/dist/packages/pipeline/src/customImages/jobImagesPlan.js +177 -43
  46. package/dist/packages/pipeline/src/customImages/jobImagesPlan.js.map +1 -1
  47. package/dist/packages/pipeline/src/customImages/projectImages.d.ts +67 -0
  48. package/dist/packages/pipeline/src/customImages/projectImages.js +9 -0
  49. package/dist/packages/pipeline/src/customImages/projectImages.js.map +1 -0
  50. package/dist/packages/pipeline/src/deploy/custom/deployJob.js +7 -6
  51. package/dist/packages/pipeline/src/deploy/custom/deployJob.js.map +1 -1
  52. package/dist/packages/pipeline/src/deploy/pages/deployJob.js +6 -4
  53. package/dist/packages/pipeline/src/deploy/pages/deployJob.js.map +1 -1
  54. package/dist/packages/pipeline/src/deploy/types/custom.d.ts +9 -3
  55. package/dist/packages/pipeline/src/deploy/types/index.d.ts +4 -4
  56. package/dist/packages/pipeline/src/deploy/types/pages.d.ts +9 -3
  57. package/dist/packages/pipeline/src/index.d.ts +2 -0
  58. package/dist/packages/pipeline/src/index.js +2 -0
  59. package/dist/packages/pipeline/src/index.js.map +1 -1
  60. package/dist/packages/pipeline/src/pipeline/detectPackageManager.d.ts +18 -0
  61. package/dist/packages/pipeline/src/pipeline/detectPackageManager.js +76 -0
  62. package/dist/packages/pipeline/src/pipeline/detectPackageManager.js.map +1 -0
  63. package/dist/packages/pipeline/src/pipeline/packageManager.d.ts +1 -1
  64. package/dist/packages/pipeline/src/pipeline/packageManager.js +43 -9
  65. package/dist/packages/pipeline/src/pipeline/packageManager.js.map +1 -1
  66. package/dist/packages/pipeline/src/pipeline/pnpm/pnpmUtils.d.ts +14 -0
  67. package/dist/packages/pipeline/src/pipeline/pnpm/pnpmUtils.js +93 -0
  68. package/dist/packages/pipeline/src/pipeline/pnpm/pnpmUtils.js.map +1 -0
  69. package/dist/packages/pipeline/src/types/config.d.ts +16 -1
  70. package/dist/packages/pipeline/src/types/config.js.map +1 -1
  71. package/dist/packages/pipeline/src/types/context.d.ts +11 -3
  72. package/dist/packages/pipeline/src/types/context.js.map +1 -1
  73. package/dist/packages/pipeline/src/types/jobs.d.ts +2 -1
  74. package/dist/packages/pipeline/src/types/jobs.js.map +1 -1
  75. package/dist/packages/pipeline/src/verify/createVerifyJobs.js +5 -5
  76. package/dist/packages/pipeline/src/verify/createVerifyJobs.js.map +1 -1
  77. package/dist/runner-images/docker-build/scripts/ensureNodeDockerfile +8 -1
  78. package/dist/runner-images/jobs-default/Dockerfile +4 -0
  79. package/dist/skills/catladder-builds/SKILL.md +68 -5
  80. package/dist/skills/catladder-builds/references/build-types.md +8 -6
  81. package/dist/skills/catladder-cli/references/commands.md +3 -2
  82. package/dist/skills/catladder-config/SKILL.md +5 -0
  83. package/dist/skills/catladder-deploys/SKILL.md +1 -1
  84. package/dist/skills/catladder-deploys/references/deploy-types.md +2 -2
  85. package/dist/skills/catladder-pipelines/SKILL.md +16 -4
  86. package/dist/tsconfig.tsbuildinfo +1 -1
  87. package/package.json +1 -1
  88. package/src/scripts/generateCliSkillReference.ts +3 -2
  89. package/dist/packages/pipeline/src/build/node/yarn.d.ts +0 -8
  90. package/dist/packages/pipeline/src/build/node/yarn.js +0 -78
  91. package/dist/packages/pipeline/src/build/node/yarn.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import type { BuildConfig } from "../build/types";
2
2
  import type { DeployConfig } from "../deploy/types";
3
3
  import type { CatladderJobSpec } from "./jobs";
4
- import type { ComponentContext } from "./context";
4
+ import type { ComponentContext, PackageManagerType } from "./context";
5
5
  import type { PartialDeep } from "./utils";
6
6
  import type { PipelineType, WorkspaceBuildConfig } from "..";
7
7
  import type { AgentConfig } from "./agent";
@@ -9,6 +9,7 @@ import type { Hooks } from "./hooks";
9
9
  import type { ReleaseConfig } from "./release";
10
10
  import type { CatladderStore } from "../store";
11
11
  import type { AgentSkillsConfig } from "../agentSkills/types";
12
+ import type { ProjectImageConfig } from "../customImages/projectImages";
12
13
  import type { VerifyConfig } from "../verify/types";
13
14
  export declare const ALL_PIPELINE_TRIGGERS: readonly ["mainBranch", "mr", "taggedRelease"];
14
15
  export type PipelineTrigger = (typeof ALL_PIPELINE_TRIGGERS)[number];
@@ -255,6 +256,13 @@ export type Config<C extends ConfigProps = never> = {
255
256
  * how secrets are stored and shared (see {@link SecretsConfig})
256
257
  */
257
258
  secrets?: SecretsConfig;
259
+ /**
260
+ * which package manager the project uses. Usually not needed:
261
+ * catladder autodetects it from the `packageManager` field in
262
+ * package.json or the lockfile present (pnpm-lock.yaml / yarn.lock),
263
+ * falling back to yarn. Set it to override the detection.
264
+ */
265
+ packageManager?: PackageManagerType;
258
266
  /**
259
267
  * materialize the agent skills shipped with catladder (usage guides
260
268
  * for AI coding agents like Claude Code) into the repository, so
@@ -287,6 +295,13 @@ export type Config<C extends ConfigProps = never> = {
287
295
  */
288
296
  domainCanonical?: string;
289
297
  agents?: Record<string, AgentConfig>;
298
+ /**
299
+ * docker images declared by the project, built automatically in the
300
+ * pipeline: content-hashed into the project's own registry and only
301
+ * rebuilt when their inputs change. Reference them in any `jobImage`
302
+ * field via `{ image: "<key>" }`.
303
+ */
304
+ images?: Record<string, ProjectImageConfig>;
290
305
  builds?: Record<string, WorkspaceBuildConfig>;
291
306
  /**
292
307
  * components (sub apps)
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/types/config.ts"],"names":[],"mappings":";;;AAca,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;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"}
@@ -45,23 +45,31 @@ export type YarnWorkspace = {
45
45
  workspaceDependencies: string[];
46
46
  mismatchedWorkspaceDependencies: string[];
47
47
  };
48
+ export type PackageManagerType = "yarn" | "pnpm";
48
49
  export type YarnPackageManagerInfoBase = {
49
50
  type: "yarn";
50
51
  version: string;
51
52
  workspaces: YarnWorkspace[];
52
53
  isClassic: boolean;
53
54
  };
54
- export type YarnPackageManagerInfoComponent = YarnPackageManagerInfoBase & {
55
+ export type PnpmPackageManagerInfoBase = {
56
+ type: "pnpm";
57
+ version: string;
58
+ workspaces: YarnWorkspace[];
59
+ };
60
+ type PackageManagerInfoComponentPart = {
55
61
  currentWorkspace?: YarnWorkspace;
56
62
  componentIsInWorkspace: boolean;
57
63
  pathsToCopyInDocker: string[];
58
64
  currentWorkspaceDependencies: string[];
59
65
  };
60
- export type PackageManagerInfoComponent = YarnPackageManagerInfoComponent;
66
+ export type YarnPackageManagerInfoComponent = YarnPackageManagerInfoBase & PackageManagerInfoComponentPart;
67
+ export type PnpmPackageManagerInfoComponent = PnpmPackageManagerInfoBase & PackageManagerInfoComponentPart;
68
+ export type PackageManagerInfoComponent = YarnPackageManagerInfoComponent | PnpmPackageManagerInfoComponent;
61
69
  /**
62
70
  * not confuse with yarn workspaces
63
71
  */
64
- export type PackageManagerInfoBase = YarnPackageManagerInfoBase;
72
+ export type PackageManagerInfoBase = YarnPackageManagerInfoBase | PnpmPackageManagerInfoBase;
65
73
  export type ContextBeforeConfig = {
66
74
  componentName: string;
67
75
  fullConfig: Config;
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/types/context.ts"],"names":[],"mappings":";;;AA8LO,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":";;;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,5 +1,6 @@
1
1
  import type { UnspecifiedEnvVars } from "..";
2
2
  import type { CatladderImageRef } from "../runner";
3
+ import type { ProjectImageRef } from "../customImages/projectImages";
3
4
  import type { CacheConfig } from "../build/types";
4
5
  import type { Artifacts, GitlabJobCache, GitlabJobDef, GitlabJobImage, GitlabRule } from "./gitlab-types";
5
6
  export type CatladderJobCache = GitlabJobCache & {
@@ -186,7 +187,7 @@ export type GitlabJobFields = {
186
187
  * catladder-provided job image (resolved by the backend to an image
187
188
  * built in the repository's own registry)
188
189
  */
189
- image?: GitlabJobImage | CatladderImageRef;
190
+ image?: GitlabJobImage | CatladderImageRef | ProjectImageRef;
190
191
  /**
191
192
  * whether failures are allowed
192
193
  */
@@ -1 +1 @@
1
- {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/types/jobs.ts"],"names":[],"mappings":";;;AAGA,8DAA2D;AAsB9C,QAAA,WAAW,GAAG;IACzB,OAAO;IACP,MAAM;IACN,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,MAAM;CACE,CAAC;AAWE,QAAA,YAAY,GAAG;IAC1B,OAAO;IACP,gBAAgB;IAChB,aAAa;IACb,aAAa;IACb,YAAY;CACJ,CAAC;AA6NX;;;;;;;GAOG;AACH,4JAA4J;AAC5J,MAAa,YAAY;IACvB,YAAY,IAAyB;QACnC,uDAAuD;QACvD,2DAA2D;QAC3D,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAA,iCAAe,EAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,IAAI,CACT,GAAkD;QAElD,OAAO,GAAG,YAAY,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;IACnE,CAAC;CACF;AAZD,oCAYC"}
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/types/jobs.ts"],"names":[],"mappings":";;;AAIA,8DAA2D;AAsB9C,QAAA,WAAW,GAAG;IACzB,OAAO;IACP,MAAM;IACN,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,MAAM;CACE,CAAC;AAWE,QAAA,YAAY,GAAG;IAC1B,OAAO;IACP,gBAAgB;IAChB,aAAa;IACb,aAAa;IACb,YAAY;CACJ,CAAC;AA6NX;;;;;;;GAOG;AACH,4JAA4J;AAC5J,MAAa,YAAY;IACvB,YAAY,IAAyB;QACnC,uDAAuD;QACvD,2DAA2D;QAC3D,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAA,iCAAe,EAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,IAAI,CACT,GAAkD;QAElD,OAAO,GAAG,YAAY,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;IACnE,CAAC;CACF;AAZD,oCAYC"}
@@ -4,7 +4,7 @@ exports.createVerifyJobs = exports.VERIFY_JOB_NAME = void 0;
4
4
  const createArtifactsConfig_1 = require("../build/base/createArtifactsConfig");
5
5
  const cache_1 = require("../build/node/cache");
6
6
  const constants_1 = require("../build/node/constants");
7
- const yarn_1 = require("../build/node/yarn");
7
+ const packageManagerInstall_1 = require("../build/node/packageManagerInstall");
8
8
  const deploy_1 = require("../deploy");
9
9
  const runner_1 = require("../runner");
10
10
  const utils_1 = require("../utils");
@@ -21,9 +21,9 @@ const createVerifyJobs = async (context) => {
21
21
  return [];
22
22
  }
23
23
  const isNodeBuild = context.build.type !== "disabled" && context.build.buildType === "node";
24
- const [yarnInstall, nodeCache] = isNodeBuild
24
+ const [packageManagerInstall, nodeCache] = isNodeBuild
25
25
  ? await Promise.all([
26
- (0, yarn_1.getYarnInstall)(context),
26
+ (0, packageManagerInstall_1.getPackageManagerInstall)(context),
27
27
  (0, cache_1.getNodeCache)(context, "pull"),
28
28
  ])
29
29
  : [null, null];
@@ -59,9 +59,9 @@ const createVerifyJobs = async (context) => {
59
59
  },
60
60
  script: [
61
61
  ...setupScript,
62
- ...(yarnInstall ? (0, yarn_1.ensureNodeVersion)(context) : []),
62
+ ...(packageManagerInstall ? (0, packageManagerInstall_1.ensureNodeVersion)(context) : []),
63
63
  `cd ${context.build.dir}`,
64
- ...(yarnInstall !== null && yarnInstall !== void 0 ? yarnInstall : []),
64
+ ...(packageManagerInstall !== null && packageManagerInstall !== void 0 ? packageManagerInstall : []),
65
65
  ...(0, utils_1.ensureArray)(verifyConfig.command),
66
66
  ],
67
67
  allow_failure: verifyConfig.allowFailure,
@@ -1 +1 @@
1
- {"version":3,"file":"createVerifyJobs.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/verify/createVerifyJobs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createVerifyJobs.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/verify/createVerifyJobs.ts"],"names":[],"mappings":";;;AAAA,+EAA4E;AAC5E,+CAAmD;AACnD,uDAAsE;AACtE,+EAG6C;AAC7C,sCAAyC;AACzC,sCAA2C;AAG3C,oCAAuC;AAE1B,QAAA,eAAe,GAAG,WAAW,CAAC;AAEpC,MAAM,gBAAgB,GAAG,KAAK,EACnC,OAAyB,EACA,EAAE;;IAC3B,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC;IACpD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,YAAY,GAAG,MAAA,OAAO,CAAC,MAAM,0CAAE,MAAM,CAAC;IAC5C,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,qDAAqD;QACrD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,WAAW,GACf,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC;IAE1E,MAAM,CAAC,qBAAqB,EAAE,SAAS,CAAC,GAAG,WAAW;QACpD,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,IAAA,gDAAwB,EAAC,OAAO,CAAC;YACjC,IAAA,oBAAY,EAAC,OAAO,EAAE,MAAM,CAAC;SAC9B,CAAC;QACJ,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAEjB,MAAM,WAAW,GACf,MAAA,MAAA,MAAA,qBAAY,CAAC,YAAY,CAAC,IAAI,CAAC,EAAC,oBAAoB,mDAAG,OAAO,CAAC,mCAAI,EAAE,CAAC;IAExE,OAAO;QACL;YACE,IAAI,EAAE,uBAAe;YACrB,KAAK,EAAE,QAAQ;YACf,OAAO,EAAE,aAAa;YACtB,QAAQ,EAAE;gBACR,uCAAuC;gBACvC,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE;gBAC9C,6DAA6D;gBAC7D,GAAG,CAAC,MAAA,YAAY,CAAC,OAAO,mCAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;oBACtD,UAAU,EAAE,YAAqB;oBACjC,IAAI,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE;oBAClC,SAAS,EAAE,KAAK;oBAChB,MAAM,EAAE,IAAI;iBACb,CAAC,CAAC;aACJ;YACD,KAAK,EAAE,MAAA,YAAY,CAAC,QAAQ,mCAAI,IAAA,uBAAc,EAAC,qBAAqB,CAAC;YACrE,+DAA+D;YAC/D,gEAAgE;YAChE,kEAAkE;YAClE,iEAAiE;YACjE,MAAM,EAAE,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,SAAS;YAC9B,SAAS,EAAE;gBACT,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO;aAC/B;YACD,eAAe,EAAE;gBACf,GAAG,uCAA2B;gBAC9B,GAAG,CAAC,MAAA,YAAY,CAAC,eAAe,mCAAI,EAAE,CAAC;aACxC;YACD,MAAM,EAAE;gBACN,GAAG,WAAW;gBACd,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAA,yCAAiB,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE;gBACzB,GAAG,CAAC,qBAAqB,aAArB,qBAAqB,cAArB,qBAAqB,GAAI,EAAE,CAAC;gBAChC,GAAG,IAAA,mBAAW,EAAC,YAAY,CAAC,OAAO,CAAC;aACrC;YACD,aAAa,EAAE,YAAY,CAAC,YAAY;YACxC,GAAG,IAAA,6CAAqB,EACtB,OAAO,CAAC,KAAK,CAAC,GAAG,EACjB,YAAY,CAAC,gBAAgB,EAC7B,YAAY,CAAC,SAAS,CACvB;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAvEW,QAAA,gBAAgB,oBAuE3B"}
@@ -35,10 +35,17 @@ FROM node:$NODE_VERSION-alpine
35
35
  $DOCKERFILE_ADDITIONS
36
36
 
37
37
  RUN apk add --no-cache git curl
38
- USER node
38
+ # package-manager setup (e.g. installing pnpm globally) and the
39
+ # workspace-file copy run as root: pnpm ADDs a tar whose extracted
40
+ # parent dirs come out root-owned (ADD --chown only covers the files),
41
+ # so it needs a root chown before the node user can write node_modules.
42
+ # The actual install below still runs as the unprivileged node user.
43
+ $DOCKER_SETUP_PACKAGE_MANAGER
39
44
 
40
45
  $DOCKER_COPY_WORKSPACE_FILES
41
46
 
47
+ USER node
48
+
42
49
  WORKDIR /app/$APP_DIR
43
50
 
44
51
  $DOCKER_COPY_AND_INSTALL_APP
@@ -9,6 +9,10 @@ RUN rm /bin/sh && \
9
9
  # set high timeout for yarn, see https://github.com/dhis2/notes/issues/29
10
10
  RUN yarn config set network-timeout 600000 -g
11
11
 
12
+ # pnpm for projects using it (pnpm self-switches to the version pinned
13
+ # in the project's packageManager field)
14
+ RUN npm install -g pnpm
15
+
12
16
  # install nvm && some common node versions
13
17
  RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash && \
14
18
  source /root/.nvm/nvm.sh && \
@@ -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, and shared workspace builds). Use when adding or changing a component's build, choosing a build type, wiring a Dockerfile/nginx image, tuning the build/test/lint jobs, or setting up a monorepo workspace build. Triggers on "build config", "buildCommand", "build type", "Dockerfile", "docker 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, 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".
4
4
  ---
5
5
 
6
6
  # Component builds with catladder
@@ -28,11 +28,26 @@ components: {
28
28
  Set `build: false` to disable building for a component (e.g. a
29
29
  deploy-only or docker-tag component).
30
30
 
31
+ Node-family builds work with **yarn or pnpm**: catladder autodetects the
32
+ package manager (from the `packageManager` field in package.json or the
33
+ lockfile) and generates the matching install commands, caches and
34
+ default build/lint/test commands. Override with `packageManager:
35
+ "pnpm" | "yarn"` at the top level of `catladder.ts` if needed. The
36
+ `meteor` build type is yarn-only.
37
+
38
+ pnpm gotchas: dependency build scripts must be approved in
39
+ pnpm-workspace.yaml (`allowBuilds` map since pnpm 11,
40
+ `onlyBuiltDependencies` list on pnpm 10); pnpm runs the root
41
+ `prepare` script even during the production install in the docker
42
+ build — guard husky with `"prepare": "husky || true"`; `pnpm run`
43
+ prints a banner to stdout, so use `pnpm --silent run` in piped
44
+ commands.
45
+
31
46
  ## Build types
32
47
 
33
48
  | Type | Use for | Notes |
34
49
  |---|---|---|
35
- | `node` | Node/JS apps (Next.js, Vite, plain node) | default `yarn build` + `yarn start`; `docker` selects the runtime image |
50
+ | `node` | Node/JS apps (Next.js, Vite, plain node) | default `<pm> build` + `<pm> start` (yarn or pnpm, autodetected); `docker` selects the runtime image |
36
51
  | `rails` | Ruby on Rails apps | Cloud Native Buildpacks when there is no `Dockerfile`; Postgres test DB |
37
52
  | `meteor` | Meteor apps | starts `node main.js` |
38
53
  | `custom` | anything else | you provide the `jobImage` and `docker` config (both required) |
@@ -46,8 +61,9 @@ type: `build: { from: "web" }` (see workspace builds below).
46
61
  - `buildCommand` — the build step (`string | string[] | null | false`;
47
62
  `false`/`null` skips building).
48
63
  - `startCommand` — how the app is started at runtime.
49
- - `postInstall` — commands run after `yarn install` (node family; needed
50
- e.g. for Yarn PnP where `package.json` postinstall won't run).
64
+ - `postInstall` — commands run after the package-manager install (node
65
+ family; needed e.g. for Yarn PnP where `package.json` postinstall
66
+ won't run).
51
67
  - `lint` / `test` / `audit` — customize (`{ command, jobImage, … }`) or
52
68
  set to `false` to disable that job.
53
69
  - `artifactsPaths` / `artifactsExcludePaths` — extra build artifacts
@@ -55,11 +71,58 @@ type: `build: { from: "web" }` (see workspace builds below).
55
71
  - `cache` — build caching (see the `catladder-pipelines` skill for the
56
72
  caching model).
57
73
  - `jobImage`, `jobTags`, `jobVars`, `runnerVariables` — the CI image,
58
- runner tags, build-only env vars, and extra runner variables.
74
+ runner tags, build-only env vars, and extra runner variables. A
75
+ `jobImage` is a concrete image url or `{ image: "<name>" }`
76
+ referencing a project image (see below).
59
77
  - `docker` — the image build strategy: a built-in
60
78
  (`{ type: "nginx" | "node" | "meteor" }`) or
61
79
  `{ type: "custom" }` (expects a `Dockerfile`).
62
80
 
81
+ ## Project images (custom CI job images)
82
+
83
+ When a job needs a toolchain catladder doesn't ship (Java, Playwright,
84
+ …), declare a Docker image at the top level under `images` and reference
85
+ it in any `jobImage` field (build, `test.jobImage`, custom/pages deploy,
86
+ verify):
87
+
88
+ ```ts
89
+ images: {
90
+ // (a) a directory in the repo (default context = the dir)
91
+ "java-build": {
92
+ dir: "docker/java-build", // contains the Dockerfile
93
+ buildArgs: { MAVEN_VERSION: "3.9.9" }, // optional, part of the content hash
94
+ hashExtraPaths: ["shared/settings.xml"], // optional extra hashed+watched files
95
+ },
96
+ // (b) inline (default context = repo root); materialized into
97
+ // .catladder-generated/images/project/<name>/Dockerfile
98
+ "db-tools": {
99
+ dockerfile: ["FROM alpine:3.21", "RUN apk add --no-cache postgresql17-client"],
100
+ },
101
+ },
102
+ components: {
103
+ api: {
104
+ build: { type: "custom", jobImage: { image: "java-build" }, docker: { type: "custom" } },
105
+ },
106
+ }
107
+ ```
108
+
109
+ `dir` and `dockerfile` are mutually exclusive. `context` overrides the
110
+ build context (relative to the repo root) — needed when the image
111
+ `COPY`s files from outside its `dir`.
112
+
113
+ Catladder generates a `🐳 image <name>` job (setup stage) that builds
114
+ the image content-hashed into the project registry
115
+ (`…/job-images/<name>:<hash>`) and skips when it already exists — works
116
+ on GitLab and GitHub.
117
+
118
+ **The build context is not hashed** (it can be the whole repo) — only
119
+ the Dockerfile / `dir`, `buildArgs` and `hashExtraPaths` are. Files
120
+ pulled in via `COPY` that should trigger a rebuild belong in
121
+ `hashExtraPaths`.
122
+
123
+ Generation (`yarn catenv`) fails fast on an undeclared image name, a
124
+ missing `dir`, or a `dir` without a `Dockerfile`.
125
+
63
126
  ## Workspace builds (monorepos)
64
127
 
65
128
  For a shared build across several components, declare it once at the top
@@ -10,7 +10,7 @@ generated pipeline files.
10
10
  |---|---|---|
11
11
  | `buildCommand` | `string \| string[] \| null \| false` | build step; `false`/`null` skips it |
12
12
  | `startCommand` | `string` | runtime start command |
13
- | `postInstall` | `string \| string[]` | runs after `yarn install` (node family) |
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
15
  | `artifactsPaths` | `string[]` | extra artifacts (`dist`, `.next` always included) |
16
16
  | `artifactsExcludePaths` | `string[]` | artifact excludes |
@@ -19,7 +19,7 @@ generated pipeline files.
19
19
  | `jobVars` | `EnvVars` | env vars only in build jobs |
20
20
  | `runnerVariables` | `Record<string,string>` | extra runner vars (also for `services:`) |
21
21
  | `jobTags` | `string[]` | runner tags |
22
- | `jobImage` | `GitlabJobImage` | custom CI image for the build |
22
+ | `jobImage` | `JobImageConfig` | CI image for the build: a concrete image or `{ image: "<name>" }` referencing a project image |
23
23
  | `docker` | see below | the deployable image strategy |
24
24
 
25
25
  `TestJobCustom` (for `lint`/`test`/`audit`): `command`, `jobImage`,
@@ -29,8 +29,9 @@ generated pipeline files.
29
29
  ## Per-type options & defaults
30
30
 
31
31
  ### `node`
32
- - `docker?` — built-in node image `{ type: "node", yarnRebuildEnabled?: boolean (default true), additionsBegin?: string[], additionsEnd?: string[] }`, or a custom docker config.
33
- - Defaults: `buildCommand: "yarn build"`, `startCommand: "yarn start"`, artifacts `["dist", ".next"]`, excludes `[".next/cache/**/*"]`.
32
+ - Works with yarn **and pnpm** — the package manager is autodetected (`packageManager` field / lockfile), overridable via top-level `packageManager: "pnpm" | "yarn"` in `catladder.ts`.
33
+ - `docker?` — built-in node image `{ type: "node", yarnRebuildEnabled?: boolean (default true, yarn berry only), additionsBegin?: string[], additionsEnd?: string[] }`, or a custom docker config.
34
+ - Defaults: `buildCommand: "<pm> build"`, `startCommand: "<pm> start"` (`yarn`/`pnpm` per detection), artifacts `["dist", ".next"]`, excludes `[".next/cache/**/*"]`.
34
35
 
35
36
  ### `rails`
36
37
  - `test?.databaseImage?` — test DB container image (Postgres only; default `docker.io/postgres:latest`).
@@ -41,12 +42,13 @@ generated pipeline files.
41
42
  - `buildVars?: Record<string, string | undefined>` — Bundler / Rails asset-precompile vars (`undefined` inherits from the component's env vars).
42
43
 
43
44
  ### `meteor`
45
+ - Yarn-only (meteor's bundler is yarn-based) — a pnpm project cannot use this build type.
44
46
  - `installScripts?: boolean` — run `yarn install` inside the source folder in the image (only needed with custom image scripts).
45
47
  - `docker?` — meteor built-in or custom. Default `startCommand: "node main.js"`.
46
48
 
47
49
  ### `custom`
48
50
  - `type: "custom"` — **required**.
49
- - `jobImage: GitlabJobImage` — **required** CI image.
51
+ - `jobImage: JobImageConfig` — **required** CI image (concrete image or `{ image: "<name>" }` project-image ref).
50
52
  - `docker: BuildConfigDocker` — **required** image build config.
51
53
  - `jobServices?: Services` — services for lint/test/audit/build jobs.
52
54
  - `lint?` / `test?` / `audit?: TestJobCustom` — disabled unless set.
@@ -68,5 +70,5 @@ defaulted `buildCommand: "yarn build-storybook --quiet -o ./dist"`.
68
70
  Top-level `builds: Record<string, WorkspaceBuildConfig>`. Only
69
71
  `type: "node"` is supported.
70
72
 
71
- - Node workspace build: `dir?`, `buildCommand?` (default `yarn build`), `dockerDefaults?: { yarnRebuildEnabled }`, plus shared `lint?` (default `{ command: "yarn lint" }`), `test?` (default `{ command: "yarn test" }`), `audit?`, `runnerVariables?`, `artifactsReports?`, `jobImage?`, `jobTags?`, `cache?`.
73
+ - 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).
72
74
  - A component references it via `build: { from: "<name>", docker?, startCommand?, artifactsPaths?, artifactsExcludePaths?, cache? }` — the per-component overrides layer on top of the shared build.
@@ -3,8 +3,9 @@
3
3
  <!-- rendered from the command definitions by
4
4
  apps/cli/src/scripts/generateCliSkillReference.ts — do not edit -->
5
5
 
6
- All commands run non-interactively as `yarn catladder <command> ...`;
7
- see SKILL.md for how to pass inputs.
6
+ All commands run non-interactively as `yarn catladder <command> ...`
7
+ (`pnpm catladder ...` in pnpm projects); see SKILL.md for how to
8
+ pass inputs.
8
9
 
9
10
  ## `catladder cloudsql restore-db`
10
11
 
@@ -64,6 +64,11 @@ Key concepts:
64
64
  - **Pipelines**: `pipelines: { gitlab: true, github: true }` selects
65
65
  which CI systems get generated files. Options objects instead of
66
66
  `true` allow per-pipeline settings (e.g. `runnerVariables`).
67
+ - **Package manager**: yarn and pnpm are supported and autodetected
68
+ (from the `packageManager` field in package.json or the lockfile;
69
+ yarn is the fallback). `packageManager: "pnpm" | "yarn"` at the top
70
+ level overrides the detection. In pnpm projects, run the CLIs as
71
+ `pnpm catenv` / `pnpm catladder`.
67
72
 
68
73
  ## Common tasks
69
74
 
@@ -121,7 +121,7 @@ docs: {
121
121
  build: false,
122
122
  deploy: {
123
123
  type: "pages",
124
- requiresYarnInstall: true,
124
+ requiresInstall: true,
125
125
  script: ["yarn workspace docs build"],
126
126
  },
127
127
  },
@@ -61,7 +61,7 @@ resources with `yarn catladder project setup`; detect drift with
61
61
  - `type: "pages"` — **required**. Publishes a static site on gitlab pages (not yet supported on the github backend).
62
62
  - `script: string[]` — **required**; produces the site.
63
63
  - `publishDir?: string` — output directory relative to the repo root, default `"public"`.
64
- - `requiresYarnInstall?: boolean` — run `yarn install` first.
64
+ - `requiresInstall?: boolean` — run the package-manager install (yarn/pnpm) first (`requiresYarnInstall` is a deprecated alias).
65
65
  - `jobImage?: GitlabJobImage`; also accepts `cache`.
66
66
  - 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.
67
67
  - Defaults to `allowFailure: true`.
@@ -75,7 +75,7 @@ resources with `yarn catladder project setup`; detect drift with
75
75
  - `type: "custom"` — **required**.
76
76
  - `requiresDocker: boolean` — **required**; whether the deploy needs a built Docker image.
77
77
  - `script: string[]` — **required**; the deploy script.
78
- - `requiresYarnInstall?: boolean` — whether the script needs `yarn install`.
78
+ - `requiresInstall?: boolean` — whether the script needs the package-manager install (`requiresYarnInstall` is a deprecated alias).
79
79
  - `stopScript?: string[]` — script to stop/tear down the environment.
80
80
  - `jobImage?: GitlabJobImage`.
81
81
  - Also accepts `cache` (via `WithCacheConfig`).
@@ -29,17 +29,29 @@ plus stop jobs for review-app teardown.
29
29
 
30
30
  ## Job images and catci
31
31
 
32
- Jobs run in catladder-provided images. Their definitions are
33
- materialized into `.catladder-generated/images/` and built in the
34
- project's own registry (content-hashed, rebuilt only on change).
32
+ Jobs run in catladder-provided images (`🐳 catladder image <name>` build
33
+ jobs). Their definitions are materialized into
34
+ `.catladder-generated/images/` and built in the project's own registry
35
+ under `catladder/` (content-hashed, rebuilt only on change).
35
36
  `.catladder-generated/catci/` holds a small bundled CI companion used by
36
37
  generated jobs (e.g. the release security audit) — all generated, never
37
38
  edit.
38
39
 
40
+ Projects can declare their own job images under `images` in
41
+ `catladder.ts` (`🐳 image <name>` build jobs, pushed to `job-images/` in
42
+ the registry) and reference them in any `jobImage` field via
43
+ `{ image: "<name>" }` — see the `catladder-builds` skill. A declared
44
+ Dockerfile directory is used in place; an inline `dockerfile` is
45
+ materialized into `.catladder-generated/images/project/<name>/`. Either
46
+ way the build job is skipped when the content hash already exists in
47
+ the registry.
48
+
39
49
  ## Caching
40
50
 
41
51
  Cache configuration is generated per build type; node builds cache
42
- `node_modules` and the yarn cache. GitLab uses mutable caches with
52
+ `node_modules` and the package manager's download cache (the `.yarn`
53
+ zip cache, or for pnpm projects a project-local `.pnpm-store`). GitLab
54
+ uses mutable caches with
43
55
  fallback keys (review branches fall back to the dev cache); GitHub uses
44
56
  immutable lockfile-keyed caches where only the build job writes.
45
57
  Caching behavior is changed via the build config in `catladder.ts`,