@catladder/pipeline 1.89.0 โ†’ 1.89.2

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 (32) hide show
  1. package/dist/build/rails/build.js +4 -8
  2. package/dist/build/rails/test.js +1 -2
  3. package/dist/bundles/catladder-gitlab/index.js +3 -3
  4. package/dist/constants.js +1 -1
  5. package/dist/pipeline/createAllJobs.d.ts +8 -0
  6. package/dist/pipeline/createAllJobs.js +164 -0
  7. package/dist/pipeline/createChildPipeline.js +24 -48
  8. package/dist/pipeline/createJobsForComponent.d.ts +3 -0
  9. package/dist/pipeline/{createJobs.js โ†’ createJobsForComponent.js} +8 -100
  10. package/dist/pipeline/gitlab/createGitlabJobs.d.ts +14 -0
  11. package/dist/pipeline/gitlab/createGitlabJobs.js +260 -0
  12. package/dist/pipeline/index.d.ts +1 -1
  13. package/dist/pipeline/index.js +1 -1
  14. package/dist/tsconfig.tsbuildinfo +1 -1
  15. package/package.json +1 -1
  16. package/src/build/index.ts +1 -1
  17. package/src/build/node/cache.ts +2 -2
  18. package/src/build/rails/build.ts +9 -6
  19. package/src/build/rails/test.ts +43 -39
  20. package/src/config/configruedEnvs.ts +2 -8
  21. package/src/deploy/kubernetes/deployJob.ts +2 -1
  22. package/src/pipeline/createAllJobs.ts +38 -0
  23. package/src/pipeline/createChildPipeline.ts +6 -22
  24. package/src/pipeline/createJobsForComponent.ts +64 -0
  25. package/src/pipeline/gitlab/createGitlabJobs.ts +149 -0
  26. package/src/pipeline/index.ts +1 -1
  27. package/src/types/gitlab-types.ts +8 -6
  28. package/dist/pipeline/createJobs.d.ts +0 -3
  29. package/dist/pipeline/gitlab/makeGitlabJob.d.ts +0 -10
  30. package/dist/pipeline/gitlab/makeGitlabJob.js +0 -75
  31. package/src/pipeline/createJobs.ts +0 -196
  32. package/src/pipeline/gitlab/makeGitlabJob.ts +0 -25
@@ -17,66 +17,70 @@ export const createRailsTestJobs = (context: Context): CatladderJob[] => {
17
17
  envMode: "none",
18
18
  };
19
19
  const defaultImage = "docker.io/ruby";
20
- const bundlerCacheDir = "tmp/cache"
20
+ const bundlerCacheDir = "tmp/cache";
21
21
  const bundlerInstall = [
22
22
  `bundle config set path '${bundlerCacheDir}'`,
23
- "bundle install -j $(nproc)"
24
- ]
23
+ "bundle install -j $(nproc)",
24
+ ];
25
25
  const bundlerCache = {
26
26
  key: {
27
27
  files: ["Gemfile.lock"],
28
- prefix: "$CI_JOB_IMAGE" // a changed image might have different OS libraries which no longer work with the cached gems
28
+ prefix: "$CI_JOB_IMAGE", // a changed image might have different OS libraries which no longer work with the cached gems
29
29
  },
30
- paths: [bundlerCacheDir]
31
- }
30
+ paths: [bundlerCacheDir],
31
+ };
32
32
  const auditJob: CatladderJob | null =
33
33
  buildConfig.audit !== false
34
34
  ? {
35
- name: "๐Ÿ›ก audit",
35
+ name: "๐Ÿ›ก audit",
36
36
 
37
- ...base,
38
- cache: undefined, // audit does not need bundle install and no cache
39
- image: buildConfig.audit?.jobImage ?? defaultImage,
40
- script: [
41
- `cd ${context.componentConfig.dir}`,
42
- ...(ensureArray(buildConfig.audit?.command) ?? [
43
- "gem install bundler-audit",
44
- "bundle audit check"
45
- ]),
46
- ],
47
- allow_failure: true,
48
- }
37
+ ...base,
38
+ cache: undefined, // audit does not need bundle install and no cache
39
+ image: buildConfig.audit?.jobImage ?? defaultImage,
40
+ script: [
41
+ `cd ${context.componentConfig.dir}`,
42
+ ...(ensureArray(buildConfig.audit?.command) ?? [
43
+ "gem install bundler-audit",
44
+ "bundle audit check",
45
+ ]),
46
+ ],
47
+ allow_failure: true,
48
+ }
49
49
  : null;
50
50
 
51
51
  const lintJob: CatladderJob | null =
52
52
  buildConfig.lint !== false
53
53
  ? {
54
- name: "๐Ÿ‘ฎ lint",
54
+ name: "๐Ÿ‘ฎ lint",
55
55
 
56
- ...base,
57
- cache: bundlerCache,
58
- image: buildConfig.lint?.jobImage ?? defaultImage,
59
- script: [
60
- `cd ${context.componentConfig.dir}`,
61
- ...bundlerInstall,
62
- ...(ensureArray(buildConfig.lint?.command) ?? ["bundle exec rubocop"]),
63
- ],
64
- }
56
+ ...base,
57
+ cache: bundlerCache,
58
+ image: buildConfig.lint?.jobImage ?? defaultImage,
59
+ script: [
60
+ `cd ${context.componentConfig.dir}`,
61
+ ...bundlerInstall,
62
+ ...(ensureArray(buildConfig.lint?.command) ?? [
63
+ "bundle exec rubocop",
64
+ ]),
65
+ ],
66
+ }
65
67
  : null;
66
68
  const testJob: CatladderJob | null =
67
69
  buildConfig.test !== false
68
70
  ? {
69
- name: "๐Ÿงช test",
71
+ name: "๐Ÿงช test",
70
72
 
71
- ...base,
72
- cache: bundlerCache,
73
- image: buildConfig.test?.jobImage ?? defaultImage,
74
- script: [
75
- `cd ${context.componentConfig.dir}`,
76
- ...bundlerInstall,
77
- ...(ensureArray(buildConfig.test?.command) ?? ["bundle exec rspec"]),
78
- ],
79
- }
73
+ ...base,
74
+ cache: bundlerCache,
75
+ image: buildConfig.test?.jobImage ?? defaultImage,
76
+ script: [
77
+ `cd ${context.componentConfig.dir}`,
78
+ ...bundlerInstall,
79
+ ...(ensureArray(buildConfig.test?.command) ?? [
80
+ "bundle exec rspec",
81
+ ]),
82
+ ],
83
+ }
80
84
  : null;
81
85
  return [auditJob, lintJob, testJob].filter(notNil);
82
86
  };
@@ -1,11 +1,5 @@
1
- import type {
2
- Config,
3
- EnvType,
4
- PipelineTrigger} from "../types";
5
- import {
6
- DEFAULT_ENV_TYPES,
7
- getEnvTypesByTrigger
8
- } from "../types";
1
+ import type { Config, EnvType, PipelineTrigger } from "../types";
2
+ import { DEFAULT_ENV_TYPES, getEnvTypesByTrigger } from "../types";
9
3
 
10
4
  const getConfiguredAndDefaultEnvs = (
11
5
  config: Config,
@@ -40,7 +40,8 @@ export const createKubernetesDeployJobs = (
40
40
  quotingType: "'",
41
41
  forceQuotes: true,
42
42
  }),
43
- HELM_GITLAB_CHART_NAME: deployConfig.chartName ?? "/helm-charts/the-panter-chart",
43
+ HELM_GITLAB_CHART_NAME:
44
+ deployConfig.chartName ?? "/helm-charts/the-panter-chart",
44
45
  HELM_ARGS: [
45
46
  ...(deployConfig.debug ? ["--debug"] : []),
46
47
  ...(deployConfig.additionalHelmArgs ?? []),
@@ -0,0 +1,38 @@
1
+ import { getAllEnvsByTrigger } from "../config";
2
+ import type { Config, PipelineTrigger } from "../types";
3
+ import type { CatladderJob } from "../types/jobs";
4
+ import { createJobsForComponent } from "./createJobsForComponent";
5
+
6
+ export type AllCatladderJobs = {
7
+ [componentName: string]: {
8
+ [env: string]: Array<CatladderJob>;
9
+ };
10
+ };
11
+ export const createAllJobs = async (
12
+ config: Config,
13
+ trigger: PipelineTrigger
14
+ ): Promise<AllCatladderJobs> => {
15
+ return Object.fromEntries(
16
+ await Promise.all(
17
+ Object.keys(config.components).map(async (componentName) => {
18
+ const envs = getAllEnvsByTrigger(config, componentName, trigger);
19
+ return [
20
+ componentName,
21
+ Object.fromEntries(
22
+ await Promise.all(
23
+ envs.map(async (env) => [
24
+ env,
25
+ await createJobsForComponent(
26
+ config,
27
+ componentName,
28
+ env,
29
+ trigger
30
+ ),
31
+ ])
32
+ )
33
+ ),
34
+ ];
35
+ })
36
+ )
37
+ );
38
+ };
@@ -1,34 +1,18 @@
1
- import { getAllEnvsByTrigger, getAllEnvsInAllComponents } from "../config";
1
+ import { getAllEnvsInAllComponents } from "../config";
2
2
  import { RULES_ALWAYS } from "../rules";
3
3
  import { getRunnerImage } from "../runner";
4
- import type {
5
- GitlabPipeline,
6
- Pipeline,
7
- PipelineJob,
8
- PipelineType,
9
- } from "../types";
4
+ import type { GitlabPipeline, Pipeline, PipelineType } from "../types";
10
5
  import type { Config, PipelineTrigger } from "../types/config";
11
6
  import { BASE_STAGES } from "../types/jobs";
12
- import { createJobs } from "./createJobs";
7
+ import { createAllJobs } from "./createAllJobs";
8
+ import { createGitlabJobs } from "./gitlab/createGitlabJobs";
13
9
 
14
10
  export const createChildPipeline = async <T extends PipelineType>(
15
11
  type: T,
16
12
  trigger: PipelineTrigger,
17
13
  config: Config
18
14
  ): Promise<Pipeline<T>> => {
19
- const components = Object.keys(config.components);
20
-
21
- // 2. write the triggering pipeline
22
- const jobs = await components.reduce<Promise<Record<string, PipelineJob<T>>>>(
23
- async (acc, componentName) => {
24
- const envs = getAllEnvsByTrigger(config, componentName, trigger);
25
- return {
26
- ...(await acc),
27
- ...(await createJobs(type, envs, config, componentName, trigger)),
28
- };
29
- },
30
- Promise.resolve({})
31
- );
15
+ const jobs = await createAllJobs(config, trigger);
32
16
 
33
17
  // while technically not required, we group different envs in its own stage
34
18
  // each job from `createJobs` that is defined as `envMode: "stagePerEnv"` will have `deploy dev`, etc. instead of just `deploy`
@@ -53,7 +37,7 @@ export const createChildPipeline = async <T extends PipelineType>(
53
37
  rules: RULES_ALWAYS,
54
38
  },
55
39
  stages,
56
- jobs,
40
+ jobs: await createGitlabJobs(jobs),
57
41
  };
58
42
  return pipeline as Pipeline<T>;
59
43
  }
@@ -0,0 +1,64 @@
1
+ import { isFunction } from "lodash";
2
+ import { BUILD_TYPES } from "../build";
3
+ import { createContext } from "../context";
4
+ import { DEPLOY_TYPES } from "../deploy";
5
+ import type { Config, PipelineTrigger } from "../types/config";
6
+ import type { CommitInfo, Context } from "../types/context";
7
+ import type { CatladderJob } from "../types/jobs";
8
+ import { getBaseCommitInfo } from "./commitInfo/getCommitInfo";
9
+ import { getPackageManagerInfo } from "./packageManager";
10
+
11
+ const injectDefaultVarsInCustomJobs = (
12
+ context: Context,
13
+ jobs: CatladderJob[]
14
+ ) =>
15
+ jobs.map(({ variables, ...job }) => ({
16
+ variables: {
17
+ ...(context.environment.envVars ?? {}),
18
+ ...(variables ?? {}),
19
+ },
20
+ ...job,
21
+ }));
22
+ const getCustomJobs = (context: Context) => {
23
+ if (!context.componentConfig.customJobs) {
24
+ return [];
25
+ }
26
+ const rawJobs = isFunction(context.componentConfig.customJobs)
27
+ ? context.componentConfig.customJobs(context)
28
+ : context.componentConfig.customJobs;
29
+ return injectDefaultVarsInCustomJobs(context, rawJobs);
30
+ };
31
+ const createRawJobs = (context: Context): CatladderJob[] => {
32
+ if (context.componentConfig.deploy === false) {
33
+ return [];
34
+ }
35
+ const buildJobs =
36
+ BUILD_TYPES[context.componentConfig.build.type].jobs(context);
37
+ const deployJobs =
38
+ DEPLOY_TYPES[context.componentConfig.deploy.type].jobs(context);
39
+
40
+ const customJobs = getCustomJobs(context);
41
+ return [...buildJobs, ...deployJobs, ...customJobs];
42
+ };
43
+ export const createJobsForComponent = async (
44
+ config: Config,
45
+ componentName: string,
46
+ env: string,
47
+ trigger: PipelineTrigger
48
+ ): Promise<Array<CatladderJob>> => {
49
+ const commitInfo: CommitInfo = {
50
+ ...(await getBaseCommitInfo()),
51
+ trigger,
52
+ };
53
+
54
+ const packageManagerInfo = await getPackageManagerInfo(config, componentName);
55
+
56
+ const context = await createContext(
57
+ config,
58
+ componentName,
59
+ env,
60
+ commitInfo,
61
+ packageManagerInfo
62
+ );
63
+ return createRawJobs(context);
64
+ };
@@ -0,0 +1,149 @@
1
+ import { isObject } from "lodash";
2
+ import { BASE_RETRY } from "../../defaults";
3
+ import type { GitlabJobDef } from "../../types";
4
+ import type { CatladderJob, CatladderJobNeed } from "../../types/jobs";
5
+ import type { AllCatladderJobs } from "../createAllJobs";
6
+
7
+ type AllGitlabJobs = Record<string, GitlabJobDef>;
8
+
9
+ const getFullJobName = (
10
+ name: string,
11
+ componentName: string,
12
+ env?: string | null
13
+ ) => {
14
+ if (env) {
15
+ return `${componentName} ${name} | ${env} `;
16
+ }
17
+ return `${componentName} ${name}`;
18
+ };
19
+
20
+ const getFullReferencedJobName = (
21
+ referencedJobName: string,
22
+ componentName: string,
23
+ env: string,
24
+ allJobs: AllCatladderJobs
25
+ ) => {
26
+ const referencedJob = allJobs[componentName]?.[env]?.find(
27
+ (j) => j.name === referencedJobName
28
+ );
29
+ if (!referencedJob) {
30
+ throw new Error(
31
+ `unknown job referenced: '${referencedJobName}' from '${env}:${componentName}'`
32
+ );
33
+ }
34
+ const envToSet = referencedJob.envMode !== "none" ? env : null;
35
+ return getFullJobName(referencedJobName, componentName, envToSet);
36
+ };
37
+
38
+ const getJobName = (need: CatladderJobNeed) =>
39
+ isObject(need) ? need.job : need;
40
+
41
+ export const makeGitlabJob = (
42
+ componentName: string,
43
+ env: string,
44
+ {
45
+ envMode,
46
+ needsStages,
47
+ needsOtherComponent,
48
+ name,
49
+ needs,
50
+ ...job
51
+ }: CatladderJob<string>,
52
+ allJobs: AllCatladderJobs
53
+ ): [fullName: string, job: GitlabJobDef] => {
54
+ const stage = envMode === "stagePerEnv" ? `${job.stage} ${env}` : job.stage;
55
+
56
+ const needsFromStages: CatladderJob["needs"] = needsStages?.flatMap((n) => {
57
+ const referencedComponentName = componentName;
58
+ const allJobNamesFromThatStage =
59
+ allJobs[referencedComponentName]?.[env]
60
+ ?.filter((j) => j.stage === n.stage)
61
+ ?.map((j) => j.name) ?? [];
62
+
63
+ return allJobNamesFromThatStage.map((job) => ({
64
+ job,
65
+ artifacts: n.artifacts ?? false,
66
+ componentName: referencedComponentName,
67
+ }));
68
+ });
69
+ const cleanedNeeds: CatladderJob["needs"] = [
70
+ ...(needs ?? []),
71
+ // pull in legacy needs from other component, which is now identical to needs
72
+ ...(needsOtherComponent ?? []),
73
+ ...(needsFromStages ?? []),
74
+ ];
75
+
76
+ const gitlabNeeds: GitlabJobDef["needs"] = cleanedNeeds
77
+ ?.map((n) =>
78
+ isObject(n)
79
+ ? {
80
+ job: getFullReferencedJobName(
81
+ n.job,
82
+ n.componentName ?? componentName,
83
+ env,
84
+ allJobs
85
+ ),
86
+ artifacts: n.artifacts,
87
+ }
88
+ : getFullReferencedJobName(n, componentName, env, allJobs)
89
+ ) // sort in a predictable manner for snapshot tests
90
+ .sort((a, b) => getJobName(a).localeCompare(getJobName(b)));
91
+
92
+ const fullJobName = getFullJobName(
93
+ name,
94
+ componentName,
95
+ envMode !== "none" ? env : undefined
96
+ );
97
+
98
+ const gitlabJob = {
99
+ ...job,
100
+ stage,
101
+ environment: job.environment?.on_stop
102
+ ? {
103
+ ...job.environment,
104
+ on_stop: getFullReferencedJobName(
105
+ job.environment.on_stop,
106
+ componentName,
107
+ env,
108
+ allJobs
109
+ ),
110
+ }
111
+ : job.environment,
112
+ // sort in a predictable manner for snapshot tests
113
+ needs: gitlabNeeds,
114
+ retry: BASE_RETRY,
115
+ interruptible: true,
116
+ };
117
+
118
+ return [fullJobName, gitlabJob];
119
+ };
120
+
121
+ export const createGitlabJobs = async (
122
+ allJobs: AllCatladderJobs
123
+ ): Promise<AllGitlabJobs> => {
124
+ return Object.keys(allJobs).reduce((accForComponents, componentName) => {
125
+ const componentJobs = allJobs[componentName];
126
+ return {
127
+ ...accForComponents,
128
+ ...Object.keys(componentJobs).reduce((accForEnvs, env) => {
129
+ const jobs = componentJobs[env];
130
+
131
+ return {
132
+ ...accForEnvs,
133
+ ...jobs.reduce((accForJobs, job) => {
134
+ const [fullJobName, gitlabJob] = makeGitlabJob(
135
+ componentName,
136
+ env,
137
+ job,
138
+ allJobs
139
+ );
140
+ return {
141
+ ...accForJobs,
142
+ [fullJobName]: gitlabJob,
143
+ };
144
+ }, {} as AllGitlabJobs),
145
+ };
146
+ }, {} as AllGitlabJobs),
147
+ };
148
+ }, {} as AllGitlabJobs);
149
+ };
@@ -1,2 +1,2 @@
1
1
  export * from "./createChildPipeline";
2
- export * from "./createJobs";
2
+ export * from "./createJobsForComponent";
@@ -5,7 +5,7 @@ export type Artifacts = {
5
5
  reports?: ArtifactReports;
6
6
  };
7
7
  // Reports won't show up on MRs until https://gitlab.com/groups/gitlab-org/-/epics/8205
8
- export type ArtifactReports =
8
+ export type ArtifactReports =
9
9
  | { accessibility: string | string[] }
10
10
  | { coverage_report: string | string[] }
11
11
  | { codequality: string | string[] }
@@ -14,7 +14,7 @@ export type ArtifactReports =
14
14
  | { junit: string | string[] }
15
15
  | { sast: string | string[] }
16
16
  | { secret_detection: string | string[] }
17
- | { terraform: string | string[] }
17
+ | { terraform: string | string[] };
18
18
  export type GitlabJobCache = {
19
19
  key: GitlabJobCacheKey;
20
20
  policy?: string;
@@ -43,10 +43,12 @@ export type GitlabJobService = {
43
43
  alias?: string;
44
44
  };
45
45
 
46
- export type GitlabJobImage = string | {
47
- name: string;
48
- entrypoint?: string[];
49
- }
46
+ export type GitlabJobImage =
47
+ | string
48
+ | {
49
+ name: string;
50
+ entrypoint?: string[];
51
+ };
50
52
 
51
53
  export type GitlabEnvironment = {
52
54
  url: string;
@@ -1,3 +0,0 @@
1
- import type { PipelineJob } from "../types";
2
- import type { Config, PipelineTrigger } from "../types/config";
3
- export declare const createJobs: <T extends "gitlab">(type: T, envs: string[], config: Config, componentName: string, trigger: PipelineTrigger) => Promise<Record<string, PipelineJob<T>>>;
@@ -1,10 +0,0 @@
1
- import type { GitlabJobDef } from "../../types";
2
- import type { CatladderJob } from "../../types/jobs";
3
- export declare const makeGitlabJob: ({
4
- envMode,
5
- needsStages,
6
- needsOtherComponent,
7
- name,
8
- needs,
9
- ...rest
10
- }: CatladderJob<string>) => GitlabJobDef;
@@ -1,75 +0,0 @@
1
- "use strict";
2
-
3
- var __assign = this && this.__assign || function () {
4
- __assign = Object.assign || function (t) {
5
- for (var s, i = 1, n = arguments.length; i < n; i++) {
6
- s = arguments[i];
7
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __rest = this && this.__rest || function (s, e) {
14
- var t = {};
15
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
16
- if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
18
- }
19
- return t;
20
- };
21
- var __read = this && this.__read || function (o, n) {
22
- var m = typeof Symbol === "function" && o[Symbol.iterator];
23
- if (!m) return o;
24
- var i = m.call(o),
25
- r,
26
- ar = [],
27
- e;
28
- try {
29
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
30
- } catch (error) {
31
- e = {
32
- error: error
33
- };
34
- } finally {
35
- try {
36
- if (r && !r.done && (m = i["return"])) m.call(i);
37
- } finally {
38
- if (e) throw e.error;
39
- }
40
- }
41
- return ar;
42
- };
43
- var __spreadArray = this && this.__spreadArray || function (to, from, pack) {
44
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
45
- if (ar || !(i in from)) {
46
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
47
- ar[i] = from[i];
48
- }
49
- }
50
- return to.concat(ar || Array.prototype.slice.call(from));
51
- };
52
- exports.__esModule = true;
53
- exports.makeGitlabJob = void 0;
54
- var lodash_1 = require("lodash");
55
- var defaults_1 = require("../../defaults");
56
- var getJobName = function (need) {
57
- return (0, lodash_1.isObject)(need) ? need.job : need;
58
- };
59
- var makeGitlabJob = function (_a) {
60
- var envMode = _a.envMode,
61
- needsStages = _a.needsStages,
62
- needsOtherComponent = _a.needsOtherComponent,
63
- name = _a.name,
64
- needs = _a.needs,
65
- rest = __rest(_a, ["envMode", "needsStages", "needsOtherComponent", "name", "needs"]);
66
- return __assign(__assign({}, rest), {
67
- // sort in a predictable manner for snapshot tests
68
- needs: needs ? __spreadArray([], __read(needs), false).sort(function (a, b) {
69
- return getJobName(a).localeCompare(getJobName(b));
70
- }) : undefined,
71
- retry: defaults_1.BASE_RETRY,
72
- interruptible: true
73
- });
74
- };
75
- exports.makeGitlabJob = makeGitlabJob;