@catladder/pipeline 0.0.0-fix-command-710f75f1 → 0.0.0-fix-error-sql-db-delete-b3878c2e

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 (98) hide show
  1. package/dist/build/custom/buildJob.js +1 -0
  2. package/dist/build/docker.d.ts +4 -18
  3. package/dist/build/docker.js +15 -9
  4. package/dist/build/index.js +7 -1
  5. package/dist/build/rails/build.js +37 -16
  6. package/dist/build/rails/index.d.ts +2 -2
  7. package/dist/build/rails/test.js +1 -2
  8. package/dist/build/types.d.ts +36 -4
  9. package/dist/bundles/catladder-gitlab/index.js +543 -218
  10. package/dist/constants.js +1 -1
  11. package/dist/context/getEnvironment.js +1 -0
  12. package/dist/context/getEnvironmentContext.js +5 -3
  13. package/dist/context/getEnvironmentVariables.d.ts +5 -1
  14. package/dist/context/getEnvironmentVariables.js +7 -2
  15. package/dist/deploy/base.js +1 -1
  16. package/dist/deploy/cloudRun/index.js +14 -6
  17. package/dist/deploy/custom/deployJob.js +6 -3
  18. package/dist/deploy/index.d.ts +2 -1
  19. package/dist/deploy/kubernetes/additionalSecretKeys.d.ts +3 -1
  20. package/dist/deploy/kubernetes/additionalSecretKeys.js +5 -1
  21. package/dist/deploy/kubernetes/deployJob.js +4 -4
  22. package/dist/deploy/kubernetes/kubeValues.d.ts +1 -0
  23. package/dist/deploy/kubernetes/kubeValues.js +9 -6
  24. package/dist/deploy/kubernetes/processSecretsAsFiles.d.ts +1 -0
  25. package/dist/deploy/types/custom.d.ts +2 -1
  26. package/dist/deploy/types/googleCloudRun.d.ts +5 -1
  27. package/dist/deploy/types/kubernetes.d.ts +9 -0
  28. package/dist/pipeline/createAllJobs.d.ts +8 -0
  29. package/dist/pipeline/createAllJobs.js +164 -0
  30. package/dist/pipeline/createChildPipeline.js +24 -48
  31. package/dist/pipeline/createJobsForComponent.d.ts +3 -0
  32. package/dist/pipeline/{createJobs.js → createJobsForComponent.js} +8 -105
  33. package/dist/pipeline/gitlab/createGitlabJobs.d.ts +14 -0
  34. package/dist/pipeline/gitlab/createGitlabJobs.js +260 -0
  35. package/dist/pipeline/index.d.ts +1 -1
  36. package/dist/pipeline/index.js +1 -1
  37. package/dist/tsconfig.tsbuildinfo +1 -1
  38. package/dist/types/config.d.ts +3 -3
  39. package/dist/types/context.d.ts +3 -1
  40. package/dist/types/environmentContext.d.ts +7 -0
  41. package/dist/types/gitlab-types.d.ts +5 -1
  42. package/dist/types/jobs.d.ts +9 -2
  43. package/dist/utils/gitlab.js +1 -1
  44. package/examples/__snapshots__/cloud-run-memory-limit.ts.snap +32 -32
  45. package/examples/__snapshots__/cloud-run-no-cpu-throttling.ts.snap +32 -32
  46. package/examples/__snapshots__/cloud-run-non-public.ts.snap +32 -32
  47. package/examples/__snapshots__/cloud-run-with-sql-reuse-db.ts.snap +3116 -0
  48. package/examples/__snapshots__/cloud-run-with-sql.ts.snap +65 -65
  49. package/examples/__snapshots__/custom-build-job.ts.snap +32 -32
  50. package/examples/__snapshots__/custom-deploy.ts.snap +1384 -0
  51. package/examples/__snapshots__/kubernetes-application-customization.ts.snap +2280 -0
  52. package/examples/__snapshots__/kubernetes-with-cloud-sql-legacy.ts.snap +2204 -0
  53. package/examples/__snapshots__/kubernetes-with-jobs.ts.snap +24 -24
  54. package/examples/__snapshots__/rails-k8s-with-worker.ts.snap +1911 -0
  55. package/examples/cloud-run-with-sql-reuse-db.ts +54 -0
  56. package/examples/custom-deploy.ts +25 -0
  57. package/examples/kubernetes-application-customization.ts +57 -0
  58. package/examples/kubernetes-with-cloud-sql-legacy.ts +33 -0
  59. package/examples/rails-k8s-with-worker.ts +95 -0
  60. package/package.json +1 -1
  61. package/src/build/custom/buildJob.ts +1 -0
  62. package/src/build/docker.ts +13 -6
  63. package/src/build/index.ts +7 -1
  64. package/src/build/node/cache.ts +2 -2
  65. package/src/build/rails/build.ts +20 -10
  66. package/src/build/rails/index.ts +2 -2
  67. package/src/build/rails/test.ts +43 -39
  68. package/src/build/types.ts +40 -5
  69. package/src/config/configruedEnvs.ts +2 -8
  70. package/src/context/getEnvironment.ts +1 -0
  71. package/src/context/getEnvironmentContext.ts +6 -6
  72. package/src/context/getEnvironmentVariables.ts +9 -4
  73. package/src/deploy/base.ts +1 -1
  74. package/src/deploy/cloudRun/deployJob.ts +1 -1
  75. package/src/deploy/cloudRun/index.ts +12 -4
  76. package/src/deploy/custom/deployJob.ts +9 -1
  77. package/src/deploy/index.ts +4 -1
  78. package/src/deploy/kubernetes/additionalSecretKeys.ts +1 -1
  79. package/src/deploy/kubernetes/deployJob.ts +2 -1
  80. package/src/deploy/kubernetes/kubeValues.ts +7 -5
  81. package/src/deploy/types/custom.ts +2 -1
  82. package/src/deploy/types/googleCloudRun.ts +6 -1
  83. package/src/deploy/types/kubernetes.ts +11 -1
  84. package/src/pipeline/createAllJobs.ts +38 -0
  85. package/src/pipeline/createChildPipeline.ts +6 -22
  86. package/src/pipeline/createJobsForComponent.ts +64 -0
  87. package/src/pipeline/gitlab/createGitlabJobs.ts +149 -0
  88. package/src/pipeline/index.ts +1 -1
  89. package/src/types/context.ts +3 -1
  90. package/src/types/environmentContext.ts +7 -0
  91. package/src/types/gitlab-types.ts +10 -3
  92. package/src/types/jobs.ts +11 -2
  93. package/src/utils/gitlab.ts +1 -1
  94. package/dist/pipeline/createJobs.d.ts +0 -3
  95. package/dist/pipeline/gitlab/makeGitlabJob.d.ts +0 -10
  96. package/dist/pipeline/gitlab/makeGitlabJob.js +0 -44
  97. package/src/pipeline/createJobs.ts +0 -199
  98. package/src/pipeline/gitlab/makeGitlabJob.ts +0 -23
@@ -5,17 +5,16 @@ import type { EnvironmentContext } from "../types/environmentContext";
5
5
  import { getEnvConfig } from "./getEnvConfig";
6
6
  import { getEnvType } from "./getEnvType";
7
7
 
8
- const getEnvironmentSlug = (
8
+ const getEnvironmentSlugPrefix = (
9
9
  envConfig: EnvConfigWithComponent,
10
10
  env: string,
11
- componentName: string,
12
11
  commitInfo?: CommitInfo
13
12
  ) => {
14
13
  const envType = getEnvType(env, envConfig);
15
14
 
16
15
  return envType === "review" && commitInfo
17
- ? `${env}-${commitInfo.reviewSlug}-${componentName}`
18
- : `${env}-${componentName}`;
16
+ ? `${env}-${commitInfo.reviewSlug}`
17
+ : `${env}`;
19
18
  };
20
19
 
21
20
  export const getEnvironmentContext = (
@@ -27,13 +26,13 @@ export const getEnvironmentContext = (
27
26
  const envConfigRaw = getEnvConfig(config, componentName, env);
28
27
  const envType = getEnvType(env, envConfigRaw);
29
28
 
30
- const environmentSlug = getEnvironmentSlug(
29
+ const environmentSlugPrefix = getEnvironmentSlugPrefix(
31
30
  envConfigRaw,
32
31
  env,
33
- componentName,
34
32
  commitInfo
35
33
  );
36
34
 
35
+ const environmentSlug = `${environmentSlugPrefix}-${componentName}`;
37
36
  const gitlabEnvironmentName =
38
37
  envType === "review" && commitInfo
39
38
  ? `${env}/${commitInfo.refName}/${componentName}`
@@ -45,6 +44,7 @@ export const getEnvironmentContext = (
45
44
  envConfigRaw,
46
45
  deployConfigRaw: envConfigRaw.deploy,
47
46
  buildConfigRaw: envConfigRaw.build,
47
+ environmentSlugPrefix,
48
48
  environmentSlug,
49
49
  gitlabEnvironmentName,
50
50
  fullName,
@@ -9,6 +9,11 @@ import {
9
9
  translateLegacyFromComponents,
10
10
  } from "./resolveReferences";
11
11
 
12
+ export type SecretEnvVar = {
13
+ key: string;
14
+ // hidden env vars are not shown in config-secrets
15
+ hidden?: boolean;
16
+ };
12
17
  export const getEnvironmentVariables = async (
13
18
  config: Config,
14
19
  componentName: string,
@@ -17,7 +22,7 @@ export const getEnvironmentVariables = async (
17
22
  alreadyVisited: Record<string, Record<string, boolean>> = {} // to prevent endless loop
18
23
  ): Promise<{
19
24
  envVars: Record<string, string>;
20
- secretEnvVarKeys: string[];
25
+ secretEnvVarKeys: SecretEnvVar[];
21
26
  host: string;
22
27
  url: string;
23
28
  }> => {
@@ -81,12 +86,12 @@ export const getEnvironmentVariables = async (
81
86
  )
82
87
  : [];
83
88
 
84
- const secretEnvVarKeys = [
85
- ...(envConfigRaw.vars?.secret ?? []),
89
+ const secretEnvVarKeys: SecretEnvVar[] = [
90
+ ...(envConfigRaw.vars?.secret ?? []).map((key) => ({ key })),
86
91
  ...additionalSecretKeys,
87
92
  ];
88
93
  const secretEnvVars = Object.fromEntries(
89
- secretEnvVarKeys.map((key) => [
94
+ secretEnvVarKeys.map(({ key }) => [
90
95
  key,
91
96
  `$${getSecretVarName(env, componentName, key)}`,
92
97
  ])
@@ -44,7 +44,7 @@ export const getBaseDeploymentJob = (context: Context): JobWithoutScript => {
44
44
  name: DEPLOY_JOB_NAME,
45
45
  envMode: "stagePerEnv", // makes it easier to run manual tasks er env
46
46
 
47
- needsOtherComponent: context.componentConfig.deploy
47
+ needs: context.componentConfig.deploy
48
48
  ? context.componentConfig.deploy.waitFor?.map((c) => ({
49
49
  componentName: c,
50
50
  job: DEPLOY_JOB_NAME,
@@ -1,5 +1,5 @@
1
1
  import { dump } from "js-yaml";
2
- import { isNil, merge, omit } from "lodash";
2
+ import { merge, omit } from "lodash";
3
3
  import { GCLOUD_DEPLOY_CREDENTIALS_KEY } from ".";
4
4
  import { getDockerJobBaseProps, gitlabDockerLogin } from "../../build/docker";
5
5
  import { getLabels } from "../../context/getLabels";
@@ -12,7 +12,7 @@ export const GCLOUD_RUN_CANONICAL_HOST_SUFFIX =
12
12
 
13
13
  const getCloudSqlVariables = ({
14
14
  deployConfigRaw,
15
- environmentSlug,
15
+ environmentSlugPrefix,
16
16
  env,
17
17
  componentName,
18
18
  fullConfig,
@@ -21,7 +21,8 @@ const getCloudSqlVariables = ({
21
21
  const DB_NAME = [
22
22
  deployConfigRaw.cloudSql.dbNamePrefix ??
23
23
  `${fullConfig.customerName}-${fullConfig.appName}`,
24
- environmentSlug,
24
+ environmentSlugPrefix,
25
+ deployConfigRaw.cloudSql.dbBaseName ?? componentName,
25
26
  ]
26
27
  .filter(Boolean)
27
28
  .join("-");
@@ -57,9 +58,16 @@ export const GCLOUD_RUN_DEPLOY_TYPE: DeployTypeDefinition<"google-cloudrun"> = {
57
58
  return {};
58
59
  },
59
60
  additionalSecretKeys: (ctx) => [
60
- GCLOUD_DEPLOY_CREDENTIALS_KEY,
61
+ {
62
+ key: GCLOUD_DEPLOY_CREDENTIALS_KEY,
63
+ hidden: true,
64
+ },
65
+ {
66
+ key: GCLOUD_RUN_CANONICAL_HOST_SUFFIX,
67
+ hidden: true,
68
+ },
61
69
  ...(ctx.deployConfigRaw && ctx.deployConfigRaw.cloudSql
62
- ? ["DB_PASSWORD"]
70
+ ? [{ key: "DB_PASSWORD" }]
63
71
  : []),
64
72
  ],
65
73
  getAdditionalEnvVars: (ctx) => {
@@ -4,7 +4,7 @@ import { getYarnInstall } from "../../build/node/yarn";
4
4
  import { getRunnerImage } from "../../runner";
5
5
  import type { Context } from "../../types/context";
6
6
  import type { CatladderJob } from "../../types/jobs";
7
- import { getBaseDeploymentJob } from "../base";
7
+ import { getBaseDeploymentJob, getBaseDeploymentStopJob } from "../base";
8
8
  import { isOfDeployType } from "../types";
9
9
 
10
10
  export const createCustomDeployJobs = (context: Context): CatladderJob[] => {
@@ -29,5 +29,13 @@ export const createCustomDeployJobs = (context: Context): CatladderJob[] => {
29
29
  ...deployConfig.script,
30
30
  ],
31
31
  }),
32
+ ...(deployConfig.stopScript
33
+ ? [
34
+ merge({}, getBaseDeploymentStopJob(context), {
35
+ image: deployConfig.jobImage ?? getRunnerImage("jobs-default"),
36
+ script: deployConfig.stopScript,
37
+ }),
38
+ ]
39
+ : []),
32
40
  ];
33
41
  };
@@ -1,3 +1,4 @@
1
+ import type { SecretEnvVar } from "..";
1
2
  import type { Context } from "../types/context";
2
3
  import type { EnvironmentContext } from "../types/environmentContext";
3
4
  import type { CatladderJob } from "../types/jobs";
@@ -17,7 +18,9 @@ export type DeployTypeDefinition<T extends DeployConfigType> = {
17
18
  defaults: (
18
19
  envContext: EnvironmentContext<any, T>
19
20
  ) => PartialDeep<DeployConfigGeneric<T>>;
20
- additionalSecretKeys: (envContext: EnvironmentContext<any, T>) => string[];
21
+ additionalSecretKeys: (
22
+ envContext: EnvironmentContext<any, T>
23
+ ) => SecretEnvVar[];
21
24
  getAdditionalEnvVars: (
22
25
  envContext: EnvironmentContext<any, T>
23
26
  ) => Record<string, string | undefined | null>;
@@ -19,5 +19,5 @@ export const additionalKubernetesSecretKeys = ({
19
19
  keys.push("cloudsqlProxyCredentials");
20
20
  }
21
21
 
22
- return keys;
22
+ return keys.map((key) => ({ key }));
23
23
  };
@@ -40,7 +40,8 @@ export const createKubernetesDeployJobs = (
40
40
  quotingType: "'",
41
41
  forceQuotes: true,
42
42
  }),
43
- HELM_GITLAB_CHART_NAME: "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 ?? []),
@@ -20,27 +20,29 @@ const createAppConfig = (
20
20
  };
21
21
  }
22
22
 
23
+ const { healthRoute, command, ...rest } = application ?? {};
24
+
23
25
  return mergeWithMergingArrays(
24
26
  {
25
27
  host: context.environment.host,
26
- command: context.componentConfig.build.startCommand,
28
+ command: command ?? context.componentConfig.build.startCommand,
27
29
  livenessProbe: {
28
30
  httpGet: {
29
- path: application?.healthRoute ?? "__health",
31
+ path: healthRoute ?? "__health",
30
32
  },
31
33
  },
32
34
  readinessProbe: {
33
35
  httpGet: {
34
- path: application?.healthRoute ?? "__health",
36
+ path: healthRoute ?? "__health",
35
37
  },
36
38
  },
37
39
  startupProbe: {
38
40
  httpGet: {
39
- path: application?.healthRoute ?? "__health",
41
+ path: healthRoute ?? "__health",
40
42
  },
41
43
  },
42
44
  }, // default
43
- application // merge rest in
45
+ rest // merge rest in
44
46
  );
45
47
  };
46
48
 
@@ -1,3 +1,4 @@
1
+ import type { GitlabJobImage } from "../../types";
1
2
  import type { CatladderJob } from "../../types/jobs";
2
3
  import type { DeployConfigBase } from "./base";
3
4
 
@@ -26,7 +27,7 @@ export type DeployConfigCustom = {
26
27
  /**
27
28
  * image to use
28
29
  */
29
- jobImage?: string;
30
+ jobImage?: GitlabJobImage;
30
31
 
31
32
  /**
32
33
  * customize cache for the job
@@ -46,11 +46,16 @@ export type DeployConfigCloudRunCloudSql = {
46
46
  dbUser?: string;
47
47
 
48
48
  /**
49
- * the prefix of the database, the full db name is this plus the environment slug
49
+ * the prefix of the database, the full db name is this plus the environment slug prefix plus the componentName
50
50
  *
51
51
  * defaults to customerName-appName
52
52
  */
53
53
  dbNamePrefix?: string | false;
54
+
55
+ /**
56
+ * the base name of the db, defaults to the componentName
57
+ */
58
+ dbBaseName?: string;
54
59
  /**
55
60
  * whether to delete the database if the environment is stopped
56
61
  * defaults to true for review envs, to false for every other environment
@@ -192,6 +192,11 @@ export type DeployConfigKubernetesValues = AllowUnknownProps<{
192
192
  application?:
193
193
  | false
194
194
  | AllowUnknownProps<{
195
+ /**
196
+ * command to start, defaults to build's startCommand
197
+ */
198
+ command?: string;
199
+
195
200
  /**
196
201
  * enable, disable app deployment, defaults to true
197
202
  */
@@ -240,7 +245,7 @@ export type DeployConfigKubernetesValues = AllowUnknownProps<{
240
245
  */
241
246
  jobDefaults?: {
242
247
  resources: KubernetesResourcesDef;
243
- }
248
+ };
244
249
  }>;
245
250
 
246
251
  /**
@@ -288,4 +293,9 @@ export type DeployConfigKubernetes = {
288
293
  * values to configure the app
289
294
  */
290
295
  values?: DeployConfigKubernetesValues;
296
+ /**
297
+ * Custom Helm chart location.
298
+ * Not recommended to use.
299
+ */
300
+ chartName?: string;
291
301
  } & DeployConfigBase;
@@ -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";
@@ -1,3 +1,4 @@
1
+ import type { SecretEnvVar } from "../context";
1
2
  import type {
2
3
  PipelineTrigger,
3
4
  ComponentConfig,
@@ -18,13 +19,14 @@ export type Environment = {
18
19
  url: string;
19
20
  };
20
21
  shortName: string;
22
+ slugPrefix: string;
21
23
  slug: string;
22
24
  /**
23
25
  * env vars contain all build-time env vars. secrets have to be resolved (they are stored in gitlab)
24
26
  */
25
27
  envVars: Record<string, string>;
26
28
  envType: EnvType;
27
- secretEnvVarKeys: string[];
29
+ secretEnvVarKeys: SecretEnvVar[];
28
30
  };
29
31
 
30
32
  export type CommitInfo = {
@@ -16,6 +16,13 @@ export type EnvironmentContext<
16
16
  envType: EnvType;
17
17
  componentName: string;
18
18
  fullName: string;
19
+ /**
20
+ * the environment slug without component name.
21
+ */
22
+ environmentSlugPrefix: string;
23
+ /**
24
+ * the full environment slug, including the componentName
25
+ */
19
26
  environmentSlug: string;
20
27
  gitlabEnvironmentName: string;
21
28
 
@@ -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,6 +43,13 @@ export type GitlabJobService = {
43
43
  alias?: string;
44
44
  };
45
45
 
46
+ export type GitlabJobImage =
47
+ | string
48
+ | {
49
+ name: string;
50
+ entrypoint?: string[];
51
+ };
52
+
46
53
  export type GitlabEnvironment = {
47
54
  url: string;
48
55
  name: string;
@@ -64,7 +71,7 @@ export type GitlabJobDef = {
64
71
  artifacts?: Artifacts;
65
72
  retry?: Retry;
66
73
  services?: GitlabJobService[];
67
- image?: string;
74
+ image?: GitlabJobImage;
68
75
  variables?: GitlabVariables;
69
76
  dependencies?: string[];
70
77
  environment?: GitlabEnvironment;