@catladder/cli 5.5.0 → 5.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/apps/cli/src/catci.js +22 -0
  2. package/dist/apps/cli/src/catci.js.map +1 -1
  3. package/dist/apps/cli/src/commands/index.d.ts +1 -0
  4. package/dist/apps/cli/src/commands/index.js +4 -1
  5. package/dist/apps/cli/src/commands/index.js.map +1 -1
  6. package/dist/apps/cli/src/commands/project/commandMrPin.d.ts +9 -0
  7. package/dist/apps/cli/src/commands/project/commandMrPin.js +11 -13
  8. package/dist/apps/cli/src/commands/project/commandMrPin.js.map +1 -1
  9. package/dist/apps/cli/src/commands/project/commandMrReviewApp.d.ts +21 -0
  10. package/dist/apps/cli/src/commands/project/commandMrReviewApp.js +102 -0
  11. package/dist/apps/cli/src/commands/project/commandMrReviewApp.js.map +1 -0
  12. package/dist/apps/cli/src/reviewApps/github.d.ts +10 -0
  13. package/dist/apps/cli/src/reviewApps/github.js +196 -0
  14. package/dist/apps/cli/src/reviewApps/github.js.map +1 -0
  15. package/dist/bundles/catci/index.js +4 -4
  16. package/dist/bundles/catenv/index.js +1261 -70
  17. package/dist/bundles/catenv/xdg-open +0 -0
  18. package/dist/bundles/cli/clipboard_i686.exe +0 -0
  19. package/dist/bundles/cli/clipboard_x86_64.exe +0 -0
  20. package/dist/bundles/cli/index.js +1387 -86
  21. package/dist/bundles/cli/xdg-open +0 -0
  22. package/dist/bundles/cli/xsel +0 -0
  23. package/dist/bundles/runner-images/changesets/scripts/changesetsRelease +0 -0
  24. package/dist/bundles/runner-images/kubernetes/scripts/kubernetesCreateSecret +0 -0
  25. package/dist/bundles/runner-images/kubernetes/scripts/kubernetesDelete +0 -0
  26. package/dist/bundles/runner-images/kubernetes/scripts/kubernetesDeploy +0 -0
  27. package/dist/bundles/runner-images/kubernetes/scripts/kubernetesRollback +0 -0
  28. package/dist/bundles/skills/catladder-builds/SKILL.md +50 -2
  29. package/dist/bundles/skills/catladder-builds/references/build-types.md +10 -2
  30. package/dist/bundles/skills/catladder-cli/references/commands.md +13 -0
  31. package/dist/bundles/skills/catladder-config/SKILL.md +4 -0
  32. package/dist/bundles/skills/catladder-deploys/SKILL.md +6 -0
  33. package/dist/bundles/skills/catladder-pipelines/SKILL.md +97 -3
  34. package/dist/packages/pipeline/src/backends/github/GithubBackend.js +60 -3
  35. package/dist/packages/pipeline/src/backends/github/GithubBackend.js.map +1 -1
  36. package/dist/packages/pipeline/src/backends/github/aggregateCheckJob.d.ts +1 -1
  37. package/dist/packages/pipeline/src/backends/github/aggregateCheckJob.js +22 -8
  38. package/dist/packages/pipeline/src/backends/github/aggregateCheckJob.js.map +1 -1
  39. package/dist/packages/pipeline/src/backends/github/artifactArchive.d.ts +22 -0
  40. package/dist/packages/pipeline/src/backends/github/artifactArchive.js +84 -0
  41. package/dist/packages/pipeline/src/backends/github/artifactArchive.js.map +1 -0
  42. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js +12 -29
  43. package/dist/packages/pipeline/src/backends/github/createGithubJobs.js.map +1 -1
  44. package/dist/packages/pipeline/src/backends/github/reviewDeployWorkflow.d.ts +128 -0
  45. package/dist/packages/pipeline/src/backends/github/reviewDeployWorkflow.js +510 -0
  46. package/dist/packages/pipeline/src/backends/github/reviewDeployWorkflow.js.map +1 -0
  47. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js +32 -5
  48. package/dist/packages/pipeline/src/backends/gitlab/GitlabBackend.js.map +1 -1
  49. package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.d.ts +11 -1
  50. package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.js +17 -5
  51. package/dist/packages/pipeline/src/backends/gitlab/createGitlabPipeline.js.map +1 -1
  52. package/dist/packages/pipeline/src/backends/gitlab/getPipelineStages.d.ts +4 -1
  53. package/dist/packages/pipeline/src/backends/gitlab/getPipelineStages.js +11 -2
  54. package/dist/packages/pipeline/src/backends/gitlab/getPipelineStages.js.map +1 -1
  55. package/dist/packages/pipeline/src/backends/gitlab/reviewDeployGate.d.ts +26 -0
  56. package/dist/packages/pipeline/src/backends/gitlab/reviewDeployGate.js +94 -0
  57. package/dist/packages/pipeline/src/backends/gitlab/reviewDeployGate.js.map +1 -0
  58. package/dist/packages/pipeline/src/build/types.d.ts +4 -3
  59. package/dist/packages/pipeline/src/build/types.js.map +1 -1
  60. package/dist/packages/pipeline/src/deploy/base/deploy.js +25 -12
  61. package/dist/packages/pipeline/src/deploy/base/deploy.js.map +1 -1
  62. package/dist/packages/pipeline/src/index.d.ts +2 -0
  63. package/dist/packages/pipeline/src/index.js +2 -0
  64. package/dist/packages/pipeline/src/index.js.map +1 -1
  65. package/dist/packages/pipeline/src/pipeline/createJobsForComponent.js +12 -2
  66. package/dist/packages/pipeline/src/pipeline/createJobsForComponent.js.map +1 -1
  67. package/dist/packages/pipeline/src/pipeline/createJobsForWorkspace.js +7 -2
  68. package/dist/packages/pipeline/src/pipeline/createJobsForWorkspace.js.map +1 -1
  69. package/dist/packages/pipeline/src/pipeline/resolveRequirements.d.ts +2 -0
  70. package/dist/packages/pipeline/src/pipeline/resolveRequirements.js +4 -2
  71. package/dist/packages/pipeline/src/pipeline/resolveRequirements.js.map +1 -1
  72. package/dist/packages/pipeline/src/postBuildTest/createPostBuildTestJobs.d.ts +16 -0
  73. package/dist/packages/pipeline/src/postBuildTest/createPostBuildTestJobs.js +167 -0
  74. package/dist/packages/pipeline/src/postBuildTest/createPostBuildTestJobs.js.map +1 -0
  75. package/dist/packages/pipeline/src/postBuildTest/index.d.ts +2 -0
  76. package/dist/packages/pipeline/src/postBuildTest/index.js +19 -0
  77. package/dist/packages/pipeline/src/postBuildTest/index.js.map +1 -0
  78. package/dist/packages/pipeline/src/postBuildTest/types.d.ts +61 -0
  79. package/dist/packages/pipeline/src/postBuildTest/types.js +3 -0
  80. package/dist/packages/pipeline/src/postBuildTest/types.js.map +1 -0
  81. package/dist/packages/pipeline/src/reviewApps.d.ts +38 -0
  82. package/dist/packages/pipeline/src/reviewApps.js +86 -0
  83. package/dist/packages/pipeline/src/reviewApps.js.map +1 -0
  84. package/dist/packages/pipeline/src/reviewAppsPolicy.d.ts +46 -0
  85. package/dist/packages/pipeline/src/reviewAppsPolicy.js +37 -0
  86. package/dist/packages/pipeline/src/reviewAppsPolicy.js.map +1 -0
  87. package/dist/packages/pipeline/src/types/config.d.ts +55 -0
  88. package/dist/packages/pipeline/src/types/config.js.map +1 -1
  89. package/dist/packages/pipeline/src/types/jobs.d.ts +2 -2
  90. package/dist/packages/pipeline/src/types/jobs.js +1 -0
  91. package/dist/packages/pipeline/src/types/jobs.js.map +1 -1
  92. package/dist/runner-images/changesets/scripts/changesetsRelease +0 -0
  93. package/dist/runner-images/kubernetes/scripts/kubernetesCreateSecret +0 -0
  94. package/dist/runner-images/kubernetes/scripts/kubernetesDelete +0 -0
  95. package/dist/runner-images/kubernetes/scripts/kubernetesDeploy +0 -0
  96. package/dist/runner-images/kubernetes/scripts/kubernetesRollback +0 -0
  97. package/dist/skills/catladder-builds/SKILL.md +50 -2
  98. package/dist/skills/catladder-builds/references/build-types.md +10 -2
  99. package/dist/skills/catladder-cli/references/commands.md +13 -0
  100. package/dist/skills/catladder-config/SKILL.md +4 -0
  101. package/dist/skills/catladder-deploys/SKILL.md +6 -0
  102. package/dist/skills/catladder-pipelines/SKILL.md +97 -3
  103. package/dist/tsconfig.tsbuildinfo +1 -1
  104. package/package.json +1 -1
  105. package/src/catci.ts +29 -0
  106. package/src/commands/index.ts +4 -0
  107. package/src/commands/project/commandMrPin.ts +15 -14
  108. package/src/commands/project/commandMrReviewApp.ts +143 -0
  109. package/src/reviewApps/github.ts +253 -0
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertUniquePostBuildTestNames = exports.createPostBuildTestJobs = exports.postBuildTestJobName = exports.POST_BUILD_TEST_STAGE = void 0;
4
+ const createArtifactsConfig_1 = require("../build/base/createArtifactsConfig");
5
+ const cache_1 = require("../build/node/cache");
6
+ const constants_1 = require("../build/node/constants");
7
+ const packageManagerInstall_1 = require("../build/node/packageManagerInstall");
8
+ const types_1 = require("../build/types");
9
+ const runner_1 = require("../runner");
10
+ const jobs_1 = require("../types/jobs");
11
+ const utils_1 = require("../utils");
12
+ exports.POST_BUILD_TEST_STAGE = "post-build";
13
+ const postBuildTestJobName = (name) => `🔬 ${name}`;
14
+ exports.postBuildTestJobName = postBuildTestJobName;
15
+ const getPostBuildTestsConfig = (context) => {
16
+ if (context.type === "workspace") {
17
+ return context.build.config.postBuildTests;
18
+ }
19
+ if (context.build.type === "disabled") {
20
+ return undefined;
21
+ }
22
+ return context.build.config.postBuildTests;
23
+ };
24
+ /**
25
+ * whether the build output is a node project, so the job has to install
26
+ * the dependencies before running the tests
27
+ */
28
+ const isNodeBuild = (context) => {
29
+ if (context.type === "workspace") {
30
+ return true; // workspace builds are node builds
31
+ }
32
+ if (context.build.type === "fromWorkspace") {
33
+ return true;
34
+ }
35
+ if (context.build.type === "standalone") {
36
+ return (0, types_1.isOfBuildType)(context.build.config, "node", "node-static", "storybook", "meteor");
37
+ }
38
+ return false;
39
+ };
40
+ const hasBuildCommand = (buildCommand) => buildCommand !== null && buildCommand !== false;
41
+ /**
42
+ * whether the build creates an app build job with artifacts. Rails builds
43
+ * and builds with `buildCommand: false` only build the docker image.
44
+ */
45
+ const hasBuildArtifacts = (context) => {
46
+ if (context.type === "workspace") {
47
+ return hasBuildCommand(context.build.config.buildCommand);
48
+ }
49
+ if (context.build.type === "fromWorkspace") {
50
+ return hasBuildCommand(context.build.workspaceBuildConfig.buildCommand);
51
+ }
52
+ if (context.build.type === "standalone") {
53
+ return (!(0, types_1.isOfBuildType)(context.build.config, "rails") &&
54
+ hasBuildCommand(context.build.config.buildCommand));
55
+ }
56
+ return false;
57
+ };
58
+ const getDefaultImage = (context) => {
59
+ if (context.type === "component" &&
60
+ context.build.type === "standalone" &&
61
+ (0, types_1.isOfBuildType)(context.build.config, "custom")) {
62
+ // custom builds bring their own toolchain image
63
+ return context.build.config.jobImage;
64
+ }
65
+ return (0, runner_1.getRunnerImage)("jobs-default");
66
+ };
67
+ /**
68
+ * jobs for `postBuildTests`: they run after the build in the `post-build`
69
+ * stage, against the build artifacts, and act as quality gates, so a
70
+ * failing post-build test blocks the deploy.
71
+ */
72
+ const createPostBuildTestJobs = async (context) => {
73
+ var _a;
74
+ // like lint and test: tagged releases deploy what was already tested
75
+ if (context.trigger === "taggedRelease") {
76
+ return [];
77
+ }
78
+ const tests = Object.entries((_a = getPostBuildTestsConfig(context)) !== null && _a !== void 0 ? _a : {}).filter((entry) => entry[1] !== false);
79
+ if (tests.length === 0) {
80
+ return [];
81
+ }
82
+ const nodeBuild = isNodeBuild(context);
83
+ const [packageManagerInstall, nodeCache] = nodeBuild
84
+ ? await Promise.all([
85
+ (0, packageManagerInstall_1.getPackageManagerInstall)(context),
86
+ // pull-only: the build job is the designated cache writer
87
+ (0, cache_1.getNodeCache)(context, "pull"),
88
+ ])
89
+ : [null, null];
90
+ // components built in a workspace test the workspace build output
91
+ const from = context.type === "component" && context.build.type === "fromWorkspace"
92
+ ? { workspace: context.build.workspaceName }
93
+ : undefined;
94
+ const buildRequirement = hasBuildArtifacts(context)
95
+ ? { capability: "buildArtifacts", artifacts: true, strict: true, from }
96
+ : // no build artifacts (e.g. rails): run after the build (docker image)
97
+ { capability: "build", artifacts: false, from };
98
+ return tests.map(([name, test]) => {
99
+ var _a, _b, _c;
100
+ const artifactsConfig = (0, createArtifactsConfig_1.createArtifactsConfig)(context.build.dir, test.artifactsReports, test.artifacts);
101
+ return new jobs_1.CatladderJob({
102
+ name: (0, exports.postBuildTestJobName)(name),
103
+ stage: exports.POST_BUILD_TEST_STAGE,
104
+ envMode: "stagePerEnv",
105
+ provides: ["qualityGate"],
106
+ needs: [],
107
+ requires: [buildRequirement],
108
+ image: (_a = test.jobImage) !== null && _a !== void 0 ? _a : getDefaultImage(context),
109
+ services: test.services,
110
+ // neutral cache declarations, lowered by each backend
111
+ caches: nodeCache !== null && nodeCache !== void 0 ? nodeCache : undefined,
112
+ variables: {
113
+ APP_PATH: context.build.dir,
114
+ ...(context.type === "component"
115
+ ? context.environment.jobOnlyVars.build.envVars
116
+ : {}),
117
+ ...((_b = test.vars) !== null && _b !== void 0 ? _b : {}),
118
+ },
119
+ runnerVariables: {
120
+ ...(nodeBuild ? constants_1.NODE_RUNNER_BUILD_VARIABLES : {}),
121
+ ...((_c = test.runnerVariables) !== null && _c !== void 0 ? _c : {}),
122
+ },
123
+ script: [
124
+ ...(nodeBuild ? (0, packageManagerInstall_1.ensureNodeVersion)(context) : []),
125
+ `cd ${context.build.dir}`,
126
+ ...(packageManagerInstall !== null && packageManagerInstall !== void 0 ? packageManagerInstall : []),
127
+ ...(0, utils_1.ensureArray)(test.command),
128
+ ],
129
+ allow_failure: test.allowFailure,
130
+ // reports and screenshots are most needed when the tests fail
131
+ ...(artifactsConfig
132
+ ? {
133
+ artifacts: {
134
+ when: "always",
135
+ ...artifactsConfig.artifacts,
136
+ },
137
+ }
138
+ : {}),
139
+ });
140
+ });
141
+ };
142
+ exports.createPostBuildTestJobs = createPostBuildTestJobs;
143
+ const jobIdOf = (jobName) => jobName
144
+ .toLowerCase()
145
+ .replace(/[^a-z0-9]+/g, "-")
146
+ .replace(/^-+|-+$/g, "");
147
+ /**
148
+ * post-build test names are chosen by the user. Github job ids drop the
149
+ * emoji of the job name, so e.g. a post-build test named `test` would
150
+ * clash with the `🧪 test` job.
151
+ */
152
+ const assertUniquePostBuildTestNames = (context, postBuildTestJobs, otherJobs) => {
153
+ const seenIds = new Set(otherJobs.map((job) => jobIdOf(job.name)));
154
+ // also catches two post-build tests that only differ in case or
155
+ // punctuation (e.g. `e2e` and `E2E`)
156
+ const clash = postBuildTestJobs.find((job) => {
157
+ const id = jobIdOf(job.name);
158
+ const isClash = seenIds.has(id);
159
+ seenIds.add(id);
160
+ return isClash;
161
+ });
162
+ if (clash) {
163
+ throw new Error(`${context.name}: post-build test '${clash.name}' clashes with another job of the same name, please rename it in postBuildTests`);
164
+ }
165
+ };
166
+ exports.assertUniquePostBuildTestNames = assertUniquePostBuildTestNames;
167
+ //# sourceMappingURL=createPostBuildTestJobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createPostBuildTestJobs.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/postBuildTest/createPostBuildTestJobs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from "./types";
2
+ export * from "./createPostBuildTestJobs";
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./createPostBuildTestJobs"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/postBuildTest/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,4DAA0C"}
@@ -0,0 +1,61 @@
1
+ import type { TestJobCustom } from "../build/types";
2
+ import type { Services } from "../types/gitlab-ci-yml";
3
+ /**
4
+ * a test job that runs after the build, against the build output, and
5
+ * blocks the deploy when it fails (e.g. an e2e suite against the
6
+ * production build with a database service)
7
+ */
8
+ export type PostBuildTestConfig = TestJobCustom & {
9
+ /**
10
+ * command(s) to run, in the build directory (component dir, or the
11
+ * workspace dir for workspace builds). The build artifacts (e.g.
12
+ * `dist`, `.next`) are already in place and dependencies are
13
+ * installed for node builds.
14
+ *
15
+ * The command is responsible for starting the app if it needs one,
16
+ * e.g. via playwright's `webServer` option running `next start`.
17
+ */
18
+ command: string | string[];
19
+ /**
20
+ * services the job needs, e.g. a database:
21
+ *
22
+ * ```ts
23
+ * services: [{
24
+ * name: "postgres:17",
25
+ * alias: "postgres",
26
+ * variables: { POSTGRES_PASSWORD: "postgres" },
27
+ * }]
28
+ * ```
29
+ *
30
+ * The service is reachable by its alias as hostname. On github,
31
+ * `command` and `entrypoint` of a service are not supported.
32
+ */
33
+ services?: Services;
34
+ /**
35
+ * variables for this job, e.g. `DATABASE_URL` pointing to a service
36
+ * or `BASE_URL` for the test runner.
37
+ *
38
+ * The job gets the build vars of the component (like the build and
39
+ * test jobs), but not the runtime vars and secrets of the deployed
40
+ * environment: post-build tests run before the deploy, also for
41
+ * merge requests, and should use their own services.
42
+ */
43
+ vars?: Record<string, string>;
44
+ };
45
+ /**
46
+ * named post-build tests: each entry becomes its own job in the
47
+ * `post-build` stage. Set an entry to `false` to disable it (e.g. in an
48
+ * env-specific override).
49
+ */
50
+ export type PostBuildTestsConfig = Record<string, PostBuildTestConfig | false>;
51
+ export type WithPostBuildTests = {
52
+ /**
53
+ * tests that run after the build against the build output, in the
54
+ * `post-build` stage between build and deploy. A failing post-build
55
+ * test blocks the deploy.
56
+ *
57
+ * Each entry becomes its own job, e.g. `{ e2e: { command: "pnpm test:e2e" } }`.
58
+ * Post-build tests don't run in tagged-release pipelines (like lint and test).
59
+ */
60
+ postBuildTests?: PostBuildTestsConfig;
61
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/postBuildTest/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import { type ResolvedReviewAppsConfig } from "./reviewAppsPolicy";
2
+ import type { Config } from "./types";
3
+ import type { Context } from "./types/context";
4
+ import type { CatladderJob } from "./types/jobs";
5
+ export * from "./reviewAppsPolicy";
6
+ export declare const getReviewAppsConfig: (config: Config) => ResolvedReviewAppsConfig;
7
+ /**
8
+ * whether the review deploys sit behind the per-MR/PR deploy switch
9
+ * instead of running in every pipeline
10
+ */
11
+ export declare const isReviewDeployGated: (config: ResolvedReviewAppsConfig) => boolean;
12
+ /**
13
+ * the label whose change switches the review apps on (`labeled` on
14
+ * opt-in, `unlabeled` on opt-out) or off (the inverse), if the mode is
15
+ * label-driven at all
16
+ */
17
+ export declare const getReviewAppsSwitchLabel: (config: ResolvedReviewAppsConfig) => {
18
+ label: string;
19
+ deployOn: "labeled" | "unlabeled";
20
+ stopOn: string;
21
+ } | undefined;
22
+ /**
23
+ * gitlab: matches a label inside `$CI_MERGE_REQUEST_LABELS`
24
+ * (comma-separated) — anchored so `x` never matches `no-x`
25
+ */
26
+ export declare const getGitlabLabelRegex: (label: string) => string;
27
+ /**
28
+ * gitlab: a draft MR, by its title prefix — the only draft signal every
29
+ * gitlab version exposes to rules
30
+ */
31
+ export declare const GITLAB_DRAFT_MR_CONDITION = "$CI_MERGE_REQUEST_TITLE =~ /^\\s*(\\[draft\\]|\\(draft\\)|draft:)/i";
32
+ /**
33
+ * whether a job belongs to the delivery chain of a review app — the
34
+ * docker image, the deploy and the post-deploy verification. These jobs
35
+ * sit behind the review deploy switch; quality jobs (lint, test, audit)
36
+ * and the app build never do.
37
+ */
38
+ export declare const isReviewDeliveryJob: (context: Context, job: CatladderJob) => boolean;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.isReviewDeliveryJob = exports.GITLAB_DRAFT_MR_CONDITION = exports.getGitlabLabelRegex = exports.getReviewAppsSwitchLabel = exports.isReviewDeployGated = exports.getReviewAppsConfig = void 0;
18
+ const autoStop_1 = require("./autoStop");
19
+ const reviewAppsPolicy_1 = require("./reviewAppsPolicy");
20
+ __exportStar(require("./reviewAppsPolicy"), exports);
21
+ const getReviewAppsConfig = (config) => {
22
+ var _a, _b, _c, _d, _e, _f, _g, _h;
23
+ return ({
24
+ deploy: (_b = (_a = config.reviewApps) === null || _a === void 0 ? void 0 : _a.deploy) !== null && _b !== void 0 ? _b : "auto",
25
+ // single colon on purpose: gitlab treats `a::b` labels as scoped and
26
+ // mutually exclusive, which would make this label and the
27
+ // `catladder::pin-review` pin label displace each other
28
+ label: (_d = (_c = config.reviewApps) === null || _c === void 0 ? void 0 : _c.label) !== null && _d !== void 0 ? _d : reviewAppsPolicy_1.DEFAULT_REVIEW_APP_LABEL,
29
+ skipLabel: (_f = (_e = config.reviewApps) === null || _e === void 0 ? void 0 : _e.skipLabel) !== null && _f !== void 0 ? _f : reviewAppsPolicy_1.DEFAULT_NO_REVIEW_APP_LABEL,
30
+ drafts: (_h = (_g = config.reviewApps) === null || _g === void 0 ? void 0 : _g.drafts) !== null && _h !== void 0 ? _h : "likeReady",
31
+ });
32
+ };
33
+ exports.getReviewAppsConfig = getReviewAppsConfig;
34
+ /**
35
+ * whether the review deploys sit behind the per-MR/PR deploy switch
36
+ * instead of running in every pipeline
37
+ */
38
+ const isReviewDeployGated = (config) => config.deploy !== "auto" || config.drafts === "checksOnly";
39
+ exports.isReviewDeployGated = isReviewDeployGated;
40
+ /**
41
+ * the label whose change switches the review apps on (`labeled` on
42
+ * opt-in, `unlabeled` on opt-out) or off (the inverse), if the mode is
43
+ * label-driven at all
44
+ */
45
+ const getReviewAppsSwitchLabel = (config) => {
46
+ switch (config.deploy) {
47
+ case "optIn":
48
+ return { label: config.label, deployOn: "labeled", stopOn: "unlabeled" };
49
+ case "optOut":
50
+ return {
51
+ label: config.skipLabel,
52
+ deployOn: "unlabeled",
53
+ stopOn: "labeled",
54
+ };
55
+ default:
56
+ return undefined;
57
+ }
58
+ };
59
+ exports.getReviewAppsSwitchLabel = getReviewAppsSwitchLabel;
60
+ /**
61
+ * gitlab: matches a label inside `$CI_MERGE_REQUEST_LABELS`
62
+ * (comma-separated) — anchored so `x` never matches `no-x`
63
+ */
64
+ const getGitlabLabelRegex = (label) => `/${(0, autoStop_1.getPinLabelRegexSource)(label)}/`;
65
+ exports.getGitlabLabelRegex = getGitlabLabelRegex;
66
+ /**
67
+ * gitlab: a draft MR, by its title prefix — the only draft signal every
68
+ * gitlab version exposes to rules
69
+ */
70
+ exports.GITLAB_DRAFT_MR_CONDITION = "$CI_MERGE_REQUEST_TITLE =~ /^\\s*(\\[draft\\]|\\(draft\\)|draft:)/i";
71
+ /**
72
+ * whether a job belongs to the delivery chain of a review app — the
73
+ * docker image, the deploy and the post-deploy verification. These jobs
74
+ * sit behind the review deploy switch; quality jobs (lint, test, audit)
75
+ * and the app build never do.
76
+ */
77
+ const isReviewDeliveryJob = (context, job) => {
78
+ var _a;
79
+ return context.type === "component" &&
80
+ context.environment.instance.type === "review" &&
81
+ (job.stage === "deploy" ||
82
+ job.stage === "verify" ||
83
+ ((_a = job.provides) !== null && _a !== void 0 ? _a : []).includes("dockerImage"));
84
+ };
85
+ exports.isReviewDeliveryJob = isReviewDeliveryJob;
86
+ //# sourceMappingURL=reviewApps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewApps.js","sourceRoot":"","sources":["../../../../../../packages/pipeline/src/reviewApps.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,yCAAoD;AACpD,yDAI4B;AAK5B,qDAAmC;AAE5B,MAAM,mBAAmB,GAAG,CACjC,MAAc,EACY,EAAE;;IAAC,OAAA,CAAC;QAC9B,MAAM,EAAE,MAAA,MAAA,MAAM,CAAC,UAAU,0CAAE,MAAM,mCAAI,MAAM;QAC3C,qEAAqE;QACrE,0DAA0D;QAC1D,wDAAwD;QACxD,KAAK,EAAE,MAAA,MAAA,MAAM,CAAC,UAAU,0CAAE,KAAK,mCAAI,2CAAwB;QAC3D,SAAS,EAAE,MAAA,MAAA,MAAM,CAAC,UAAU,0CAAE,SAAS,mCAAI,8CAA2B;QACtE,MAAM,EAAE,MAAA,MAAA,MAAM,CAAC,UAAU,0CAAE,MAAM,mCAAI,WAAW;KACjD,CAAC,CAAA;CAAA,CAAC;AAVU,QAAA,mBAAmB,uBAU7B;AAEH;;;GAGG;AACI,MAAM,mBAAmB,GAAG,CAAC,MAAgC,EAAE,EAAE,CACtE,MAAM,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,CAAC;AADhD,QAAA,mBAAmB,uBAC6B;AAE7D;;;;GAIG;AACI,MAAM,wBAAwB,GAAG,CACtC,MAAgC,EAGpB,EAAE;IACd,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,OAAO;YACV,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAC3E,KAAK,QAAQ;YACX,OAAO;gBACL,KAAK,EAAE,MAAM,CAAC,SAAS;gBACvB,QAAQ,EAAE,WAAW;gBACrB,MAAM,EAAE,SAAS;aAClB,CAAC;QACJ;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC,CAAC;AAjBW,QAAA,wBAAwB,4BAiBnC;AAEF;;;GAGG;AACI,MAAM,mBAAmB,GAAG,CAAC,KAAa,EAAU,EAAE,CAC3D,IAAI,IAAA,iCAAsB,EAAC,KAAK,CAAC,GAAG,CAAC;AAD1B,QAAA,mBAAmB,uBACO;AAEvC;;;GAGG;AACU,QAAA,yBAAyB,GACpC,qEAAqE,CAAC;AAExE;;;;;GAKG;AACI,MAAM,mBAAmB,GAAG,CAAC,OAAgB,EAAE,GAAiB,EAAE,EAAE;;IACzE,OAAA,OAAO,CAAC,IAAI,KAAK,WAAW;QAC5B,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ;QAC9C,CAAC,GAAG,CAAC,KAAK,KAAK,QAAQ;YACrB,GAAG,CAAC,KAAK,KAAK,QAAQ;YACtB,CAAC,MAAA,GAAG,CAAC,QAAQ,mCAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAA;CAAA,CAAC;AALrC,QAAA,mBAAmB,uBAKkB"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * the review-app deploy policy — dependency-free, so catci (the CI
3
+ * companion bundle) can import it without dragging in the pipeline.
4
+ */
5
+ /**
6
+ * when the review apps of a merge request / pull request deploy:
7
+ * - auto: every MR/PR deploys its review apps (default)
8
+ * - manual: never on their own — one "deploy review" switch per MR/PR
9
+ * (gitlab: a manual job in the pipeline, github: a dispatch workflow)
10
+ * - optIn: only while the MR/PR carries the `label`
11
+ * - optOut: unless the MR/PR carries the `skipLabel`
12
+ */
13
+ export type ReviewAppsDeployMode = "auto" | "manual" | "optIn" | "optOut";
14
+ /**
15
+ * what a draft MR/PR runs:
16
+ * - likeReady: the same as a ready one, review apps included (default)
17
+ * - checksOnly: tests, lint and audit only — the review apps deploy once it is
18
+ * marked ready
19
+ * - skip: no pipeline at all
20
+ */
21
+ export type ReviewAppsDraftsMode = "likeReady" | "checksOnly" | "skip";
22
+ export declare const DEFAULT_REVIEW_APP_LABEL = "catladder:review-app";
23
+ export declare const DEFAULT_NO_REVIEW_APP_LABEL = "catladder:no-review-app";
24
+ export type ResolvedReviewAppsConfig = {
25
+ deploy: ReviewAppsDeployMode;
26
+ label: string;
27
+ skipLabel: string;
28
+ drafts: ReviewAppsDraftsMode;
29
+ };
30
+ /**
31
+ * the state of a merge request / pull request the deploy decision
32
+ * depends on
33
+ */
34
+ export type ReviewAppsMrState = {
35
+ labels: string[];
36
+ draft: boolean;
37
+ };
38
+ /**
39
+ * whether the review apps of an MR/PR in the given state deploy
40
+ * automatically. An explicit request (playing the gate job, dispatching
41
+ * the deploy workflow) always deploys and doesn't consult this.
42
+ */
43
+ export declare const shouldAutoDeployReviewApps: (config: ResolvedReviewAppsConfig, { labels, draft }: ReviewAppsMrState) => {
44
+ deploy: boolean;
45
+ reason: string;
46
+ };
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shouldAutoDeployReviewApps = exports.DEFAULT_NO_REVIEW_APP_LABEL = exports.DEFAULT_REVIEW_APP_LABEL = void 0;
4
+ exports.DEFAULT_REVIEW_APP_LABEL = "catladder:review-app";
5
+ exports.DEFAULT_NO_REVIEW_APP_LABEL = "catladder:no-review-app";
6
+ /**
7
+ * whether the review apps of an MR/PR in the given state deploy
8
+ * automatically. An explicit request (playing the gate job, dispatching
9
+ * the deploy workflow) always deploys and doesn't consult this.
10
+ */
11
+ const shouldAutoDeployReviewApps = (config, { labels, draft }) => {
12
+ if (draft && config.drafts !== "likeReady") {
13
+ return { deploy: false, reason: "drafts don't deploy review apps" };
14
+ }
15
+ switch (config.deploy) {
16
+ case "auto":
17
+ return { deploy: true, reason: "review apps deploy automatically" };
18
+ case "manual":
19
+ return {
20
+ deploy: false,
21
+ reason: "review apps only deploy on request (deploy: manual)",
22
+ };
23
+ case "optIn":
24
+ return labels.includes(config.label)
25
+ ? { deploy: true, reason: `the '${config.label}' label is set` }
26
+ : { deploy: false, reason: `the '${config.label}' label is not set` };
27
+ case "optOut":
28
+ return labels.includes(config.skipLabel)
29
+ ? { deploy: false, reason: `the '${config.skipLabel}' label is set` }
30
+ : {
31
+ deploy: true,
32
+ reason: `the '${config.skipLabel}' label is not set`,
33
+ };
34
+ }
35
+ };
36
+ exports.shouldAutoDeployReviewApps = shouldAutoDeployReviewApps;
37
+ //# sourceMappingURL=reviewAppsPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewAppsPolicy.js","sourceRoot":"","sources":["../../../../../../packages/pipeline/src/reviewAppsPolicy.ts"],"names":[],"mappings":";;;AAuBa,QAAA,wBAAwB,GAAG,sBAAsB,CAAC;AAClD,QAAA,2BAA2B,GAAG,yBAAyB,CAAC;AAkBrE;;;;GAIG;AACI,MAAM,0BAA0B,GAAG,CACxC,MAAgC,EAChC,EAAE,MAAM,EAAE,KAAK,EAAqB,EACC,EAAE;IACvC,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAC3C,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC;IACtE,CAAC;IACD,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,MAAM;YACT,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAC;QACtE,KAAK,QAAQ;YACX,OAAO;gBACL,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,qDAAqD;aAC9D,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;gBAClC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,MAAM,CAAC,KAAK,gBAAgB,EAAE;gBAChE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,MAAM,CAAC,KAAK,oBAAoB,EAAE,CAAC;QAC1E,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;gBACtC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,MAAM,CAAC,SAAS,gBAAgB,EAAE;gBACrE,CAAC,CAAC;oBACE,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,QAAQ,MAAM,CAAC,SAAS,oBAAoB;iBACrD,CAAC;IACV,CAAC;AACH,CAAC,CAAC;AA3BW,QAAA,0BAA0B,8BA2BrC"}
@@ -11,6 +11,7 @@ import type { CatladderStore } from "../store";
11
11
  import type { AgentSkillsConfig } from "../agentSkills/types";
12
12
  import type { ProjectImageConfig } from "../customImages/projectImages";
13
13
  import type { VerifyConfig } from "../verify/types";
14
+ import type { ReviewAppsDeployMode, ReviewAppsDraftsMode } from "../reviewAppsPolicy";
14
15
  export declare const ALL_PIPELINE_TRIGGERS: readonly ["mainBranch", "mr", "taggedRelease"];
15
16
  export type PipelineTrigger = (typeof ALL_PIPELINE_TRIGGERS)[number];
16
17
  /**
@@ -492,6 +493,60 @@ export type Config<C extends ConfigProps = never> = {
492
493
  */
493
494
  pinLabel?: string | false;
494
495
  };
496
+ /**
497
+ * when merge requests / pull requests deploy their review apps —
498
+ * useful when many MRs/PRs are opened (e.g. by agents) and most of
499
+ * them don't need a running instance.
500
+ *
501
+ * With anything but the defaults, the delivery chain of every
502
+ * component's review app (docker image → deploy → verify) waits for
503
+ * ONE switch per MR/PR instead of running in every pipeline; tests,
504
+ * lint and audit always run:
505
+ * - gitlab: a `🚀 deploy review` job (manual, or automatic when the
506
+ * label policy says so). Label changes only apply to the next
507
+ * pipeline — `catladder mr review-app-on/off` sets the label and
508
+ * triggers one.
509
+ * - github: the review workflow decides at its start (labels, draft)
510
+ * and deploys in the same run when the policy says so. Later
511
+ * changes go through a `▶️ catladder deploy review` workflow,
512
+ * dispatched by the review workflow once green (when the policy now
513
+ * says deploy), by adding/removing the label, or by hand with the
514
+ * PR number. Switching the label off stops the review apps.
515
+ *
516
+ * Per-component `deploy.when` of the review env is ignored then — the
517
+ * switch covers all components.
518
+ */
519
+ reviewApps?: {
520
+ /**
521
+ * - auto: every MR/PR deploys (default)
522
+ * - manual: only on request (play the gate job / dispatch the
523
+ * workflow)
524
+ * - optIn: only while the MR/PR carries `label`
525
+ * - optOut: unless the MR/PR carries `skipLabel`
526
+ * @defaultValue "auto"
527
+ */
528
+ deploy?: ReviewAppsDeployMode;
529
+ /**
530
+ * the opt-in label
531
+ * @defaultValue "catladder:review-app"
532
+ */
533
+ label?: string;
534
+ /**
535
+ * the opt-out label
536
+ * @defaultValue "catladder:no-review-app"
537
+ */
538
+ skipLabel?: string;
539
+ /**
540
+ * what draft MRs/PRs run:
541
+ * - likeReady: the same as ready ones (default)
542
+ * - checksOnly: tests, lint and audit — the review apps deploy once the
543
+ * MR/PR is marked ready
544
+ * - skip: nothing (gitlab: marking an MR ready doesn't start a
545
+ * pipeline, the next push does)
546
+ * @defaultValue "likeReady"
547
+ */
548
+ drafts?: ReviewAppsDraftsMode;
549
+ };
495
550
  /**
496
551
  * additional vars only for the runner in all jobs.
497
552
  */
@@ -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;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;AAmMF;;;GAGG;AACI,MAAM,oBAAoB,GAAG,CAClC,YAA4C,EAC5C,GAAW,EACoB,EAAE,CAAC,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,GAAG,CAAC,KAAI,SAAS,CAAC;AAHxD,QAAA,oBAAoB,wBAGoC;AAE9D,MAAM,qBAAqB,GAAG,CACnC,YAA4C,EAC5C,GAAW,EACF,EAAE,CAAC,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,GAAG,CAAC,MAAK,KAAK,CAAC;AAH/B,QAAA,qBAAqB,yBAGU"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../../../../../packages/pipeline/src/types/config.ts"],"names":[],"mappings":";;;AAmBa,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;AAmMF;;;GAGG;AACI,MAAM,oBAAoB,GAAG,CAClC,YAA4C,EAC5C,GAAW,EACoB,EAAE,CAAC,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,GAAG,CAAC,KAAI,SAAS,CAAC;AAHxD,QAAA,oBAAoB,wBAGoC;AAE9D,MAAM,qBAAqB,GAAG,CACnC,YAA4C,EAC5C,GAAW,EACF,EAAE,CAAC,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAG,GAAG,CAAC,MAAK,KAAK,CAAC;AAH/B,QAAA,qBAAqB,yBAGU"}
@@ -16,7 +16,7 @@ export type CatladderJobCache = GitlabJobCache & {
16
16
  cacheId?: string;
17
17
  redundantOnExactHitOf?: string;
18
18
  };
19
- export declare const BASE_STAGES: readonly ["setup", "test", "build", "deploy", "verify", "agents", "rollback", "stop"];
19
+ export declare const BASE_STAGES: readonly ["setup", "test", "build", "post-build", "deploy", "verify", "agents", "rollback", "stop"];
20
20
  export type BaseStage = (typeof BASE_STAGES)[number];
21
21
  export type CatladderJobNeed = string | {
22
22
  job: string;
@@ -130,7 +130,7 @@ export type CatladderJobCore<S = BaseStage> = {
130
130
  /**
131
131
  * the capabilities this job provides to other jobs.
132
132
  * If not set, it is derived from the stage:
133
- * build -> "build", test -> "qualityGate", deploy -> "deployment"
133
+ * build -> "build", test and post-build -> "qualityGate", deploy -> "deployment"
134
134
  */
135
135
  provides?: CapabilityName[];
136
136
  /**
@@ -6,6 +6,7 @@ exports.BASE_STAGES = [
6
6
  "setup",
7
7
  "test",
8
8
  "build",
9
+ "post-build",
9
10
  "deploy",
10
11
  "verify",
11
12
  "agents",
@@ -1 +1 @@
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;AAuOX;;;;;;;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,YAAY;IACZ,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;AAuOX;;;;;;;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"}