@catladder/cli 0.0.0-next-78d43d4a → 0.0.0-next-6916db3c

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 (65) hide show
  1. package/dist/apps/cli/src/catci.js +2 -2
  2. package/dist/apps/cli/src/catci.js.map +1 -1
  3. package/dist/apps/cli/src/commands/project/commandGitlabCi.js +2 -1
  4. package/dist/apps/cli/src/commands/project/commandGitlabCi.js.map +1 -1
  5. package/dist/apps/cli/src/commands/security/commandSecurityAuditCiJob.js +2 -2
  6. package/dist/apps/cli/src/commands/security/commandSecurityAuditCiJob.js.map +1 -1
  7. package/dist/apps/cli/src/commands/security/commandSecurityAuditCreate.js +2 -2
  8. package/dist/apps/cli/src/commands/security/commandSecurityAuditCreate.js.map +1 -1
  9. package/dist/apps/cli/src/publish/npmPublishJob.js +22 -5
  10. package/dist/apps/cli/src/publish/npmPublishJob.js.map +1 -1
  11. package/dist/apps/cli/src/utils/gitlabHost.d.ts +14 -0
  12. package/dist/apps/cli/src/utils/gitlabHost.js +27 -0
  13. package/dist/apps/cli/src/utils/gitlabHost.js.map +1 -0
  14. package/dist/bundles/catci/index.js +10 -4
  15. package/dist/bundles/catenv/index.js +137 -36
  16. package/dist/bundles/cli/index.js +177 -41
  17. package/dist/bundles/runner-images/kubernetes/helm-charts/the-panter-chart/templates/_helpers.tpl +0 -10
  18. package/dist/bundles/runner-images/kubernetes/helm-charts/the-panter-chart/templates/app.ingress.yaml +0 -5
  19. package/dist/bundles/runner-images/kubernetes/helm-charts/the-panter-chart/values.yaml +0 -1
  20. package/dist/bundles/runner-images/npm-publish/Dockerfile +12 -0
  21. package/dist/bundles/runner-images/semantic-release/scripts/semanticRelease +4 -3
  22. package/dist/bundles/skills/catladder-deploys/references/deploy-types.md +3 -2
  23. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js +70 -24
  24. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js.map +1 -1
  25. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js +11 -1
  26. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
  27. package/dist/packages/pipeline/src/backends/gitlab/createGitlabJobs.js +5 -1
  28. package/dist/packages/pipeline/src/backends/gitlab/createGitlabJobs.js.map +1 -1
  29. package/dist/packages/pipeline/src/backends/index.d.ts +6 -0
  30. package/dist/packages/pipeline/src/backends/index.js +9 -2
  31. package/dist/packages/pipeline/src/backends/index.js.map +1 -1
  32. package/dist/packages/pipeline/src/context/getEnvironmentVariables.d.ts +1 -1
  33. package/dist/packages/pipeline/src/customImages/shippedImages.js +1 -0
  34. package/dist/packages/pipeline/src/customImages/shippedImages.js.map +1 -1
  35. package/dist/packages/pipeline/src/deploy/base/deploy.js +1 -0
  36. package/dist/packages/pipeline/src/deploy/base/deploy.js.map +1 -1
  37. package/dist/packages/pipeline/src/deploy/npmPackage/deployJob.js +6 -1
  38. package/dist/packages/pipeline/src/deploy/npmPackage/deployJob.js.map +1 -1
  39. package/dist/packages/pipeline/src/deploy/pages/deployJob.js +16 -5
  40. package/dist/packages/pipeline/src/deploy/pages/deployJob.js.map +1 -1
  41. package/dist/packages/pipeline/src/pipeline/generatePipelineFiles.js +10 -0
  42. package/dist/packages/pipeline/src/pipeline/generatePipelineFiles.js.map +1 -1
  43. package/dist/packages/pipeline/src/runner/index.d.ts +1 -1
  44. package/dist/packages/pipeline/src/runner/index.js.map +1 -1
  45. package/dist/packages/pipeline/src/types/config.d.ts +3 -3
  46. package/dist/packages/pipeline/src/types/jobDefinition.d.ts +1 -1
  47. package/dist/packages/pipeline/src/types/jobs.d.ts +9 -0
  48. package/dist/packages/pipeline/src/types/jobs.js.map +1 -1
  49. package/dist/packages/pipeline/src/utils/writeFiles.d.ts +6 -0
  50. package/dist/packages/pipeline/src/utils/writeFiles.js +8 -2
  51. package/dist/packages/pipeline/src/utils/writeFiles.js.map +1 -1
  52. package/dist/runner-images/kubernetes/helm-charts/the-panter-chart/templates/_helpers.tpl +0 -10
  53. package/dist/runner-images/kubernetes/helm-charts/the-panter-chart/templates/app.ingress.yaml +0 -5
  54. package/dist/runner-images/kubernetes/helm-charts/the-panter-chart/values.yaml +0 -1
  55. package/dist/runner-images/npm-publish/Dockerfile +12 -0
  56. package/dist/runner-images/semantic-release/scripts/semanticRelease +4 -3
  57. package/dist/skills/catladder-deploys/references/deploy-types.md +3 -2
  58. package/dist/tsconfig.tsbuildinfo +1 -1
  59. package/package.json +1 -1
  60. package/src/catci.ts +2 -3
  61. package/src/commands/project/commandGitlabCi.ts +2 -1
  62. package/src/commands/security/commandSecurityAuditCiJob.ts +2 -3
  63. package/src/commands/security/commandSecurityAuditCreate.ts +2 -3
  64. package/src/publish/npmPublishJob.ts +32 -6
  65. package/src/utils/gitlabHost.ts +23 -0
@@ -2931,6 +2931,11 @@ const makeGithubJob = (context, job, allJobs, uploadProviderIds, images, scripts
2931
2931
  ? runScript
2932
2932
  : scripts.add(id, runScript);
2933
2933
  const artifactPaths = (_g = (_f = job.artifacts) === null || _f === void 0 ? void 0 : _f.paths) !== null && _g !== void 0 ? _g : [];
2934
+ // github pages: the built site is handed to the official actions
2935
+ // instead of being uploaded as a plain artifact. `deploy-pages`
2936
+ // replaces the whole site, so there is no path_prefix equivalent —
2937
+ // review previews are rejected upstream (see the pages deploy type).
2938
+ const pagesPublishDir = job.pages ? artifactPaths[0] : undefined;
2934
2939
  const declaredServices = ((_h = job.services) !== null && _h !== void 0 ? _h : []).map((service) => typeof service === "string" ? { name: service } : service);
2935
2940
  // docker runs natively on github runners, so gitlab's docker-in-docker
2936
2941
  // services are dropped. The job container stays: the runner mounts the
@@ -2976,14 +2981,38 @@ const makeGithubJob = (context, job, allJobs, uploadProviderIds, images, scripts
2976
2981
  */
2977
2982
  const referencesSecrets = Object.values(env).some((value) => typeof value === "string" &&
2978
2983
  (value.includes("${{ secrets.") || value.includes("${{ vars.")));
2979
- const githubEnvironment = job.environment && isComponent
2984
+ const githubEnvironment = pagesPublishDir
2985
+ ? // github requires pages deployments to target the `github-pages`
2986
+ // environment, and only the deploy step knows the final url.
2987
+ // `secrets-sync-github` derives its targets from the generated
2988
+ // workflows, so any secret this job references is synced there.
2989
+ {
2990
+ name: "github-pages",
2991
+ url: "${{ steps.deployment.outputs.page_url }}",
2992
+ }
2993
+ : job.environment && isComponent
2994
+ ? {
2995
+ name: `${context.env}-${context.name}`,
2996
+ ...(createsJobEnv ? { url: "${{ steps.main.outputs.url }}" } : {}),
2997
+ }
2998
+ : referencesSecrets
2999
+ ? { name: context.env }
3000
+ : undefined;
3001
+ // declaring `permissions` drops ALL default token grants, so a job
3002
+ // that needs any special grant must also re-declare the ordinary ones:
3003
+ // `contents: read` for the checkout and `packages: read` to pull its
3004
+ // job image from the repo registry.
3005
+ const specialPermissions = {
3006
+ ...(pagesPublishDir ? { pages: "write", "id-token": "write" } : {}),
3007
+ ...(job.idToken ? { "id-token": "write" } : {}),
3008
+ };
3009
+ const permissions = Object.keys(specialPermissions).length
2980
3010
  ? {
2981
- name: `${context.env}-${context.name}`,
2982
- ...(createsJobEnv ? { url: "${{ steps.main.outputs.url }}" } : {}),
3011
+ contents: "read",
3012
+ ...(resolved.fromRepoRegistry ? { packages: "read" } : {}),
3013
+ ...specialPermissions,
2983
3014
  }
2984
- : referencesSecrets
2985
- ? { name: context.env }
2986
- : undefined;
3015
+ : undefined;
2987
3016
  const githubJob = {
2988
3017
  name: githubJobName(context, job.name),
2989
3018
  "runs-on": "ubuntu-latest",
@@ -3006,6 +3035,7 @@ const makeGithubJob = (context, job, allJobs, uploadProviderIds, images, scripts
3006
3035
  : {}),
3007
3036
  ...(Object.keys(services).length > 0 ? { services } : {}),
3008
3037
  ...(githubEnvironment ? { environment: githubEnvironment } : {}),
3038
+ ...(permissions ? { permissions } : {}),
3009
3039
  env,
3010
3040
  steps: [
3011
3041
  ...(skipCheckout
@@ -3025,25 +3055,41 @@ const makeGithubJob = (context, job, allJobs, uploadProviderIds, images, scripts
3025
3055
  run,
3026
3056
  shell: "bash",
3027
3057
  },
3028
- ...(uploadProviderIds.has(id) || artifactPaths.length > 0
3029
- ? artifactPaths.length > 0
3030
- ? [
3031
- {
3032
- name: "Upload artifacts",
3033
- uses: "actions/upload-artifact@v4",
3034
- with: {
3035
- name: id,
3036
- path: artifactPaths.join("\n"),
3037
- "if-no-files-found": "warn",
3038
- // gitlab artifacts include everything; upload-artifact
3039
- // silently drops hidden files by default — which is
3040
- // exactly where next.js builds live (.next)
3041
- "include-hidden-files": true,
3042
- },
3043
- },
3044
- ]
3045
- : []
3058
+ ...(pagesPublishDir
3059
+ ? [
3060
+ {
3061
+ name: "Upload pages artifact",
3062
+ uses: "actions/upload-pages-artifact@v3",
3063
+ with: { path: pagesPublishDir },
3064
+ },
3065
+ {
3066
+ name: "Deploy to github pages",
3067
+ id: "deployment",
3068
+ uses: "actions/deploy-pages@v4",
3069
+ },
3070
+ ]
3046
3071
  : []),
3072
+ ...(pagesPublishDir
3073
+ ? []
3074
+ : uploadProviderIds.has(id) || artifactPaths.length > 0
3075
+ ? artifactPaths.length > 0
3076
+ ? [
3077
+ {
3078
+ name: "Upload artifacts",
3079
+ uses: "actions/upload-artifact@v4",
3080
+ with: {
3081
+ name: id,
3082
+ path: artifactPaths.join("\n"),
3083
+ "if-no-files-found": "warn",
3084
+ // gitlab artifacts include everything; upload-artifact
3085
+ // silently drops hidden files by default — which is
3086
+ // exactly where next.js builds live (.next)
3087
+ "include-hidden-files": true,
3088
+ },
3089
+ },
3090
+ ]
3091
+ : []
3092
+ : []),
3047
3093
  ],
3048
3094
  };
3049
3095
  return [id, githubJob];
@@ -3533,8 +3579,10 @@ const createGitlabPipeline_1 = __nccwpck_require__(94411);
3533
3579
  const gitlabReleaseJobs_1 = __nccwpck_require__(75512);
3534
3580
  const getPipelineStages_1 = __nccwpck_require__(29641);
3535
3581
  const sortGitLabJobDefProps_1 = __nccwpck_require__(71625);
3582
+ const writeFiles_1 = __nccwpck_require__(7396);
3536
3583
  const CATLADDER_GENERATED_FOLDER = ".catladder-generated";
3537
3584
  const GITLAB_GENERATED_FOLDER = CATLADDER_GENERATED_FOLDER + "/gitlab";
3585
+ const GITLAB_MAIN_FILE = ".gitlab-ci.yml";
3538
3586
  class GitlabBackend {
3539
3587
  constructor() {
3540
3588
  this.type = "gitlab";
@@ -3542,12 +3590,20 @@ class GitlabBackend {
3542
3590
  }
3543
3591
  async cleanup() {
3544
3592
  await (0, promises_1.rm)(this.generatedFolder, { force: true, recursive: true });
3593
+ // `.gitlab-ci.yml` lives outside the generated folder, so it used to
3594
+ // survive disabling the gitlab backend and kept a stale pipeline
3595
+ // running. Only remove it when it is ours: a project that generates
3596
+ // github only may well hand-maintain a gitlab file of its own.
3597
+ const mainFile = await (0, promises_1.readFile)(GITLAB_MAIN_FILE, "utf-8").catch(() => null);
3598
+ if (mainFile === null || mainFile === void 0 ? void 0 : mainFile.includes(writeFiles_1.GENERATED_FILE_MARKER)) {
3599
+ await (0, promises_1.rm)(GITLAB_MAIN_FILE, { force: true });
3600
+ }
3545
3601
  }
3546
3602
  async createFiles(config) {
3547
3603
  const images = this.createImagesPlan(config);
3548
3604
  const includes = await this.createIncludes(config, images);
3549
3605
  const mainFile = {
3550
- path: ".gitlab-ci.yml",
3606
+ path: GITLAB_MAIN_FILE,
3551
3607
  content: {
3552
3608
  include: includes.map((i) => i.path),
3553
3609
  },
@@ -3856,7 +3912,11 @@ const getFullReferencedJobNameFromWorkspace = (referencedJobName, workspaceName,
3856
3912
  const getJobName = (need) => (0, lodash_es_1.isObject)(need) ? need.job : need;
3857
3913
  const makeGitlabJob = (context, job, allJobs, images, baseRules) => {
3858
3914
  var _a, _b, _c;
3859
- const { environment, envMode, requires, provides, name, needs, jobTags, script, variables, runnerVariables, gate, when: jobWhen, allow_failure: jobAllowFailure, cache: jobCache, caches, image: jobImage, ...rest } = job;
3915
+ const { environment, envMode, requires, provides, name, needs, jobTags, script, variables, runnerVariables, gate, when: jobWhen, allow_failure: jobAllowFailure, cache: jobCache, caches, image: jobImage,
3916
+ // github lowers this to `permissions: id-token: write`; gitlab has
3917
+ // no counterpart, and anything left in `rest` lands in the job yaml
3918
+ // verbatim ("config contains unknown keys: idtoken")
3919
+ idToken: _idToken, ...rest } = job;
3860
3920
  // catladder image references resolve to an image built in the repo's
3861
3921
  // own registry; the job additionally depends on the image build job
3862
3922
  const resolvedImage = images.resolve(jobImage);
@@ -4525,7 +4585,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
4525
4585
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
4526
4586
  };
4527
4587
  Object.defineProperty(exports, "__esModule", ({ value: true }));
4528
- exports.getEnabledPipelineTypes = exports.getVaultConfig = exports.getPipelineGitRemote = exports.getPipelineOptions = exports.getPipelineBackend = void 0;
4588
+ exports.getEnabledPipelineTypes = exports.getVaultConfig = exports.getPipelineGitRemote = exports.getPipelineOptions = exports.getPipelineBackend = exports.getAllPipelineTypes = void 0;
4529
4589
  const github_1 = __nccwpck_require__(48);
4530
4590
  const gitlab_1 = __nccwpck_require__(10744);
4531
4591
  __exportStar(__nccwpck_require__(33415), exports);
@@ -4535,6 +4595,13 @@ const BACKENDS = {
4535
4595
  gitlab: () => new gitlab_1.GitlabBackend(),
4536
4596
  github: () => new github_1.GithubBackend(),
4537
4597
  };
4598
+ /**
4599
+ * every pipeline type catladder knows how to generate — regardless of
4600
+ * what the config enables. Cleanup uses this to also reach backends that
4601
+ * were switched off (their files would otherwise linger).
4602
+ */
4603
+ const getAllPipelineTypes = () => Object.keys(BACKENDS);
4604
+ exports.getAllPipelineTypes = getAllPipelineTypes;
4538
4605
  const getPipelineBackend = (type) => {
4539
4606
  const createBackend = BACKENDS[type];
4540
4607
  if (!createBackend) {
@@ -4577,7 +4644,7 @@ exports.getVaultConfig = getVaultConfig;
4577
4644
  const getEnabledPipelineTypes = (config) => {
4578
4645
  var _a;
4579
4646
  if (config.pipelines) {
4580
- const enabled = Object.keys(BACKENDS).filter((type) => { var _a; return (_a = config.pipelines) === null || _a === void 0 ? void 0 : _a[type]; });
4647
+ const enabled = (0, exports.getAllPipelineTypes)().filter((type) => { var _a; return (_a = config.pipelines) === null || _a === void 0 ? void 0 : _a[type]; });
4581
4648
  if (enabled.length === 0) {
4582
4649
  throw new Error("`pipelines` is configured, but no pipeline type is enabled");
4583
4650
  }
@@ -7774,6 +7841,7 @@ exports.RUNNER_IMAGE_BUILD_CONTEXT = {
7774
7841
  "docker-build": "self",
7775
7842
  "semantic-release": "self",
7776
7843
  changesets: "self",
7844
+ "npm-publish": "self",
7777
7845
  "agent-claude": "self",
7778
7846
  };
7779
7847
  /**
@@ -7913,6 +7981,7 @@ class DeployJob extends jobs_1.CatladderJob {
7913
7981
  artifacts: jobDefinition.artifacts,
7914
7982
  services: jobDefinition.services,
7915
7983
  pages: jobDefinition.pages,
7984
+ idToken: jobDefinition.idToken,
7916
7985
  allow_failure: (_e = jobDefinition.allow_failure) !== null && _e !== void 0 ? _e : deployConfig === null || deployConfig === void 0 ? void 0 : deployConfig.allowFailure,
7917
7986
  envMode: "stagePerEnv", // makes it easier to run manual tasks er env
7918
7987
  needs: [],
@@ -10170,7 +10239,12 @@ const createNpmPackageDeployJobs = (context) => {
10170
10239
  ];
10171
10240
  return (0, base_1.createDeployementJobs)(context, {
10172
10241
  deploy: {
10173
- image: (0, runner_1.getRunnerImage)("jobs-default"),
10242
+ // dedicated image: publishing needs npm >= 11.5.1 for trusted
10243
+ // publishing (OIDC), which jobs-default's node does not carry
10244
+ image: (0, runner_1.getRunnerImage)("npm-publish"),
10245
+ // github: lowered to `id-token: write` so npm can exchange the
10246
+ // workflow's OIDC token for short-lived publish credentials
10247
+ idToken: true,
10174
10248
  script: [
10175
10249
  // catci derives version + dist-tag from the pipeline trigger,
10176
10250
  // sets the version in package.json and runs npm publish
@@ -10227,9 +10301,14 @@ const createPagesDeployJobs = async (context) => {
10227
10301
  // should not happen
10228
10302
  throw new Error("deploy config is not pages");
10229
10303
  }
10230
- if (context.pipelineType === "github") {
10231
- // don't fail the whole github generation of a multi-backend project
10232
- console.warn(`component "${context.name}": the pages deploy type is not yet supported on the github backend — no deploy jobs generated`);
10304
+ const onGithub = context.pipelineType === "github";
10305
+ if (onGithub && context.environment.envType === "review") {
10306
+ // github pages serves ONE site per repository and deploy-pages
10307
+ // replaces all of it — there is no path_prefix equivalent, so per-PR
10308
+ // previews cannot exist (deploy-pages has a `preview` input, but it
10309
+ // is alpha and not publicly available). Warn instead of throwing, so
10310
+ // the github generation of a multi-backend project still succeeds.
10311
+ console.warn(`component "${context.name}": github pages cannot host per-merge-request previews (one site per repository) — no review deploy job generated`);
10233
10312
  return [];
10234
10313
  }
10235
10314
  // review environments publish under their own path prefix (gitlab
@@ -10252,8 +10331,14 @@ const createPagesDeployJobs = async (context) => {
10252
10331
  : []),
10253
10332
  ...deployConfig.script,
10254
10333
  // the gitlab environment url should point at the published site
10255
- // (the base deploy job reports $ROOT_URL as environment url)
10256
- `export ROOT_URL="$CI_PAGES_URL${pathPrefix ? `/${pathPrefix}` : ""}"`,
10334
+ // (the base deploy job reports $ROOT_URL as environment url).
10335
+ // On github the url is only known after deploy-pages ran, so the
10336
+ // backend takes it from that step's output instead.
10337
+ ...(onGithub
10338
+ ? []
10339
+ : [
10340
+ `export ROOT_URL="$CI_PAGES_URL${pathPrefix ? `/${pathPrefix}` : ""}"`,
10341
+ ]),
10257
10342
  ],
10258
10343
  variables: {},
10259
10344
  runnerVariables: {
@@ -11242,6 +11327,16 @@ async function generatePipelineFiles(context, pipelineType) {
11242
11327
  await (0, promises_1.rm)(jobImagesPlan_1.GENERATED_IMAGES_FOLDER, { recursive: true, force: true });
11243
11328
  // same for the materialized catci bundle (union across backends)
11244
11329
  await (0, promises_1.rm)(shippedCatci_1.GENERATED_CATCI_FOLDER, { recursive: true, force: true });
11330
+ // clean up the backends that are NOT enabled (any more): each
11331
+ // backend only ever removed its own files while it was enabled, so
11332
+ // disabling one in `pipelines` used to leave its pipeline files
11333
+ // behind forever — and a stale `.gitlab-ci.yml` keeps running a
11334
+ // stale pipeline. Only safe on a full generation, where the enabled
11335
+ // set is authoritative.
11336
+ const disabledTypes = (0, backends_1.getAllPipelineTypes)().filter((type) => !pipelineTypes.includes(type));
11337
+ for (const type of disabledTypes) {
11338
+ await (0, backends_1.getPipelineBackend)(type).cleanup();
11339
+ }
11245
11340
  // agent skills are backend-independent, materialized once per full
11246
11341
  // generation
11247
11342
  await (0, agentSkills_1.generateAgentSkills)(context);
@@ -12206,9 +12301,15 @@ exports.removeUndefined = removeUndefined;
12206
12301
  "use strict";
12207
12302
 
12208
12303
  Object.defineProperty(exports, "__esModule", ({ value: true }));
12209
- exports.FileWriter = exports.yamlStringifyOptions = void 0;
12304
+ exports.FileWriter = exports.yamlStringifyOptions = exports.GENERATED_FILE_MARKER = void 0;
12210
12305
  const promises_1 = __nccwpck_require__(91943);
12211
12306
  const yaml_1 = __nccwpck_require__(33483);
12307
+ /**
12308
+ * the line that marks a file as catladder-generated. Cleanup code uses
12309
+ * it to tell a generated file apart from a hand-maintained one at the
12310
+ * same path (e.g. a `.gitlab-ci.yml` a project wrote itself).
12311
+ */
12312
+ exports.GENERATED_FILE_MARKER = "🐱 🔨 This file is generated by catladder";
12212
12313
  exports.yamlStringifyOptions = {
12213
12314
  // prevents colapsing long command statements into multiple lines
12214
12315
  lineWidth: 0,
@@ -12268,7 +12369,7 @@ class FileWriter {
12268
12369
  getAutoGeneratedHeader(commentChar) {
12269
12370
  return [
12270
12371
  "-------------------------------------------------",
12271
- `🐱 🔨 This file is generated by catladder`,
12372
+ exports.GENERATED_FILE_MARKER,
12272
12373
  `🚨 Do not edit this file manually 🚨`,
12273
12374
  "-------------------------------------------------",
12274
12375
  ]