@catladder/pipeline 1.153.0 → 1.154.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 (153) hide show
  1. package/dist/build/artifacts/createBuildJobArtifact.d.ts +3 -0
  2. package/dist/build/artifacts/createBuildJobArtifact.js +97 -0
  3. package/dist/build/base/createAppBuildJob.d.ts +3 -3
  4. package/dist/build/base/createAppBuildJob.js +9 -15
  5. package/dist/build/base/index.d.ts +6 -2
  6. package/dist/build/base/index.js +14 -5
  7. package/dist/build/base/writeDotEnv.js +2 -1
  8. package/dist/build/custom/__tests__/testJob.test.js +1 -1
  9. package/dist/build/custom/buildJob.js +3 -10
  10. package/dist/build/docker.js +3 -3
  11. package/dist/build/index.d.ts +13 -6
  12. package/dist/build/index.js +29 -7
  13. package/dist/build/node/buildJob.d.ts +7 -2
  14. package/dist/build/node/buildJob.js +40 -33
  15. package/dist/build/node/cache.d.ts +2 -2
  16. package/dist/build/node/cache.js +8 -4
  17. package/dist/build/node/index.d.ts +2 -2
  18. package/dist/build/node/meteor.js +3 -6
  19. package/dist/build/node/testJob.d.ts +3 -2
  20. package/dist/build/node/testJob.js +9 -4
  21. package/dist/build/node/yarn.js +1 -1
  22. package/dist/build/rails/build.d.ts +1 -1
  23. package/dist/build/rails/build.js +7 -2
  24. package/dist/build/rails/test.d.ts +1 -1
  25. package/dist/build/rails/test.js +5 -0
  26. package/dist/build/sbom.js +3 -2
  27. package/dist/build/types.d.ts +48 -4
  28. package/dist/build/types.js +7 -1
  29. package/dist/bundles/catladder-gitlab/index.js +2 -2
  30. package/dist/constants.js +1 -1
  31. package/dist/context/createAllComponentsContext.d.ts +12 -0
  32. package/dist/context/createAllComponentsContext.js +159 -0
  33. package/dist/context/createComponentContext.d.ts +1 -5
  34. package/dist/context/createComponentContext.js +82 -20
  35. package/dist/context/createWorkspaceContext.d.ts +16 -0
  36. package/dist/context/createWorkspaceContext.js +173 -0
  37. package/dist/context/getBuildInfoVariables.d.ts +1 -1
  38. package/dist/context/getEnvironmentContext.d.ts +1 -1
  39. package/dist/context/getEnvironmentVariables.d.ts +2 -2
  40. package/dist/context/getEnvironmentVariables.js +5 -4
  41. package/dist/context/getLabels.js +5 -5
  42. package/dist/deploy/base/deploy.d.ts +1 -1
  43. package/dist/deploy/base/deploy.js +18 -5
  44. package/dist/deploy/cloudRun/artifactsRegistry.js +2 -2
  45. package/dist/deploy/cloudRun/createJobs/common.d.ts +4 -4
  46. package/dist/deploy/cloudRun/index.d.ts +2 -2
  47. package/dist/deploy/custom/index.d.ts +2 -2
  48. package/dist/deploy/dockerTag/index.d.ts +2 -2
  49. package/dist/deploy/index.d.ts +7 -7
  50. package/dist/deploy/kubernetes/additionalSecretKeys.d.ts +3 -1
  51. package/dist/deploy/kubernetes/cloudSql/index.js +1 -1
  52. package/dist/deploy/kubernetes/deployJob.js +2 -2
  53. package/dist/deploy/kubernetes/index.d.ts +2 -2
  54. package/dist/deploy/sbom.d.ts +1 -1
  55. package/dist/deploy/sbom.js +4 -3
  56. package/dist/deploy/types/index.d.ts +3 -3
  57. package/dist/pipeline/createAllJobs.d.ts +12 -10
  58. package/dist/pipeline/createAllJobs.js +94 -51
  59. package/dist/pipeline/createJobsForComponent.js +2 -3
  60. package/dist/pipeline/createJobsForWorkspace.d.ts +3 -0
  61. package/dist/pipeline/createJobsForWorkspace.js +12 -0
  62. package/dist/pipeline/createMainPipeline.js +26 -6
  63. package/dist/pipeline/gitlab/createGitlabJobs.d.ts +3 -16
  64. package/dist/pipeline/gitlab/createGitlabJobs.js +191 -73
  65. package/dist/pipeline/packageManager.d.ts +3 -2
  66. package/dist/pipeline/packageManager.js +43 -15
  67. package/dist/tsconfig.tsbuildinfo +1 -1
  68. package/dist/types/config.d.ts +5 -4
  69. package/dist/types/context.d.ts +80 -12
  70. package/dist/types/context.js +10 -1
  71. package/dist/types/environmentContext.d.ts +5 -6
  72. package/dist/types/jobs.d.ts +5 -0
  73. package/examples/__snapshots__/cloud-run-memory-limit.ts.snap +8 -8
  74. package/examples/__snapshots__/cloud-run-meteor-with-worker.ts.snap +8 -0
  75. package/examples/__snapshots__/cloud-run-no-cpu-throttling.ts.snap +8 -8
  76. package/examples/__snapshots__/cloud-run-no-service.ts.snap +8 -8
  77. package/examples/__snapshots__/cloud-run-non-public.ts.snap +8 -8
  78. package/examples/__snapshots__/cloud-run-post-stop-job.ts.snap +8 -8
  79. package/examples/__snapshots__/cloud-run-service-gen2.ts.snap +8 -8
  80. package/examples/__snapshots__/cloud-run-service-increase-timout.ts.snap +8 -8
  81. package/examples/__snapshots__/cloud-run-service-with-volumes.ts.snap +8 -8
  82. package/examples/__snapshots__/cloud-run-storybook.ts.snap +4 -8
  83. package/examples/__snapshots__/cloud-run-with-ngnix.ts.snap +4 -8
  84. package/examples/__snapshots__/cloud-run-with-sql-reuse-db.ts.snap +16 -16
  85. package/examples/__snapshots__/cloud-run-with-sql.ts.snap +589 -1097
  86. package/examples/__snapshots__/cloud-run-with-worker.ts.snap +8 -8
  87. package/examples/__snapshots__/custom-build-job-with-tests.ts.snap +4 -0
  88. package/examples/__snapshots__/custom-build-job.ts.snap +4 -0
  89. package/examples/__snapshots__/custom-deploy.ts.snap +8 -8
  90. package/examples/__snapshots__/custom-envs.ts.snap +18 -12
  91. package/examples/__snapshots__/custom-sbom-java.ts.snap +4 -0
  92. package/examples/__snapshots__/kubernetes-application-customization.ts.snap +8 -8
  93. package/examples/__snapshots__/kubernetes-with-cloud-sql-legacy.ts.snap +8 -8
  94. package/examples/__snapshots__/kubernetes-with-cloud-sql.ts.snap +8 -8
  95. package/examples/__snapshots__/kubernetes-with-jobs.ts.snap +16 -16
  96. package/examples/__snapshots__/kubernetes-with-mongodb.ts.snap +8 -8
  97. package/examples/__snapshots__/local-dot-env.ts.snap +8 -8
  98. package/examples/__snapshots__/meteor-kubernetes.ts.snap +8 -0
  99. package/examples/__snapshots__/multiline-var.ts.snap +16 -16
  100. package/examples/__snapshots__/native-app.ts.snap +24 -16
  101. package/examples/__snapshots__/node-build-with-custom-image.ts.snap +8 -8
  102. package/examples/__snapshots__/node-build-with-docker-additions.ts.snap +8 -8
  103. package/examples/__snapshots__/wait-for-other-deploy.ts.snap +16 -16
  104. package/examples/cloud-run-with-sql.ts +9 -2
  105. package/package.json +1 -1
  106. package/src/build/artifacts/createBuildJobArtifact.ts +61 -0
  107. package/src/build/base/createAppBuildJob.ts +26 -22
  108. package/src/build/base/index.ts +31 -4
  109. package/src/build/base/writeDotEnv.ts +6 -2
  110. package/src/build/custom/__tests__/testJob.test.ts +4 -4
  111. package/src/build/custom/buildJob.ts +2 -13
  112. package/src/build/docker.ts +6 -8
  113. package/src/build/index.ts +39 -7
  114. package/src/build/node/buildJob.ts +68 -56
  115. package/src/build/node/cache.ts +17 -8
  116. package/src/build/node/index.ts +4 -2
  117. package/src/build/node/meteor.ts +3 -9
  118. package/src/build/node/testJob.ts +21 -7
  119. package/src/build/node/yarn.ts +2 -2
  120. package/src/build/rails/build.ts +14 -4
  121. package/src/build/rails/test.ts +9 -1
  122. package/src/build/sbom.ts +7 -2
  123. package/src/build/types.ts +68 -4
  124. package/src/context/createAllComponentsContext.ts +31 -0
  125. package/src/context/createComponentContext.ts +59 -20
  126. package/src/context/createWorkspaceContext.ts +56 -0
  127. package/src/context/getBuildInfoVariables.ts +2 -1
  128. package/src/context/getEnvironmentContext.ts +2 -2
  129. package/src/context/getEnvironmentVariables.ts +12 -7
  130. package/src/context/getLabels.ts +3 -3
  131. package/src/deploy/base/deploy.ts +33 -7
  132. package/src/deploy/cloudRun/artifactsRegistry.ts +3 -4
  133. package/src/deploy/cloudRun/createJobs/common.ts +4 -4
  134. package/src/deploy/cloudRun/index.ts +68 -67
  135. package/src/deploy/custom/index.ts +2 -2
  136. package/src/deploy/dockerTag/index.ts +8 -7
  137. package/src/deploy/index.ts +11 -9
  138. package/src/deploy/kubernetes/additionalSecretKeys.ts +3 -1
  139. package/src/deploy/kubernetes/cloudSql/index.ts +1 -1
  140. package/src/deploy/kubernetes/deployJob.ts +2 -2
  141. package/src/deploy/kubernetes/index.ts +42 -41
  142. package/src/deploy/sbom.ts +9 -4
  143. package/src/pipeline/createAllJobs.ts +56 -55
  144. package/src/pipeline/createChildPipeline.ts +1 -0
  145. package/src/pipeline/createJobsForComponent.ts +5 -4
  146. package/src/pipeline/createJobsForWorkspace.ts +12 -0
  147. package/src/pipeline/createMainPipeline.ts +38 -23
  148. package/src/pipeline/gitlab/createGitlabJobs.ts +283 -119
  149. package/src/pipeline/packageManager.ts +25 -9
  150. package/src/types/config.ts +4 -1
  151. package/src/types/context.ts +108 -12
  152. package/src/types/environmentContext.ts +6 -7
  153. package/src/types/jobs.ts +3 -1
@@ -1,7 +1,13 @@
1
1
  import { isObject, merge } from "lodash";
2
2
  import { getInjectVarsScript } from "../../bash/getInjectVarsScript";
3
3
  import { BASE_RETRY } from "../../defaults";
4
- import type { ComponentContext, GitlabJobDef, GitlabRule } from "../../types";
4
+ import type {
5
+ ComponentContext,
6
+ Context,
7
+ GitlabJobDef,
8
+ GitlabRule,
9
+ WorkspaceContext,
10
+ } from "../../types";
5
11
  import type { CatladderJob, CatladderJobNeed } from "../../types/jobs";
6
12
  import { notNil } from "../../utils";
7
13
  import { collapseableSection } from "../../utils/gitlab";
@@ -11,31 +17,40 @@ import type { AllCatladderJobs } from "../createAllJobs";
11
17
  export type AllGitlabJobs = {
12
18
  name: string;
13
19
  gitlabJob: GitlabJobDef;
14
- context: ComponentContext;
20
+ context: Context;
15
21
  }[];
16
22
 
17
23
  export const GITLAB_ENVIRONMENT_URL_VARIABLE = "CL_GITLAB_ENVIRONMENT_URL";
18
- const getFullJobName = (
19
- name: string,
20
- componentName: string,
21
- env?: string | null,
22
- ) => {
24
+ const getFullJobName = ({
25
+ type,
26
+ name,
27
+ baseName,
28
+ allJobs,
29
+ env,
30
+ }: {
31
+ type: "component" | "workspace";
32
+ name: string;
33
+ baseName: string;
34
+ allJobs: AllCatladderJobs;
35
+ env?: string | null;
36
+ }) => {
37
+ const shouldAddIcon = allJobs.workspaces.length > 0;
38
+ const icon = type === "component" ? "🔹" : "🔸";
39
+ const prefix = shouldAddIcon ? icon + " " : "";
23
40
  if (env) {
24
- return `${componentName} ${name} | ${env} `;
41
+ return `${prefix}${baseName} ${name} | ${env} `;
25
42
  }
26
- return `${componentName} ${name}`;
43
+ return `${prefix}${baseName} ${name}`;
27
44
  };
28
45
 
29
- const getFullReferencedJobName = (
46
+ const getFullReferencedJobNameFromComponent = (
30
47
  referencedJobName: string,
31
48
  componentName: string,
32
49
  env: string,
33
50
  allJobs: AllCatladderJobs,
34
51
  ) => {
35
- const referencedJob = allJobs
36
- .find(
37
- (j) => j.context.componentName === componentName && j.context.env === env,
38
- )
52
+ const referencedJob = allJobs.components
53
+ .find((j) => j.context.name === componentName && j.context.env === env)
39
54
  ?.jobs?.find((j) => j.name === referencedJobName);
40
55
 
41
56
  if (!referencedJob) {
@@ -44,15 +59,50 @@ const getFullReferencedJobName = (
44
59
  );
45
60
  }
46
61
  const envToSet = referencedJob.envMode !== "none" ? env : null;
47
- return getFullJobName(referencedJobName, componentName, envToSet);
62
+ return getFullJobName({
63
+ type: "component",
64
+ name: referencedJobName,
65
+ baseName: componentName,
66
+ env: envToSet,
67
+ allJobs,
68
+ });
69
+ };
70
+
71
+ const getFullReferencedJobNameFromWorkspace = (
72
+ referencedJobName: string,
73
+ workspaceName: string,
74
+ env: string,
75
+ allJobs: AllCatladderJobs,
76
+ ) => {
77
+ const referencedJob = allJobs.workspaces
78
+ .find((w) => w.context.name === workspaceName)
79
+ ?.jobs?.find((j) => j.name === referencedJobName);
80
+ if (!referencedJob) {
81
+ throw new Error(
82
+ `unknown job referenced: '${referencedJobName}' from workspace ${env}:${workspaceName}'`,
83
+ );
84
+ }
85
+ const envToSet = referencedJob.envMode !== "none" ? env : null;
86
+
87
+ return getFullJobName({
88
+ type: "workspace",
89
+ name: referencedJobName,
90
+ baseName: workspaceName,
91
+ env: envToSet,
92
+ allJobs,
93
+ });
48
94
  };
49
95
 
50
96
  const getJobName = (need: CatladderJobNeed) =>
51
97
  isObject(need) ? need.job : need;
52
98
 
53
99
  export const makeGitlabJob = (
54
- context: ComponentContext,
55
- {
100
+ context: Context,
101
+ job: CatladderJob<string>,
102
+ allJobs: AllCatladderJobs,
103
+ baseRules?: GitlabRule[],
104
+ ): [fullName: string, job: GitlabJobDef] => {
105
+ const {
56
106
  environment,
57
107
  envMode,
58
108
  needsStages,
@@ -65,70 +115,24 @@ export const makeGitlabJob = (
65
115
  variables,
66
116
  runnerVariables,
67
117
  when,
68
- ...job
69
- }: CatladderJob<string>,
70
- allJobs: AllCatladderJobs,
71
- baseRules?: GitlabRule[],
72
- ): [fullName: string, job: GitlabJobDef] => {
118
+ ...rest
119
+ } = job;
73
120
  const stage =
74
121
  envMode === "stagePerEnv" ? `${job.stage} ${context.env}` : job.stage;
75
122
 
76
- const needsFromStages: CatladderJob["needs"] = needsStages?.flatMap((n) => {
77
- const referencedComponentName = context.componentName;
78
- const allJobNamesFromThatStage =
79
- allJobs
80
- .filter(
81
- (j) =>
82
- j.context.componentName === referencedComponentName &&
83
- j.context.env === context.env,
84
- )
85
- .flatMap((j) => j.jobs)
86
- ?.filter((j) => j.stage === n.stage)
87
- ?.map((j) => j.name) ?? [];
88
-
89
- return allJobNamesFromThatStage.map((job) => ({
90
- job,
91
- artifacts: n.artifacts ?? false,
92
- componentName: referencedComponentName,
93
- }));
94
- });
95
- const cleanedNeeds: CatladderJob["needs"] = [
96
- ...(needsFromStages ?? []),
97
- ...(needs ?? []),
98
- // pull in legacy needs from other component, which is now identical to needs
99
- ...(needsOtherComponent ?? []),
100
- ];
101
-
102
- const gitlabNeeds: GitlabJobDef["needs"] = cleanedNeeds
103
- ?.map((n) =>
104
- isObject(n)
105
- ? {
106
- job: getFullReferencedJobName(
107
- n.job,
108
- n.componentName ?? context.componentName,
109
- context.env,
110
- allJobs,
111
- ),
112
- artifacts: n.artifacts,
113
- }
114
- : getFullReferencedJobName(
115
- n,
116
- context.componentName,
117
- context.env,
118
- allJobs,
119
- ),
120
- ) // sort in a predictable manner for snapshot tests
121
- .sort((a, b) => getJobName(a).localeCompare(getJobName(b)));
122
-
123
- const deduplicatedGitlabNeeds: GitlabJobDef["needs"] = [
124
- ...new Map(gitlabNeeds.map((n) => [isObject(n) ? n.job : n, n])).values(),
125
- ];
123
+ const deduplicatedGitlabNeeds: GitlabJobDef["needs"] = getGitlabNeeds(
124
+ context,
125
+ job,
126
+ allJobs,
127
+ );
126
128
 
127
- const fullJobName = getFullJobName(
129
+ const fullJobName = getFullJobName({
130
+ type: context.type,
128
131
  name,
129
- context.componentName,
130
- envMode !== "none" ? context.env : undefined,
131
- );
132
+ baseName: context.name,
133
+ env: envMode !== "none" ? context.env : undefined,
134
+ allJobs,
135
+ });
132
136
 
133
137
  // backwards compatibility, some may still use KUBERNETES_CPU_REQUEST, KUBERNETES_MEMORY_REQUEST, etc. in variables.
134
138
  // those should now be set in the runnerVariables as they don't work in the variables key of the catladder job, becuase those get injected
@@ -178,27 +182,27 @@ export const makeGitlabJob = (
178
182
  ? [{ when }]
179
183
  : []),
180
184
  ];
185
+
186
+ const gitlabJob: GitlabJobDef = {
187
+ ...rest,
188
+ rules: rules.length > 0 ? rules : undefined,
189
+ variables: {
190
+ ...legacyRunnerVariables,
191
+ ...runnerVariables,
192
+ },
193
+ script: [...varsInjectScripts, ...(script?.filter(notNil) ?? [])],
194
+ tags: jobTags,
195
+ stage,
196
+
197
+ // sort in a predictable manner for snapshot tests
198
+ needs: deduplicatedGitlabNeeds,
199
+ retry: BASE_RETRY,
200
+ interruptible: true,
201
+ };
181
202
  const modified = addGitlabEnvironment(
182
203
  context,
183
204
  environment,
184
- {
185
- ...job,
186
- rules: rules.length > 0 ? rules : undefined,
187
- variables: {
188
- ...legacyRunnerVariables,
189
- ...runnerVariables,
190
- },
191
- script: [...varsInjectScripts, ...(script?.filter(notNil) ?? [])],
192
- tags: jobTags,
193
- stage,
194
-
195
- // sort in a predictable manner for snapshot tests
196
- needs: deduplicatedGitlabNeeds,
197
- retry: BASE_RETRY,
198
- interruptible: true,
199
- },
200
- context.componentName,
201
- context.env,
205
+ gitlabJob,
202
206
  allJobs,
203
207
  );
204
208
 
@@ -206,18 +210,21 @@ export const makeGitlabJob = (
206
210
  };
207
211
 
208
212
  const addGitlabEnvironment = (
209
- context: ComponentContext,
210
- environment: CatladderJob["environment"],
213
+ context: Context,
214
+ catladderJobEnvironment: CatladderJob["environment"],
211
215
  job: GitlabJobDef,
212
- componentName: string,
213
- env: string, // TODO: we could actually pull this from contxt
214
216
  allJobs: AllCatladderJobs,
215
217
  ): GitlabJobDef => {
216
- if (!environment) {
218
+ if (!catladderJobEnvironment) {
219
+ return job;
220
+ }
221
+ if (context.type !== "component") {
222
+ // don't add enviornment for workspace jobs atm.
217
223
  return job;
218
224
  }
219
- const { url, envType } = context.environment;
220
- const { on_stop, ...restEnvironment } = environment;
225
+ const { env, name, environment } = context;
226
+ const { url, envType } = environment;
227
+ const { on_stop, ...restEnvironment } = catladderJobEnvironment;
221
228
  // those can be dynamic, so we therefore have to do this: https://docs.gitlab.com/ee/ci/environments/#set-a-dynamic-environment-url
222
229
 
223
230
  const dotEnvFile = "gitlab_environment.env";
@@ -229,8 +236,8 @@ const addGitlabEnvironment = (
229
236
  // this is NOT a bashVariable since it NEEDS to be used as a string in gitlab
230
237
  const gitlabEnvironmentName =
231
238
  envType === "review"
232
- ? `${env}/$CI_COMMIT_REF_NAME/${componentName}` // FIXME: should be replaced with mr name as well
233
- : `${env}/${componentName}`;
239
+ ? `${env}/$CI_COMMIT_REF_NAME/${name}` // FIXME: should be replaced with mr name as well
240
+ : `${env}/${name}`;
234
241
 
235
242
  return {
236
243
  ...job,
@@ -239,9 +246,9 @@ const addGitlabEnvironment = (
239
246
  url: `$${GITLAB_ENVIRONMENT_URL_VARIABLE}`,
240
247
  ...(on_stop
241
248
  ? {
242
- on_stop: getFullReferencedJobName(
249
+ on_stop: getFullReferencedJobNameFromComponent(
243
250
  on_stop,
244
- componentName,
251
+ name,
245
252
  env,
246
253
  allJobs,
247
254
  ),
@@ -263,19 +270,176 @@ export const createGitlabJobs = async (
263
270
  allJobs: AllCatladderJobs,
264
271
  baseRules?: GitlabRule[],
265
272
  ): Promise<AllGitlabJobs> => {
266
- return allJobs.flatMap(({ context, jobs }) => {
267
- return jobs.map((job) => {
268
- const [fullJobName, gitlabJob] = makeGitlabJob(
269
- context,
273
+ // TODO: add workspace jobs
274
+ return [...allJobs.workspaces, ...allJobs.components].flatMap(
275
+ ({ context, jobs }) => {
276
+ return jobs.map((job) => {
277
+ const [fullJobName, gitlabJob] = makeGitlabJob(
278
+ context,
279
+ job,
280
+ allJobs,
281
+ baseRules,
282
+ );
283
+ return {
284
+ name: fullJobName,
285
+ gitlabJob,
286
+ context,
287
+ };
288
+ });
289
+ },
290
+ );
291
+ };
292
+
293
+ function getGitlabNeeds(
294
+ context: Context,
295
+ job: CatladderJob<string>,
296
+ allJobs: AllCatladderJobs,
297
+ ): GitlabJobDef["needs"] {
298
+ const needs =
299
+ context.type === "workspace"
300
+ ? getGitlabNeedsForWorkspaceJob(context, job, allJobs)
301
+ : getGitlabNeedsForComponentJob(context, job, allJobs);
302
+
303
+ return deduplicateNeeds(needs);
304
+ }
305
+ function deduplicateNeeds(needs: GitlabJobDef["needs"]): GitlabJobDef["needs"] {
306
+ return needs
307
+ ? [...new Map(needs.map((n) => [isObject(n) ? n.job : n, n])).values()]
308
+ : undefined;
309
+ }
310
+
311
+ function getGitlabNeedsForComponentJob(
312
+ context: ComponentContext,
313
+ { needsStages, needs, needsOtherComponent }: CatladderJob<string>,
314
+ allJobs: AllCatladderJobs,
315
+ ): GitlabJobDef["needs"] {
316
+ const needsFromStages = needsStages?.flatMap<CatladderJobNeed>((n) => {
317
+ const componentName = context.name;
318
+ if (!n.workspaceName) {
319
+ const allJobNamesFromThatStage =
320
+ allJobs.components
321
+ .filter(
322
+ (j) =>
323
+ j.context.name === componentName && j.context.env === context.env,
324
+ )
325
+ .flatMap((j) => j.jobs)
326
+ ?.filter((j) => j.stage === n.stage)
327
+ ?.map((j) => j.name) ?? [];
328
+
329
+ return allJobNamesFromThatStage.map((job) => ({
330
+ job,
331
+ artifacts: n.artifacts ?? false,
332
+ componentName,
333
+ }));
334
+ } else {
335
+ const allJobNamesFromThatStage =
336
+ allJobs.workspaces
337
+ .find(
338
+ (w) =>
339
+ w.context.name === n.workspaceName &&
340
+ w.context.env === context.env,
341
+ )
342
+ ?.jobs?.flatMap((j) => j)
343
+ ?.filter((j) => j.stage === n.stage)
344
+ ?.map((j) => j.name) ?? [];
345
+
346
+ return allJobNamesFromThatStage.map((job) => ({
270
347
  job,
271
- allJobs,
272
- baseRules,
273
- );
274
- return {
275
- name: fullJobName,
276
- gitlabJob,
277
- context,
278
- };
279
- });
348
+ artifacts: n.artifacts ?? false,
349
+ workspaceName: n.workspaceName,
350
+ }));
351
+ }
280
352
  });
281
- };
353
+ const cleanedNeeds: CatladderJob["needs"] = [
354
+ ...(needsFromStages ?? []),
355
+ ...(needs ?? []),
356
+ // pull in legacy needs from other component, which is now identical to needs
357
+ ...(needsOtherComponent ?? []),
358
+ ];
359
+
360
+ return cleanedNeeds
361
+ ?.map((n) =>
362
+ isObject(n)
363
+ ? "workspaceName" in n
364
+ ? {
365
+ job: getFullReferencedJobNameFromWorkspace(
366
+ n.job,
367
+ n.workspaceName,
368
+ context.env,
369
+ allJobs,
370
+ ),
371
+ artifacts: n.artifacts,
372
+ }
373
+ : {
374
+ job: getFullReferencedJobNameFromComponent(
375
+ n.job,
376
+ n.componentName ?? context.name,
377
+ context.env,
378
+ allJobs,
379
+ ),
380
+ artifacts: n.artifacts,
381
+ }
382
+ : getFullReferencedJobNameFromComponent(
383
+ n,
384
+ context.name,
385
+ context.env,
386
+ allJobs,
387
+ ),
388
+ ) // sort in a predictable manner for snapshot tests
389
+ .sort((a, b) => getJobName(a).localeCompare(getJobName(b)));
390
+ }
391
+ /**
392
+ *
393
+ *unclear whether we actually need this. So far jobs in a workspace don't have needs to other jobs from the same workspace
394
+ */
395
+ function getGitlabNeedsForWorkspaceJob(
396
+ context: WorkspaceContext,
397
+ { needsStages, needs }: CatladderJob<string>,
398
+ allJobs: AllCatladderJobs,
399
+ ): GitlabJobDef["needs"] {
400
+ const needsFromStages = needsStages?.flatMap<CatladderJobNeed>((n) => {
401
+ const workspaceName = n.workspaceName ?? context.name;
402
+ const allJobNamesFromThatStage =
403
+ allJobs.workspaces
404
+ .filter(
405
+ (j) =>
406
+ j.context.name === workspaceName && j.context.env === context.env,
407
+ )
408
+ .flatMap((j) => j.jobs)
409
+ ?.filter((j) => j.stage === n.stage)
410
+ ?.map((j) => j.name) ?? [];
411
+
412
+ return allJobNamesFromThatStage.map((job) => ({
413
+ job,
414
+ artifacts: n.artifacts ?? false,
415
+ workspaceName: workspaceName,
416
+ }));
417
+ });
418
+ const cleanedNeeds: CatladderJob["needs"] = [
419
+ ...(needsFromStages ?? []),
420
+ ...(needs ?? []),
421
+ ];
422
+
423
+ return cleanedNeeds
424
+ ?.map((n) =>
425
+ isObject(n)
426
+ ? {
427
+ job: getFullReferencedJobNameFromWorkspace(
428
+ n.job,
429
+ "workspaceName" in n && n.workspaceName
430
+ ? n.workspaceName
431
+ : context.name,
432
+ context.env,
433
+ allJobs,
434
+ ),
435
+ artifacts: n.artifacts,
436
+ }
437
+ : getFullReferencedJobNameFromWorkspace(
438
+ n,
439
+ context.name,
440
+ context.env,
441
+ allJobs,
442
+ ),
443
+ ) // sort in a predictable manner for snapshot tests
444
+ .sort((a, b) => getJobName(a).localeCompare(getJobName(b)));
445
+ }
@@ -1,7 +1,11 @@
1
1
  import { existsSync } from "fs";
2
2
  import { join } from "path";
3
3
  import { pathEqual } from "path-equal";
4
- import type { Config, PackageManagerInfoComponent } from "../types";
4
+ import type {
5
+ Config,
6
+ PackageManagerInfoBase,
7
+ PackageManagerInfoComponent,
8
+ } from "../types";
5
9
  import {
6
10
  getWorkspaces,
7
11
  getYarnVersion,
@@ -12,13 +16,11 @@ export const getPackageManagerInfoForComponent = async (
12
16
  config: Config,
13
17
  componentName: string,
14
18
  ): Promise<PackageManagerInfoComponent> => {
19
+ const baseInfo = await getPackageManagerInfoBase();
20
+ const { workspaces } = baseInfo;
15
21
  // currently only supports yarn
16
- const version = await getYarnVersion();
17
- if (!version) throw new Error("could not get yarn version");
18
- const isClassic = version.startsWith("1");
19
22
 
20
23
  const component = config.components[componentName];
21
- const workspaces = await getWorkspaces(isClassic);
22
24
  const currentWorkspace = workspaces.find((w) =>
23
25
  pathEqual(component.dir, w.location),
24
26
  );
@@ -54,13 +56,27 @@ export const getPackageManagerInfoForComponent = async (
54
56
  ...currentWorkspaceDependencies,
55
57
  ];
56
58
  return {
57
- type: "yarn",
58
- workspaces,
59
- version,
60
- isClassic,
59
+ ...baseInfo,
61
60
  currentWorkspace,
62
61
  currentWorkspaceDependencies,
63
62
  componentIsInWorkspace,
64
63
  pathsToCopyInDocker,
65
64
  };
66
65
  };
66
+ // TODO: memoizee
67
+ export const getPackageManagerInfoBase =
68
+ async (): Promise<PackageManagerInfoBase> => {
69
+ // currently only supports yarn
70
+ const version = await getYarnVersion();
71
+ if (!version) throw new Error("could not get yarn version");
72
+ const isClassic = version.startsWith("1");
73
+
74
+ const workspaces = await getWorkspaces(isClassic);
75
+
76
+ return {
77
+ type: "yarn",
78
+ workspaces,
79
+ version,
80
+ isClassic,
81
+ };
82
+ };
@@ -4,7 +4,7 @@ import type { DeployConfig } from "../deploy/types";
4
4
  import type { CatladderJob } from "./jobs";
5
5
  import type { ComponentContext } from "./context";
6
6
  import type { PartialDeep } from "./utils";
7
- import type { PipelineType } from "..";
7
+ import type { PipelineType, WorkspaceBuildConfig } from "..";
8
8
 
9
9
  export const ALL_PIPELINE_TRIGGERS = [
10
10
  "mainBranch",
@@ -200,6 +200,9 @@ export type Config<C extends ConfigProps = never> = {
200
200
  *
201
201
  */
202
202
  domainCanonical?: string;
203
+
204
+ // shared workspace Builds
205
+ builds?: Record<string, WorkspaceBuildConfig>;
203
206
  /**
204
207
  * components (sub apps)
205
208
  */