@catladder/pipeline 1.110.1 → 1.110.3

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 (69) hide show
  1. package/dist/build/base/__tests__/createArtifactsConfig.test.d.ts +1 -0
  2. package/dist/build/base/__tests__/createArtifactsConfig.test.js +40 -0
  3. package/dist/build/base/createArtifactsConfig.d.ts +4 -0
  4. package/dist/build/base/createArtifactsConfig.js +63 -0
  5. package/dist/build/custom/__tests__/testJob.test.d.ts +1 -0
  6. package/dist/build/custom/__tests__/testJob.test.js +37 -0
  7. package/dist/build/custom/buildJob.js +4 -2
  8. package/dist/build/custom/testJob.d.ts +5 -1
  9. package/dist/build/custom/testJob.js +10 -23
  10. package/dist/build/node/buildJob.js +4 -2
  11. package/dist/build/node/testJob.js +12 -11
  12. package/dist/build/rails/build.js +13 -2
  13. package/dist/build/sbom.d.ts +5 -0
  14. package/dist/build/sbom.js +29 -0
  15. package/dist/build/types.d.ts +39 -40
  16. package/dist/bundles/catladder-gitlab/index.js +3 -3
  17. package/dist/constants.js +1 -1
  18. package/dist/deploy/base.js +38 -2
  19. package/dist/deploy/cloudRun/deployJob.js +5 -4
  20. package/dist/deploy/custom/deployJob.js +3 -2
  21. package/dist/deploy/kubernetes/deployJob.js +3 -2
  22. package/dist/deploy/sbom.d.ts +4 -0
  23. package/dist/deploy/sbom.js +17 -0
  24. package/dist/pipeline/createJobsForComponent.js +1 -3
  25. package/dist/pipeline/gitlab/createGitlabJobs.js +5 -2
  26. package/dist/tsconfig.tsbuildinfo +1 -1
  27. package/dist/types/gitlab-types.d.ts +13 -22
  28. package/examples/__snapshots__/cloud-run-memory-limit.ts.snap +40 -96
  29. package/examples/__snapshots__/cloud-run-no-cpu-throttling.ts.snap +40 -96
  30. package/examples/__snapshots__/cloud-run-non-public.ts.snap +40 -96
  31. package/examples/__snapshots__/cloud-run-with-sql-reuse-db.ts.snap +80 -192
  32. package/examples/__snapshots__/cloud-run-with-sql.ts.snap +80 -192
  33. package/examples/__snapshots__/custom-build-job-with-tests.ts.snap +40 -96
  34. package/examples/__snapshots__/custom-build-job.ts.snap +40 -96
  35. package/examples/__snapshots__/custom-deploy.ts.snap +40 -96
  36. package/examples/__snapshots__/custom-envs.ts.snap +6 -126
  37. package/examples/__snapshots__/custom-sbom-java.ts.snap +40 -96
  38. package/examples/__snapshots__/kubernetes-application-customization.ts.snap +40 -96
  39. package/examples/__snapshots__/kubernetes-with-cloud-sql-legacy.ts.snap +40 -96
  40. package/examples/__snapshots__/kubernetes-with-cloud-sql.ts.snap +40 -96
  41. package/examples/__snapshots__/kubernetes-with-jobs.ts.snap +80 -192
  42. package/examples/__snapshots__/kubernetes-with-mongodb.ts.snap +40 -96
  43. package/examples/__snapshots__/native-app.ts.snap +72 -192
  44. package/examples/__snapshots__/node-build-with-custom-image.ts.snap +40 -96
  45. package/examples/__snapshots__/rails-k8s-with-worker.ts.snap +40 -96
  46. package/examples/__snapshots__/wait-for-other-deploy.ts.snap +64 -192
  47. package/package.json +1 -1
  48. package/src/build/base/__tests__/__snapshots__/createArtifactsConfig.test.ts.snap +49 -0
  49. package/src/build/base/__tests__/createArtifactsConfig.test.ts +41 -0
  50. package/src/build/base/createArtifactsConfig.ts +34 -0
  51. package/src/build/custom/__tests__/testJob.test.ts +32 -0
  52. package/src/build/custom/buildJob.ts +3 -0
  53. package/src/build/custom/testJob.ts +8 -21
  54. package/src/build/node/buildJob.ts +3 -0
  55. package/src/build/node/testJob.ts +16 -0
  56. package/src/build/rails/build.ts +3 -0
  57. package/src/build/sbom.ts +43 -0
  58. package/src/build/types.ts +45 -46
  59. package/src/deploy/base.ts +14 -7
  60. package/src/deploy/cloudRun/deployJob.ts +6 -0
  61. package/src/deploy/custom/deployJob.ts +9 -1
  62. package/src/deploy/kubernetes/deployJob.ts +10 -1
  63. package/src/deploy/sbom.ts +24 -0
  64. package/src/pipeline/createJobsForComponent.ts +1 -3
  65. package/src/pipeline/gitlab/createGitlabJobs.ts +6 -2
  66. package/src/types/gitlab-types.ts +12 -12
  67. package/dist/verify/reporting.d.ts +0 -3
  68. package/dist/verify/reporting.js +0 -48
  69. package/src/verify/reporting.ts +0 -69
@@ -1,10 +1,9 @@
1
- import { join } from "path";
2
1
  import type { Context } from "../../types/context";
3
2
  import type { CatladderJob } from "../../types/jobs";
4
3
  import { ensureArray, notNil } from "../../utils";
5
4
  import { isOfBuildType } from "../types";
6
- import type { BuildConfigArtifactsReports } from "../types";
7
5
  import type { Artifacts } from "../../types";
6
+ import { createArtifactsConfig } from "../base/createArtifactsConfig";
8
7
 
9
8
  const RUNNER_CUSTOM_TEST_VARIABLES = {
10
9
  KUBERNETES_CPU_REQUEST: "0.5",
@@ -48,7 +47,8 @@ export const createCustomTestJobs = (context: Context): CatladderJob[] => {
48
47
  allow_failure: true,
49
48
  ...createArtifactsConfig(
50
49
  context.componentConfig.dir,
51
- buildConfig.audit?.artifactsReports
50
+ buildConfig.audit?.artifactsReports,
51
+ buildConfig.audit?.artifacts
52
52
  ),
53
53
  }
54
54
  : null;
@@ -62,7 +62,8 @@ export const createCustomTestJobs = (context: Context): CatladderJob[] => {
62
62
  script: [...(ensureArray(buildConfig.lint?.command) ?? [])],
63
63
  ...createArtifactsConfig(
64
64
  context.componentConfig.dir,
65
- buildConfig.lint?.artifactsReports
65
+ buildConfig.lint?.artifactsReports,
66
+ buildConfig.lint?.artifacts
66
67
  ),
67
68
  }
68
69
  : null;
@@ -75,30 +76,16 @@ export const createCustomTestJobs = (context: Context): CatladderJob[] => {
75
76
  script: [...(ensureArray(buildConfig.test?.command) ?? [])],
76
77
  ...createArtifactsConfig(
77
78
  context.componentConfig.dir,
78
- buildConfig.test?.artifactsReports
79
+ buildConfig.test?.artifactsReports,
80
+ buildConfig.test?.artifacts
79
81
  ),
80
82
  }
81
83
  : null;
82
84
  return [auditJob, lintJob, testJob].filter(notNil);
83
85
  };
84
86
 
85
- type OptionalArtifacts =
87
+ export type OptionalArtifacts =
86
88
  | {
87
89
  artifacts: Artifacts;
88
90
  }
89
91
  | undefined;
90
-
91
- const createArtifactsConfig = (
92
- rootPath: string,
93
- artifactsReports?: BuildConfigArtifactsReports
94
- ): OptionalArtifacts =>
95
- artifactsReports
96
- ? {
97
- artifacts: {
98
- paths: [],
99
- reports: {
100
- junit: artifactsReports?.junit?.map((p) => join(rootPath, p)) ?? [],
101
- },
102
- },
103
- }
104
- : undefined;
@@ -10,6 +10,8 @@ import { NODE_RUNNER_BUILD_VARIABLES } from "./constants";
10
10
  import { getDockerAppCopyAndBuildScript, getYarnInstall } from "./yarn";
11
11
  import type { CatladderJob } from "../../types/jobs";
12
12
  import { getRunnerImage } from "../../runner";
13
+ import { createSbomBuildJob } from "../sbom";
14
+ import { sbomDeactivated } from "../../deploy/sbom";
13
15
 
14
16
  export const createNodeBuildJobs = (context: Context): CatladderJob[] => {
15
17
  const buildConfig = context.componentConfig.build;
@@ -76,5 +78,6 @@ export const createNodeBuildJobs = (context: Context): CatladderJob[] => {
76
78
  }),
77
79
  ]
78
80
  : []),
81
+ ...(sbomDeactivated(context) ? [] : [createSbomBuildJob(context)]),
79
82
  ];
80
83
  };
@@ -5,6 +5,7 @@ import { ensureArray, notNil } from "../../utils";
5
5
  import { getNodeCache } from "./cache";
6
6
  import { NODE_RUNNER_BUILD_VARIABLES } from "./constants";
7
7
  import { getYarnInstall } from "./yarn";
8
+ import { createArtifactsConfig } from "../base/createArtifactsConfig";
8
9
 
9
10
  export const createNodeTestJobs = (context: Context): CatladderJob[] => {
10
11
  // don't run tests after release
@@ -42,6 +43,11 @@ export const createNodeTestJobs = (context: Context): CatladderJob[] => {
42
43
  ]),
43
44
  ],
44
45
  allow_failure: true,
46
+ ...createArtifactsConfig(
47
+ context.componentConfig.dir,
48
+ buildConfig.audit?.artifactsReports,
49
+ buildConfig.audit?.artifacts
50
+ ),
45
51
  }
46
52
  : null;
47
53
 
@@ -57,6 +63,11 @@ export const createNodeTestJobs = (context: Context): CatladderJob[] => {
57
63
  ...yarnInstall,
58
64
  ...(ensureArray(buildConfig.lint?.command) ?? ["yarn lint"]),
59
65
  ],
66
+ ...createArtifactsConfig(
67
+ context.componentConfig.dir,
68
+ buildConfig.lint?.artifactsReports,
69
+ buildConfig.lint?.artifacts
70
+ ),
60
71
  }
61
72
  : null;
62
73
  const testJob: CatladderJob | null =
@@ -73,6 +84,11 @@ export const createNodeTestJobs = (context: Context): CatladderJob[] => {
73
84
  ...yarnInstall,
74
85
  ...(ensureArray(buildConfig.test?.command) ?? ["yarn test"]),
75
86
  ],
87
+ ...createArtifactsConfig(
88
+ context.componentConfig.dir,
89
+ buildConfig.test?.artifactsReports,
90
+ buildConfig.test?.artifacts
91
+ ),
76
92
  }
77
93
  : null;
78
94
  return [auditJob, lintJob, testJob].filter(notNil);
@@ -2,6 +2,8 @@ import type { Context } from "../..";
2
2
  import { isOfBuildType } from "../types";
3
3
  import type { CatladderJob } from "../../types/jobs";
4
4
  import { createDockerBuildJobBase, gitlabDockerLogin } from "../docker";
5
+ import { sbomDeactivated } from "../../deploy/sbom";
6
+ import { createSbomBuildJob } from "../sbom";
5
7
 
6
8
  export const createRailsBuildJobs = (context: Context): CatladderJob[] => {
7
9
  const buildConfig = context.componentConfig.build;
@@ -37,5 +39,6 @@ export const createRailsBuildJobs = (context: Context): CatladderJob[] => {
37
39
  }`,
38
40
  ],
39
41
  }),
42
+ ...(sbomDeactivated(context) ? [] : [createSbomBuildJob(context)]),
40
43
  ];
41
44
  };
@@ -0,0 +1,43 @@
1
+ import type { Context } from "../types/context";
2
+ import type { CatladderJob } from "../types/jobs";
3
+ import { ensureArray } from "../utils";
4
+
5
+ export const SBOM_BUILD_JOB_NAME = "🧾 sbom";
6
+ export const SBOM_FILE = "__sbom.json";
7
+
8
+ export const createSbomBuildJob = (context: Context): CatladderJob => {
9
+ const buildConfig = context.componentConfig.build;
10
+
11
+ const defaultImage = "aquasec/trivy:0.38.3";
12
+ const defaultScript = [
13
+ `trivy fs --quiet --format cyclonedx --output "${SBOM_FILE}" ${
14
+ context.packageManagerInfo?.componentIsInWorkspace
15
+ ? "."
16
+ : context.componentConfig.dir
17
+ }`,
18
+ ];
19
+
20
+ const image =
21
+ buildConfig.type === "custom" && buildConfig.sbom !== false
22
+ ? buildConfig.sbom?.jobImage ?? defaultImage
23
+ : defaultImage;
24
+
25
+ const script =
26
+ buildConfig.type === "custom" && buildConfig.sbom !== false
27
+ ? ensureArray(buildConfig.sbom?.command) ?? defaultScript
28
+ : defaultScript;
29
+
30
+ return {
31
+ name: SBOM_BUILD_JOB_NAME,
32
+ stage: "build",
33
+ envMode: "jobPerEnv",
34
+ variables: {},
35
+ cache: undefined,
36
+ image,
37
+ script,
38
+ allow_failure: true,
39
+ artifacts: {
40
+ paths: [SBOM_FILE],
41
+ },
42
+ };
43
+ };
@@ -1,4 +1,9 @@
1
- import type { EnvVars, GitlabJobImage, GitlabJobService } from "../types";
1
+ import type {
2
+ Artifacts,
3
+ EnvVars,
4
+ GitlabJobImage,
5
+ GitlabJobService,
6
+ } from "../types";
2
7
 
3
8
  import type { CatladderJob } from "../types/jobs";
4
9
 
@@ -12,6 +17,22 @@ export type BuildConfigArtifactsReports = {
12
17
  junit?: string[];
13
18
  };
14
19
 
20
+ export type TestJobCustom = {
21
+ command?: string | string[];
22
+ jobImage?: GitlabJobImage;
23
+ /**
24
+ * additional CI/CD artifacts reports,
25
+ * use to display information in merge requests, pipeline views and security dashboards.
26
+ */
27
+ artifactsReports?: BuildConfigArtifactsReports;
28
+ /**
29
+ * GitLab {@link Artifacts} configuration.
30
+ *
31
+ * {@link TestJobCustom.artifacts}.reports.junit is merged with {@link TestJobCustom.artifactsReports} in case both given.
32
+ */
33
+ artifacts?: Artifacts;
34
+ };
35
+
15
36
  export type BuildConfigBase = {
16
37
  /**
17
38
  * command to run on the image to start the app (e.g. yarn start)
@@ -38,39 +59,38 @@ export type BuildConfigBase = {
38
59
  * customize docker build
39
60
  */
40
61
  docker?: {
62
+ /**
63
+ * Custom Dockerfile lines integrated in the generated Dockerfile before the standard build steps.
64
+ *
65
+ * - [runner-images/docker-build/scripts/ensureNodeDockerfile](https://git.panter.ch/catladder/catladder/-/tree/main/runner-images/docker-build/scripts/ensureNodeDockerfile)
66
+ * - [runner-images/docker-build/scripts/ensureNginxDockerfile](https://git.panter.ch/catladder/catladder/-/tree/main/runner-images/docker-build/scripts/ensureNginxDockerfile)
67
+ * - [runner-images/docker-build/scripts/ensureMeteorDockerfile](https://git.panter.ch/catladder/catladder/-/tree/main/runner-images/docker-build/scripts/ensureMeteorDockerfile)
68
+ */
41
69
  additionsBegin?: string[];
70
+ /**
71
+ * Custom Dockerfile lines integrated in the generated Dockerfile after the standard build steps.
72
+ *
73
+ * - [runner-images/docker-build/scripts/ensureNodeDockerfile](https://git.panter.ch/catladder/catladder/-/tree/main/runner-images/docker-build/scripts/ensureNodeDockerfile)
74
+ * - [runner-images/docker-build/scripts/ensureNginxDockerfile](https://git.panter.ch/catladder/catladder/-/tree/main/runner-images/docker-build/scripts/ensureNginxDockerfile)
75
+ * - [runner-images/docker-build/scripts/ensureMeteorDockerfile](https://git.panter.ch/catladder/catladder/-/tree/main/runner-images/docker-build/scripts/ensureMeteorDockerfile)
76
+ */
42
77
  additionsEnd?: string[];
43
78
  };
44
79
 
45
80
  /**
46
81
  * customize lint, set false to disable
47
82
  */
48
- lint?:
49
- | false
50
- | {
51
- command?: string | string[];
52
- jobImage?: GitlabJobImage;
53
- };
83
+ lint?: false | TestJobCustom;
54
84
 
55
85
  /**
56
86
  * customize test, set false to disable
57
87
  */
58
- test?:
59
- | false
60
- | {
61
- command?: string | string[];
62
- jobImage?: GitlabJobImage;
63
- };
88
+ test?: false | TestJobCustom;
64
89
 
65
90
  /**
66
91
  * customize audit, set false to disable
67
92
  */
68
- audit?:
69
- | false
70
- | {
71
- command?: string | string[];
72
- jobImage?: GitlabJobImage;
73
- };
93
+ audit?: false | TestJobCustom;
74
94
 
75
95
  /**
76
96
  * additional paths for artifacts,
@@ -147,6 +167,9 @@ export type BuildConfigCustom = Omit<
147
167
  > & {
148
168
  type: "custom";
149
169
  jobImage: GitlabJobImage;
170
+ /**
171
+ * {@link GitlabJobService}s used in lint, test, audit, and build jobs.
172
+ */
150
173
  jobServices?: GitlabJobService[];
151
174
 
152
175
  docker: BuildConfigCustomDocker;
@@ -154,41 +177,17 @@ export type BuildConfigCustom = Omit<
154
177
  /**
155
178
  * custom lint, disabled when not set
156
179
  */
157
- lint?: {
158
- command?: string | string[];
159
- jobImage?: GitlabJobImage;
160
- /**
161
- * additional CI/CD artifacts reports,
162
- * use to display information in merge requests, pipeline views and security dashboards.
163
- */
164
- artifactsReports?: BuildConfigArtifactsReports;
165
- };
180
+ lint?: TestJobCustom;
166
181
 
167
182
  /**
168
183
  * custom test, disabled when not set
169
184
  */
170
- test?: {
171
- command?: string | string[];
172
- jobImage?: GitlabJobImage;
173
- /**
174
- * additional CI/CD artifacts reports,
175
- * use to display information in merge requests, pipeline views and security dashboards.
176
- */
177
- artifactsReports?: BuildConfigArtifactsReports;
178
- };
185
+ test?: TestJobCustom;
179
186
 
180
187
  /**
181
188
  * custom audit, disabled when not set
182
189
  */
183
- audit?: {
184
- command?: string | string[];
185
- jobImage?: GitlabJobImage;
186
- /**
187
- * additional CI/CD artifacts reports,
188
- * use to display information in merge requests, pipeline views and security dashboards.
189
- */
190
- artifactsReports?: BuildConfigArtifactsReports;
191
- };
190
+ audit?: TestJobCustom;
192
191
 
193
192
  /**
194
193
  * custom sbom (software bill of materials), set false to disable
@@ -1,6 +1,8 @@
1
1
  import { getDockerImageVariables, requiresDockerBuild } from "../build/docker";
2
+ import { SBOM_BUILD_JOB_NAME } from "../build/sbom";
2
3
  import type { Context } from "../types";
3
4
  import type { CatladderJob } from "../types/jobs";
5
+ import { sbomDeactivated } from "./sbom";
4
6
  import { contextIsStoppable } from "./utils";
5
7
 
6
8
  export const DEPLOY_JOB_NAME = "🚀 Deploy";
@@ -43,13 +45,18 @@ export const getBaseDeploymentJob = (context: Context): JobWithoutScript => {
43
45
  name: DEPLOY_JOB_NAME,
44
46
  envMode: "stagePerEnv", // makes it easier to run manual tasks er env
45
47
 
46
- needs: context.componentConfig.deploy
47
- ? context.componentConfig.deploy.waitFor?.map((c) => ({
48
- componentName: c,
49
- job: DEPLOY_JOB_NAME,
50
- artifacts: false,
51
- })) ?? undefined
52
- : undefined,
48
+ needs: [
49
+ ...(sbomDeactivated(context)
50
+ ? []
51
+ : [{ job: SBOM_BUILD_JOB_NAME, artifacts: true }]),
52
+ ...(context.componentConfig.deploy
53
+ ? context.componentConfig.deploy.waitFor?.map((c) => ({
54
+ componentName: c,
55
+ job: DEPLOY_JOB_NAME,
56
+ artifacts: false,
57
+ })) ?? []
58
+ : []),
59
+ ],
53
60
  // we don't want to deploy when there is a broken test
54
61
  needsStages: [
55
62
  {
@@ -22,6 +22,10 @@ import {
22
22
  import { allowFailureInScripts } from "../../utils/gitlab";
23
23
  import { getCloudRunJobName } from "./utils/jobName";
24
24
  import { createArgsString } from "./utils/createArgsString";
25
+ import {
26
+ getDependencyTrackDeleteScript,
27
+ getDependencyTrackUploadScript,
28
+ } from "../sbom";
25
29
 
26
30
  const setExtraVarsScripts = (deployConfig: DeployConfigCloudRun) => [
27
31
  `export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe ${deployConfig.projectId} --format="value(projectNumber)")`,
@@ -234,6 +238,7 @@ export const createGoogleCloudRunDeployJobs = (
234
238
  ...getJobRunScripts("postDeploy"),
235
239
 
236
240
  `docker image rm ${gcloudImageName}`,
241
+ ...getDependencyTrackUploadScript(context),
237
242
  ];
238
243
 
239
244
  const stopScripts = [
@@ -250,6 +255,7 @@ export const createGoogleCloudRunDeployJobs = (
250
255
  ...(deployConfig.cloudSql && deployConfig.cloudSql.deleteDatabaseOnStop
251
256
  ? getDatabaseDeleteScript(context, deployConfig)
252
257
  : []),
258
+ ...getDependencyTrackDeleteScript(context),
253
259
  ];
254
260
  return [
255
261
  merge({}, baseDeploymentJob, getDockerJobBaseProps(context), {
@@ -6,6 +6,10 @@ import type { Context } from "../../types/context";
6
6
  import type { CatladderJob } from "../../types/jobs";
7
7
  import { getBaseDeploymentJob, getBaseDeploymentStopJob } from "../base";
8
8
  import { isOfDeployType } from "../types";
9
+ import {
10
+ getDependencyTrackDeleteScript,
11
+ getDependencyTrackUploadScript,
12
+ } from "../sbom";
9
13
 
10
14
  export const createCustomDeployJobs = (context: Context): CatladderJob[] => {
11
15
  const deployConfig = context.componentConfig.deploy;
@@ -27,13 +31,17 @@ export const createCustomDeployJobs = (context: Context): CatladderJob[] => {
27
31
  `cd ${context.componentConfig.dir}`,
28
32
  ...(deployConfig.requiresYarnInstall ? yarnInstall : []),
29
33
  ...deployConfig.script,
34
+ ...getDependencyTrackUploadScript(context),
30
35
  ],
31
36
  }),
32
37
  ...(deployConfig.stopScript
33
38
  ? [
34
39
  merge({}, getBaseDeploymentStopJob(context), {
35
40
  image: deployConfig.jobImage ?? getRunnerImage("jobs-default"),
36
- script: deployConfig.stopScript,
41
+ script: [
42
+ ...deployConfig.stopScript,
43
+ ...getDependencyTrackDeleteScript(context),
44
+ ],
37
45
  }),
38
46
  ]
39
47
  : []),
@@ -11,6 +11,10 @@ import {
11
11
  } from "../base";
12
12
  import { isOfDeployType } from "../types";
13
13
  import { createKubeValues } from "./kubeValues";
14
+ import {
15
+ getDependencyTrackDeleteScript,
16
+ getDependencyTrackUploadScript,
17
+ } from "../sbom";
14
18
 
15
19
  export const createKubernetesDeployJobs = (
16
20
  context: Context
@@ -76,6 +80,7 @@ export const createKubernetesDeployJobs = (
76
80
  ...connectContext,
77
81
  "kubernetesCreateSecret",
78
82
  "kubernetesDeploy",
83
+ ...getDependencyTrackUploadScript(context),
79
84
  "echo deployment successful 😻",
80
85
  ],
81
86
  environment: {
@@ -83,7 +88,11 @@ export const createKubernetesDeployJobs = (
83
88
  },
84
89
  }),
85
90
  merge({}, baseStopJob, shared, {
86
- script: [...connectContext, "kubernetesDelete"],
91
+ script: [
92
+ ...connectContext,
93
+ "kubernetesDelete",
94
+ ...getDependencyTrackDeleteScript(context),
95
+ ],
87
96
  environment: {
88
97
  kubernetes: kubernetesEnvironment,
89
98
  },
@@ -0,0 +1,24 @@
1
+ import type { Context } from "../types/context";
2
+ import { SBOM_FILE } from "../build/sbom";
3
+
4
+ export const sbomDeactivated = (context: Context) =>
5
+ context.componentConfig.build.type === "custom" &&
6
+ context.componentConfig.build.sbom === false;
7
+
8
+ export const getDependencyTrackUploadScript = (context: Context): string[] => {
9
+ return sbomDeactivated(context)
10
+ ? []
11
+ : [
12
+ "echo Uploading SBOM to Dependency Track",
13
+ `/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" upload "${context.fullConfig.customerName}-${context.fullConfig.appName}/${context.componentName}" "${context.environment.url}" "${SBOM_FILE}" vex.json || true`,
14
+ ];
15
+ };
16
+
17
+ export const getDependencyTrackDeleteScript = (context: Context): string[] => {
18
+ return sbomDeactivated(context)
19
+ ? []
20
+ : [
21
+ "echo Disabling component in Dependency Track",
22
+ `/dtrackuploader https://dep.panter.swiss/ "$DT_KEY_PROD" disable "${context.fullConfig.customerName}-${context.fullConfig.appName}/${context.componentName}" "${context.environment.url}" || true`,
23
+ ];
24
+ };
@@ -1,6 +1,5 @@
1
1
  import { isFunction } from "lodash";
2
2
  import { BUILD_TYPES } from "../build";
3
- import { createReportingJobs } from "../verify/reporting";
4
3
  import { createContext } from "../context";
5
4
  import { DEPLOY_TYPES } from "../deploy";
6
5
  import type { Config, PipelineTrigger } from "../types/config";
@@ -36,10 +35,9 @@ const createRawJobs = (context: Context): CatladderJob[] => {
36
35
  context.componentConfig.deploy !== false
37
36
  ? DEPLOY_TYPES[context.componentConfig.deploy.type].jobs(context)
38
37
  : [];
39
- const reportingJobs = createReportingJobs(context);
40
38
 
41
39
  const customJobs = getCustomJobs(context);
42
- return [...buildJobs, ...deployJobs, ...reportingJobs, ...customJobs];
40
+ return [...buildJobs, ...deployJobs, ...customJobs];
43
41
  };
44
42
  export const createJobsForComponent = async (
45
43
  config: Config,
@@ -72,10 +72,10 @@ export const makeGitlabJob = (
72
72
  }));
73
73
  });
74
74
  const cleanedNeeds: CatladderJob["needs"] = [
75
+ ...(needsFromStages ?? []),
75
76
  ...(needs ?? []),
76
77
  // pull in legacy needs from other component, which is now identical to needs
77
78
  ...(needsOtherComponent ?? []),
78
- ...(needsFromStages ?? []),
79
79
  ];
80
80
 
81
81
  const gitlabNeeds: GitlabJobDef["needs"] = cleanedNeeds
@@ -94,6 +94,10 @@ export const makeGitlabJob = (
94
94
  ) // sort in a predictable manner for snapshot tests
95
95
  .sort((a, b) => getJobName(a).localeCompare(getJobName(b)));
96
96
 
97
+ const deduplicatedGitlabNeeds: GitlabJobDef["needs"] = [
98
+ ...new Map(gitlabNeeds.map((n) => [isObject(n) ? n.job : n, n])).values(),
99
+ ];
100
+
97
101
  const fullJobName = getFullJobName(
98
102
  name,
99
103
  componentName,
@@ -116,7 +120,7 @@ export const makeGitlabJob = (
116
120
  }
117
121
  : job.environment,
118
122
  // sort in a predictable manner for snapshot tests
119
- needs: gitlabNeeds,
123
+ needs: deduplicatedGitlabNeeds,
120
124
  retry: BASE_RETRY,
121
125
  interruptible: true,
122
126
  });
@@ -2,19 +2,19 @@ export type Artifacts = {
2
2
  paths: string[];
3
3
  expire_in?: string;
4
4
  when?: "always" | "on_success" | "on_failure";
5
- reports?: ArtifactReports;
5
+ // Reports won't show up on MRs until https://gitlab.com/groups/gitlab-org/-/epics/8205
6
+ reports?: {
7
+ accessibility?: string | string[];
8
+ coverage_report?: { coverage_format: string; path: string };
9
+ codequality?: string | string[];
10
+ cyclonedx?: string | string[];
11
+ dotenv?: string | string[];
12
+ junit?: string | string[];
13
+ sast?: string;
14
+ secret_detection?: string;
15
+ terraform?: string;
16
+ };
6
17
  };
7
- // Reports won't show up on MRs until https://gitlab.com/groups/gitlab-org/-/epics/8205
8
- export type ArtifactReports =
9
- | { accessibility: string | string[] }
10
- | { coverage_report: { coverage_format: string; path: string } }
11
- | { codequality: string | string[] }
12
- | { cyclonedx: string | string[] }
13
- | { dotenv: string | string[] }
14
- | { junit: string | string[] }
15
- | { sast: string }
16
- | { secret_detection: string }
17
- | { terraform: string };
18
18
  export type GitlabJobCache = {
19
19
  key: GitlabJobCacheKey;
20
20
  policy?: string;
@@ -1,3 +0,0 @@
1
- import type { Context } from "../types/context";
2
- import type { CatladderJob } from "../types/jobs";
3
- export declare const createReportingJobs: (context: Context) => CatladderJob<"stop" | "setup" | "test" | "build" | "deploy" | "verify" | "rollback">[];
@@ -1,48 +0,0 @@
1
- "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.createReportingJobs = void 0;
5
- var base_1 = require("../deploy/base");
6
- var utils_1 = require("../utils");
7
- var STAGE = "verify";
8
- var SBOM_GENERATE_JOB_NAME = "🧾 sbom";
9
- var SBOM_FILE = "__sbom.json";
10
- var createSbomGenerateJob = function (context) {
11
- var _a, _b, _c, _d, _e;
12
- var buildConfig = context.componentConfig.build;
13
- var defaultImage = "aquasec/trivy:0.38.3";
14
- var defaultScript = ["trivy fs --quiet --format cyclonedx --output \"".concat(SBOM_FILE, "\" ").concat(((_a = context.packageManagerInfo) === null || _a === void 0 ? void 0 : _a.componentIsInWorkspace) ? "." : context.componentConfig.dir)];
15
- var image = buildConfig.type === "custom" && buildConfig.sbom !== false ? (_c = (_b = buildConfig.sbom) === null || _b === void 0 ? void 0 : _b.jobImage) !== null && _c !== void 0 ? _c : defaultImage : defaultImage;
16
- var script = buildConfig.type === "custom" && buildConfig.sbom !== false ? (_e = (0, utils_1.ensureArray)((_d = buildConfig.sbom) === null || _d === void 0 ? void 0 : _d.command)) !== null && _e !== void 0 ? _e : defaultScript : defaultScript;
17
- return {
18
- name: SBOM_GENERATE_JOB_NAME,
19
- stage: STAGE,
20
- needs: context.componentConfig.deploy !== false ? [base_1.DEPLOY_JOB_NAME] : [],
21
- envMode: "jobPerEnv",
22
- variables: {},
23
- cache: undefined,
24
- image: image,
25
- script: script,
26
- allow_failure: true,
27
- artifacts: {
28
- paths: [SBOM_FILE]
29
- }
30
- };
31
- };
32
- var createSbomUploadJob = function (context) {
33
- return {
34
- name: "🧾 sbom upload",
35
- stage: STAGE,
36
- needs: [SBOM_GENERATE_JOB_NAME],
37
- envMode: "jobPerEnv",
38
- variables: {},
39
- cache: undefined,
40
- image: "git.panter.ch:5001/open-source/dependency-track-uploader:dtrackuploader-v0.2.1",
41
- script: ["/dtrackuploader https://dep.panter.swiss/ \"$DT_KEY_PROD\" upload \"".concat(context.fullConfig.customerName, "-").concat(context.fullConfig.appName, "/").concat(context.componentName, "\" \"").concat(context.environment.shortName, "\" \"").concat(SBOM_FILE, "\" vex.json")],
42
- allow_failure: true
43
- };
44
- };
45
- var createReportingJobs = function (context) {
46
- return context.componentConfig.build.type === "custom" && context.componentConfig.build.sbom === false ? [] : [createSbomGenerateJob(context), createSbomUploadJob(context)];
47
- };
48
- exports.createReportingJobs = createReportingJobs;