@catladder/pipeline 1.10.2 → 1.13.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.
- package/dist/build/base/constants.js +1 -1
- package/dist/build/base/createBuildJob.d.ts +4 -2
- package/dist/build/base/createBuildJob.js +13 -18
- package/dist/build/docker.d.ts +6 -3
- package/dist/build/docker.js +24 -9
- package/dist/build/index.d.ts +2 -2
- package/dist/build/node/buildJob.d.ts +2 -2
- package/dist/build/node/buildJob.js +26 -13
- package/dist/build/node/cache.d.ts +3 -1
- package/dist/build/node/cache.js +33 -5
- package/dist/build/node/constants.js +2 -2
- package/dist/build/node/index.d.ts +4 -4
- package/dist/build/node/meteor.d.ts +2 -2
- package/dist/build/node/meteor.js +4 -23
- package/dist/build/node/testJob.d.ts +2 -2
- package/dist/build/node/testJob.js +20 -29
- package/dist/build/node/yarn.d.ts +4 -0
- package/dist/build/node/yarn.js +10 -3
- package/dist/build/tests/storybook.test.js +10 -23
- package/dist/build/types.d.ts +6 -0
- package/dist/catladder-gitlab.js +33 -2
- package/dist/constants.js +1 -1
- package/dist/context/index.d.ts +2 -2
- package/dist/context/index.js +2 -2
- package/dist/deploy/base.d.ts +3 -4
- package/dist/deploy/base.js +27 -33
- package/dist/deploy/index.d.ts +2 -2
- package/dist/deploy/kubernetes/deployJob.d.ts +2 -2
- package/dist/deploy/kubernetes/deployJob.js +32 -38
- package/dist/pipeline/createChildPipeline.d.ts +2 -11
- package/dist/pipeline/createChildPipeline.js +24 -18
- package/dist/pipeline/createChildPipeline.test.js +3 -14
- package/dist/pipeline/createJobs.d.ts +2 -2
- package/dist/pipeline/createJobs.js +29 -23
- package/dist/pipeline/gitlab/makeGitlabJob.d.ts +8 -0
- package/dist/pipeline/gitlab/makeGitlabJob.js +45 -0
- package/dist/pipeline/packageManager.d.ts +2 -0
- package/dist/pipeline/{yarnInfo.js → packageManager.js} +69 -8
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/context.d.ts +15 -6
- package/dist/types/gitlab-types.d.ts +10 -22
- package/dist/types/gitlab-types.js +1 -3
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.js +3 -1
- package/dist/types/jobs.d.ts +75 -0
- package/dist/types/jobs.js +5 -0
- package/dist/types/pipeline.d.ts +4 -0
- package/dist/types/pipeline.js +3 -0
- package/package.json +1 -1
- package/src/build/base/constants.ts +1 -1
- package/src/build/base/createBuildJob.ts +29 -31
- package/src/build/docker.ts +50 -45
- package/src/build/index.ts +3 -2
- package/src/build/node/buildJob.ts +35 -25
- package/src/build/node/cache.ts +30 -5
- package/src/build/node/constants.ts +2 -2
- package/src/build/node/index.ts +4 -4
- package/src/build/node/meteor.ts +10 -18
- package/src/build/node/testJob.ts +31 -40
- package/src/build/node/yarn.ts +20 -3
- package/src/build/tests/storybook.test.ts +4 -2
- package/src/build/types.ts +6 -0
- package/src/catladder-gitlab.ts +9 -5
- package/src/context/index.ts +8 -4
- package/src/deploy/base.ts +40 -45
- package/src/deploy/index.ts +2 -2
- package/src/deploy/kubernetes/deployJob.ts +43 -48
- package/src/pipeline/createChildPipeline.test.ts +2 -1
- package/src/pipeline/createChildPipeline.ts +23 -21
- package/src/pipeline/createJobs.ts +50 -41
- package/src/pipeline/gitlab/makeGitlabJob.ts +16 -0
- package/src/pipeline/packageManager.ts +99 -0
- package/src/types/context.ts +14 -3
- package/src/types/gitlab-types.ts +10 -30
- package/src/types/index.ts +1 -0
- package/src/types/jobs.ts +88 -0
- package/src/types/pipeline.ts +11 -0
- package/dist/pipeline/yarnInfo.d.ts +0 -2
- package/src/pipeline/yarnInfo.ts +0 -54
package/src/context/index.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { merge, mergeWith } from "lodash";
|
|
2
1
|
import slugify from "slugify";
|
|
3
2
|
import { BUILD_TYPES } from "../build";
|
|
4
3
|
import { BuildConfig } from "../build/types";
|
|
5
4
|
import { DEPLOY_TYPES, getKubernetesNamespace } from "../deploy";
|
|
6
5
|
import { DeployConfig } from "../deploy/types";
|
|
7
6
|
import { Config, isKnowEnvType, DevLocalEnvConfig } from "../types/config";
|
|
8
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
CommitInfo,
|
|
9
|
+
Context,
|
|
10
|
+
Environment,
|
|
11
|
+
PackageManagerInfo,
|
|
12
|
+
} from "../types/context";
|
|
9
13
|
import { mergeWithMergingArrays } from "../utils";
|
|
10
14
|
|
|
11
15
|
const sanitizeForEnVar = (s: string) => s.replace(/-/g, "_");
|
|
@@ -164,7 +168,7 @@ export const createContext = (
|
|
|
164
168
|
componentName: string,
|
|
165
169
|
env: string,
|
|
166
170
|
commitInfo?: CommitInfo,
|
|
167
|
-
|
|
171
|
+
packageManagerInfo?: PackageManagerInfo
|
|
168
172
|
): Context => {
|
|
169
173
|
if (!/^[a-z0-9-]+$/.test(componentName)) {
|
|
170
174
|
throw new Error(
|
|
@@ -208,6 +212,6 @@ export const createContext = (
|
|
|
208
212
|
componentName,
|
|
209
213
|
environment: getEnvironment(config, componentName, env, commitInfo),
|
|
210
214
|
commitInfo,
|
|
211
|
-
|
|
215
|
+
packageManagerInfo,
|
|
212
216
|
};
|
|
213
217
|
};
|
package/src/deploy/base.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Context } from "../types";
|
|
2
|
+
import { CatladderJob } from "../types/jobs";
|
|
2
3
|
|
|
3
4
|
export const DEPLOY_JOB_NAME = "🚀 Deploy";
|
|
4
5
|
export const STOP_JOB_NAME = "🛑 Stop ⚠️";
|
|
@@ -9,9 +10,7 @@ const DEPLOY_RUNNER_VARIABLES = {
|
|
|
9
10
|
KUBERNETES_MEMORY_REQUEST: "200Mi",
|
|
10
11
|
KUBERNETES_MEMORY_LIMIT: "500Mi",
|
|
11
12
|
};
|
|
12
|
-
type JobWithoutScript = Omit<
|
|
13
|
-
job: Omit<GitlabJobDef, "script">;
|
|
14
|
-
};
|
|
13
|
+
type JobWithoutScript = Omit<CatladderJob, "script">;
|
|
15
14
|
export const getBaseDeploymentJob = (context: Context): JobWithoutScript => {
|
|
16
15
|
const environment = {
|
|
17
16
|
name: context.environment.fullName,
|
|
@@ -45,26 +44,24 @@ export const getBaseDeploymentJob = (context: Context): JobWithoutScript => {
|
|
|
45
44
|
artifacts: false,
|
|
46
45
|
},
|
|
47
46
|
], // workaround for https://gitlab.com/gitlab-org/gitlab/-/issues/220758
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
environment
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
auto_stop_in: autoStop,
|
|
67
|
-
},
|
|
47
|
+
|
|
48
|
+
rules: [
|
|
49
|
+
autoDeploy
|
|
50
|
+
? {
|
|
51
|
+
when: "on_success",
|
|
52
|
+
}
|
|
53
|
+
: {
|
|
54
|
+
when: "manual",
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
stage: "deploy",
|
|
58
|
+
variables: {
|
|
59
|
+
...DEPLOY_RUNNER_VARIABLES,
|
|
60
|
+
},
|
|
61
|
+
environment: {
|
|
62
|
+
...environment,
|
|
63
|
+
on_stop: STOP_JOB_NAME,
|
|
64
|
+
auto_stop_in: autoStop,
|
|
68
65
|
},
|
|
69
66
|
};
|
|
70
67
|
};
|
|
@@ -79,29 +76,27 @@ export const getBaseDeploymentStopJob = (
|
|
|
79
76
|
return {
|
|
80
77
|
name: STOP_JOB_NAME,
|
|
81
78
|
envMode: "stagePerEnv", // makes it easier to run manual tasks er env
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
when: "manual",
|
|
92
|
-
allow_failure: true,
|
|
93
|
-
},
|
|
94
|
-
],
|
|
95
|
-
variables: {
|
|
96
|
-
...DEPLOY_RUNNER_VARIABLES,
|
|
97
|
-
GIT_STRATEGY: "none",
|
|
79
|
+
|
|
80
|
+
needs: [DEPLOY_JOB_NAME],
|
|
81
|
+
rules: [
|
|
82
|
+
{
|
|
83
|
+
if: "$CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/", // automatic on hotfix branches
|
|
84
|
+
when: "on_success",
|
|
85
|
+
allow_failure: true,
|
|
98
86
|
},
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
...environment,
|
|
103
|
-
action: "stop",
|
|
87
|
+
{
|
|
88
|
+
when: "manual",
|
|
89
|
+
allow_failure: true,
|
|
104
90
|
},
|
|
91
|
+
],
|
|
92
|
+
variables: {
|
|
93
|
+
...DEPLOY_RUNNER_VARIABLES,
|
|
94
|
+
GIT_STRATEGY: "none",
|
|
95
|
+
},
|
|
96
|
+
stage: "stop",
|
|
97
|
+
environment: {
|
|
98
|
+
...environment,
|
|
99
|
+
action: "stop",
|
|
105
100
|
},
|
|
106
101
|
};
|
|
107
102
|
};
|
package/src/deploy/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { GitlabJobs } from "../types/gitlab-types";
|
|
2
1
|
import { Context } from "../types/context";
|
|
2
|
+
import { CatladderJob } from "../types/jobs";
|
|
3
3
|
import { createKubernetesDeployJobs } from "./kubernetes";
|
|
4
4
|
import { DeployConfig } from "./types";
|
|
5
5
|
export * from "./kubernetes";
|
|
@@ -7,7 +7,7 @@ export * from "./types";
|
|
|
7
7
|
export * from "./utils";
|
|
8
8
|
export type DeployTypes = {
|
|
9
9
|
[type in DeployConfig["type"]]: {
|
|
10
|
-
jobs: (context: Context) =>
|
|
10
|
+
jobs: (context: Context) => CatladderJob[];
|
|
11
11
|
defaults: () => Partial<Extract<DeployConfig, { type: type }>>;
|
|
12
12
|
};
|
|
13
13
|
};
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { GitlabJobs } from "../../types/gitlab-types";
|
|
2
|
-
import { Context } from "../../types/context";
|
|
3
|
-
import { isOfDeployType } from "../types";
|
|
4
|
-
import { getRunnerImage } from "../../runner";
|
|
5
|
-
import { getBaseDeploymentJob, getBaseDeploymentStopJob } from "../base";
|
|
6
|
-
import { merge } from "lodash";
|
|
7
1
|
import { dump } from "js-yaml";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
2
|
+
import { merge } from "lodash";
|
|
3
|
+
import { DeployConfigKubernetesValues } from "..";
|
|
10
4
|
import { getSecretVarNameForContext } from "../..";
|
|
5
|
+
import { getRunnerImage } from "../../runner";
|
|
6
|
+
import { Context } from "../../types/context";
|
|
7
|
+
import { CatladderJob } from "../../types/jobs";
|
|
11
8
|
import { mergeWithMergingArrays } from "../../utils";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
9
|
+
import { getBaseDeploymentJob, getBaseDeploymentStopJob } from "../base";
|
|
10
|
+
import { isOfDeployType } from "../types";
|
|
11
|
+
import { createCloudsqlBaseConfig } from "./cloudsql";
|
|
12
|
+
import { createMongodbBaseConfig } from "./mongodb";
|
|
14
13
|
|
|
15
|
-
export const createKubernetesDeployJobs = (
|
|
14
|
+
export const createKubernetesDeployJobs = (
|
|
15
|
+
context: Context
|
|
16
|
+
): CatladderJob[] => {
|
|
16
17
|
const deployConfig = context.componentConfig.deploy;
|
|
17
18
|
if (deployConfig === false) {
|
|
18
19
|
return [];
|
|
@@ -91,28 +92,26 @@ export const createKubernetesDeployJobs = (context: Context): GitlabJobs => {
|
|
|
91
92
|
namespace: context.environment.envVars.KUBE_NAMESPACE,
|
|
92
93
|
};
|
|
93
94
|
const shared = {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
IMAGE_TAG: "$CI_COMMIT_SHA",
|
|
115
|
-
},
|
|
95
|
+
image: getRunnerImage("kubernetes"),
|
|
96
|
+
variables: {
|
|
97
|
+
...context.environment.envVars,
|
|
98
|
+
HELM_EXPERIMENTAL_OCI: "1",
|
|
99
|
+
IMAGE_PULL_SECRET: `gitlab-registry-${context.componentName}`,
|
|
100
|
+
KUBE_VALUES: dump(kubeValues, {
|
|
101
|
+
lineWidth: -1,
|
|
102
|
+
quotingType: "'",
|
|
103
|
+
forceQuotes: true,
|
|
104
|
+
}),
|
|
105
|
+
HELM_GITLAB_CHART_NAME: "the-panter-chart",
|
|
106
|
+
HELM_ARGS: [
|
|
107
|
+
...(deployConfig.debug ? ["--debug"] : []),
|
|
108
|
+
...(deployConfig.additionalHelmArgs ?? []),
|
|
109
|
+
].join(" "),
|
|
110
|
+
COMPONENT_NAME: context.componentName,
|
|
111
|
+
BUILD_ID: context.commitInfo?.buildId,
|
|
112
|
+
// TODO: unify with docker build stage
|
|
113
|
+
IMAGE_NAME: context.environment.shortName + "/" + context.componentName,
|
|
114
|
+
IMAGE_TAG: "$CI_COMMIT_SHA",
|
|
116
115
|
},
|
|
117
116
|
};
|
|
118
117
|
|
|
@@ -136,24 +135,20 @@ export const createKubernetesDeployJobs = (context: Context): GitlabJobs => {
|
|
|
136
135
|
];
|
|
137
136
|
return [
|
|
138
137
|
merge({}, baseDeploymentJob, shared, {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
kubernetes: kubernetesEnvironment,
|
|
148
|
-
},
|
|
138
|
+
script: [
|
|
139
|
+
...connectContext,
|
|
140
|
+
"kubernetesCreateSecret",
|
|
141
|
+
"kubernetesDeploy",
|
|
142
|
+
"echo deployment successful 😻",
|
|
143
|
+
],
|
|
144
|
+
environment: {
|
|
145
|
+
kubernetes: kubernetesEnvironment,
|
|
149
146
|
},
|
|
150
147
|
}),
|
|
151
148
|
merge({}, baseStopJob, shared, {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
kubernetes: kubernetesEnvironment,
|
|
156
|
-
},
|
|
149
|
+
script: [...connectContext, "kubernetesDelete"],
|
|
150
|
+
environment: {
|
|
151
|
+
kubernetes: kubernetesEnvironment,
|
|
157
152
|
},
|
|
158
153
|
}),
|
|
159
154
|
];
|
|
@@ -26,7 +26,8 @@ describe("createChildPipeline", () => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
it("creates a pipeline for a single app on the main branch", async () => {
|
|
29
|
-
const { image,
|
|
29
|
+
const { image, jobs } = await createChildPipeline(
|
|
30
|
+
"gitlab",
|
|
30
31
|
"mainBranch",
|
|
31
32
|
config
|
|
32
33
|
);
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import { getAllEnvsByTrigger, getAllEnvsInAllComponents } from "../config";
|
|
2
|
-
import { createJobs } from "./createJobs";
|
|
3
2
|
import { RULES_ALWAYS } from "../rules";
|
|
4
3
|
import { getRunnerImage } from "../runner";
|
|
4
|
+
import { GitlabPipeline, Pipeline, PipelineJob, PipelineType } from "../types";
|
|
5
5
|
import { Config, PipelineTrigger } from "../types/config";
|
|
6
|
-
import {
|
|
6
|
+
import { createJobs } from "./createJobs";
|
|
7
|
+
|
|
7
8
|
const baseStages = ["setup", "test", "build", "deploy", "verify", "stop"];
|
|
8
|
-
export const createChildPipeline = async (
|
|
9
|
+
export const createChildPipeline = async <T extends PipelineType>(
|
|
10
|
+
type: T,
|
|
9
11
|
trigger: PipelineTrigger,
|
|
10
12
|
config: Config
|
|
11
|
-
) => {
|
|
13
|
+
): Promise<Pipeline<T>> => {
|
|
12
14
|
const components = Object.keys(config.components);
|
|
13
15
|
|
|
14
16
|
// 2. write the triggering pipeline
|
|
15
|
-
|
|
16
|
-
const jobs = await components.reduce<Promise<Record<string, GitlabJobDef>>>(
|
|
17
|
+
const jobs = await components.reduce<Promise<Record<string, PipelineJob<T>>>>(
|
|
17
18
|
async (acc, componentName) => {
|
|
18
19
|
const envs = getAllEnvsByTrigger(config, componentName, trigger);
|
|
19
20
|
return {
|
|
20
21
|
...(await acc),
|
|
21
|
-
...(await createJobs(envs, config, componentName, trigger)),
|
|
22
|
+
...(await createJobs(type, envs, config, componentName, trigger)),
|
|
22
23
|
};
|
|
23
24
|
},
|
|
24
25
|
Promise.resolve({})
|
|
@@ -37,18 +38,19 @@ export const createChildPipeline = async (
|
|
|
37
38
|
],
|
|
38
39
|
[]
|
|
39
40
|
);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
41
|
+
if (type === "gitlab") {
|
|
42
|
+
const pipeline: GitlabPipeline = {
|
|
43
|
+
image: getRunnerImage("jobs-default"), // default image
|
|
44
|
+
variables: {
|
|
45
|
+
FF_USE_FASTZIP: "true",
|
|
46
|
+
},
|
|
47
|
+
workflow: {
|
|
48
|
+
rules: RULES_ALWAYS,
|
|
49
|
+
},
|
|
50
|
+
stages,
|
|
51
|
+
jobs,
|
|
52
|
+
};
|
|
53
|
+
return pipeline as Pipeline<T>;
|
|
54
|
+
}
|
|
55
|
+
throw new Error(`${type} is not supported`);
|
|
54
56
|
};
|
|
@@ -3,13 +3,15 @@ import { isObject } from "lodash";
|
|
|
3
3
|
import { BUILD_TYPES } from "../build";
|
|
4
4
|
import { createContext } from "../context";
|
|
5
5
|
import { DEPLOY_TYPES } from "../deploy";
|
|
6
|
+
import { PipelineJob, PipelineType } from "../types";
|
|
6
7
|
import { Config, PipelineTrigger } from "../types/config";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { CommitInfo, Context } from "../types/context";
|
|
9
|
+
import { CatladderJob } from "../types/jobs";
|
|
9
10
|
import { notNil } from "../utils";
|
|
10
|
-
import {
|
|
11
|
+
import { makeGitlabJob } from "./gitlab/makeGitlabJob";
|
|
12
|
+
import { getPackageManagerInfo } from "./packageManager";
|
|
11
13
|
|
|
12
|
-
const createRawJobs = (context: Context):
|
|
14
|
+
const createRawJobs = (context: Context): CatladderJob[] => {
|
|
13
15
|
if (context.componentConfig.deploy === false) {
|
|
14
16
|
return [];
|
|
15
17
|
}
|
|
@@ -35,7 +37,7 @@ const getFullReferencedJobName = (
|
|
|
35
37
|
referencedJobName: string,
|
|
36
38
|
componentName: string,
|
|
37
39
|
env: string,
|
|
38
|
-
allRawJobs:
|
|
40
|
+
allRawJobs: CatladderJob[]
|
|
39
41
|
) => {
|
|
40
42
|
const referencedJob = allRawJobs.find((j) => j.name === referencedJobName);
|
|
41
43
|
if (!referencedJob) {
|
|
@@ -47,18 +49,17 @@ const getFullReferencedJobName = (
|
|
|
47
49
|
// replaces references to other jobs with the full name
|
|
48
50
|
// the full name contains the componentname and the env name (if any)
|
|
49
51
|
const replaceReferences = (
|
|
50
|
-
job:
|
|
52
|
+
job: CatladderJob,
|
|
51
53
|
componentName: string,
|
|
52
54
|
env: string,
|
|
53
|
-
allRawJobs:
|
|
54
|
-
):
|
|
55
|
-
const def = job.job;
|
|
55
|
+
allRawJobs: CatladderJob[]
|
|
56
|
+
): CatladderJob<string> => {
|
|
56
57
|
const stage =
|
|
57
|
-
job.envMode === "stagePerEnv" ? `${
|
|
58
|
+
job.envMode === "stagePerEnv" ? `${job.stage} ${env}` : job.stage;
|
|
58
59
|
return {
|
|
59
|
-
...
|
|
60
|
+
...job,
|
|
60
61
|
stage,
|
|
61
|
-
needs:
|
|
62
|
+
needs: job.needs?.map((n) =>
|
|
62
63
|
isObject(n)
|
|
63
64
|
? {
|
|
64
65
|
job: getFullReferencedJobName(
|
|
@@ -71,25 +72,22 @@ const replaceReferences = (
|
|
|
71
72
|
}
|
|
72
73
|
: getFullReferencedJobName(n, componentName, env, allRawJobs)
|
|
73
74
|
),
|
|
74
|
-
environment:
|
|
75
|
+
environment: job.environment?.on_stop
|
|
75
76
|
? {
|
|
76
|
-
...
|
|
77
|
+
...job.environment,
|
|
77
78
|
on_stop: getFullReferencedJobName(
|
|
78
|
-
|
|
79
|
+
job.environment.on_stop,
|
|
79
80
|
componentName,
|
|
80
81
|
env,
|
|
81
82
|
allRawJobs
|
|
82
83
|
),
|
|
83
84
|
}
|
|
84
|
-
:
|
|
85
|
-
dependencies: def.dependencies?.map((n) =>
|
|
86
|
-
getFullReferencedJobName(n, componentName, env, allRawJobs)
|
|
87
|
-
),
|
|
85
|
+
: job.environment,
|
|
88
86
|
};
|
|
89
87
|
};
|
|
90
88
|
|
|
91
89
|
// this can be removed once https://gitlab.com/gitlab-org/gitlab/-/issues/220758 is resolved
|
|
92
|
-
const addStageNeeds = (jobs:
|
|
90
|
+
const addStageNeeds = (jobs: CatladderJob[]): CatladderJob[] => {
|
|
93
91
|
// when a job defines needsStages, we add these as needs
|
|
94
92
|
return jobs.map((job) => {
|
|
95
93
|
if (!job.needsStages || job.needsStages.length === 0) {
|
|
@@ -98,9 +96,7 @@ const addStageNeeds = (jobs: GitlabJobs): GitlabJobs => {
|
|
|
98
96
|
|
|
99
97
|
const neededJobs = jobs
|
|
100
98
|
.map((j) => {
|
|
101
|
-
const neededStage = job.needsStages?.find(
|
|
102
|
-
(s) => j.job.stage === s.stage
|
|
103
|
-
);
|
|
99
|
+
const neededStage = job.needsStages?.find((s) => j.stage === s.stage);
|
|
104
100
|
if (neededStage) {
|
|
105
101
|
return {
|
|
106
102
|
job: j.name,
|
|
@@ -111,19 +107,19 @@ const addStageNeeds = (jobs: GitlabJobs): GitlabJobs => {
|
|
|
111
107
|
.filter(notNil);
|
|
112
108
|
return {
|
|
113
109
|
...job,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
needs: [...(job.job.needs ?? []), ...neededJobs],
|
|
117
|
-
},
|
|
110
|
+
|
|
111
|
+
needs: [...(job.needs ?? []), ...neededJobs],
|
|
118
112
|
};
|
|
119
113
|
});
|
|
120
114
|
};
|
|
121
|
-
|
|
115
|
+
|
|
116
|
+
export const createJobs = async <T extends PipelineType>(
|
|
117
|
+
type: T,
|
|
122
118
|
envs: string[],
|
|
123
119
|
config: Config,
|
|
124
120
|
componentName: string,
|
|
125
121
|
trigger: PipelineTrigger
|
|
126
|
-
): Promise<Record<string,
|
|
122
|
+
): Promise<Record<string, PipelineJob<T>>> => {
|
|
127
123
|
const commitInfo: CommitInfo = {
|
|
128
124
|
refName: process.env.CI_COMMIT_REF_NAME ?? "unknown",
|
|
129
125
|
refSlug: process.env.CI_COMMIT_REF_SLUG ?? "unknown",
|
|
@@ -134,7 +130,7 @@ export const createJobs = async (
|
|
|
134
130
|
trigger,
|
|
135
131
|
};
|
|
136
132
|
|
|
137
|
-
const
|
|
133
|
+
const packageManagerInfo = await getPackageManagerInfo(config, componentName);
|
|
138
134
|
|
|
139
135
|
return envs.reduce((acc, env) => {
|
|
140
136
|
const context = createContext(
|
|
@@ -142,22 +138,35 @@ export const createJobs = async (
|
|
|
142
138
|
componentName,
|
|
143
139
|
env,
|
|
144
140
|
commitInfo,
|
|
145
|
-
|
|
141
|
+
packageManagerInfo
|
|
146
142
|
);
|
|
147
143
|
const jobs = addStageNeeds(createRawJobs(context));
|
|
148
144
|
|
|
149
|
-
|
|
145
|
+
const result = {
|
|
150
146
|
...acc,
|
|
151
|
-
...jobs.reduce((acc, job) => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
147
|
+
...jobs.reduce<Record<string, PipelineJob<T>>>((acc, job) => {
|
|
148
|
+
const jobWithResolvedReferences = replaceReferences(
|
|
149
|
+
job,
|
|
150
|
+
componentName,
|
|
151
|
+
env,
|
|
152
|
+
jobs
|
|
153
|
+
);
|
|
154
|
+
const jobName = getFullJobName(
|
|
155
|
+
job.name,
|
|
156
|
+
componentName,
|
|
157
|
+
job.envMode !== "none" ? env : undefined
|
|
158
|
+
);
|
|
159
|
+
if (type === "gitlab") {
|
|
160
|
+
return {
|
|
161
|
+
...acc,
|
|
162
|
+
[jobName]: makeGitlabJob(
|
|
163
|
+
jobWithResolvedReferences
|
|
164
|
+
) as PipelineJob<T>,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
throw new Error("not supported");
|
|
160
168
|
}, {}),
|
|
161
169
|
};
|
|
170
|
+
return result;
|
|
162
171
|
}, {});
|
|
163
172
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BASE_RETRY } from "../../defaults";
|
|
2
|
+
import { GitlabJobDef } from "../../types";
|
|
3
|
+
import { CatladderJob } from "../../types/jobs";
|
|
4
|
+
|
|
5
|
+
export const makeGitlabJob = ({
|
|
6
|
+
envMode,
|
|
7
|
+
needsStages,
|
|
8
|
+
name,
|
|
9
|
+
...rest
|
|
10
|
+
}: CatladderJob<string>): GitlabJobDef => {
|
|
11
|
+
return {
|
|
12
|
+
...rest,
|
|
13
|
+
retry: BASE_RETRY,
|
|
14
|
+
interruptible: true,
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { exec } from "child-process-promise";
|
|
2
|
+
import { Config, PackageManagerInfo } from "../types";
|
|
3
|
+
import { pathEqual } from "path-equal";
|
|
4
|
+
import memoizee from "memoizee";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import { existsSync } from "fs";
|
|
7
|
+
|
|
8
|
+
const execOrFail = async (cmd: string, onFail: string): Promise<string> => {
|
|
9
|
+
try {
|
|
10
|
+
return await exec(cmd).then((r) => r.stdout);
|
|
11
|
+
} catch (e) {
|
|
12
|
+
return onFail ?? null;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const getYarnVersion = memoizee(
|
|
17
|
+
async () => {
|
|
18
|
+
return await execOrFail("yarn --version", "");
|
|
19
|
+
},
|
|
20
|
+
{ promise: true }
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const getWorkspaces = memoizee(
|
|
24
|
+
async (isClassic: boolean): Promise<PackageManagerInfo["workspaces"]> => {
|
|
25
|
+
return isClassic
|
|
26
|
+
? Object.values(
|
|
27
|
+
JSON.parse(
|
|
28
|
+
JSON.parse(await execOrFail("yarn workspaces --json info", "{}"))
|
|
29
|
+
?.data ?? "{}"
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
: JSON.parse(
|
|
33
|
+
`[${(await execOrFail("yarn workspaces list --json --verbose", ""))
|
|
34
|
+
.trim()
|
|
35
|
+
.split("\n")
|
|
36
|
+
.join(",")}]`
|
|
37
|
+
);
|
|
38
|
+
},
|
|
39
|
+
{ promise: true }
|
|
40
|
+
);
|
|
41
|
+
export const getPackageManagerInfo = async (
|
|
42
|
+
config: Config,
|
|
43
|
+
componentName: string
|
|
44
|
+
): Promise<PackageManagerInfo> => {
|
|
45
|
+
// currently only supports yarn
|
|
46
|
+
const version = await getYarnVersion();
|
|
47
|
+
if (!version) throw new Error("could not get yarn version");
|
|
48
|
+
const isClassic = version.startsWith("1");
|
|
49
|
+
|
|
50
|
+
const component = config.components[componentName];
|
|
51
|
+
const workspaces = await getWorkspaces(isClassic);
|
|
52
|
+
const currentWorkspace = workspaces.find((w) =>
|
|
53
|
+
pathEqual(component.dir, w.location)
|
|
54
|
+
);
|
|
55
|
+
const componentIsInWorkspace = Boolean(currentWorkspace);
|
|
56
|
+
const workspaceRoot = "."; // currently we assume the root folder, later on we might support nested workspaces
|
|
57
|
+
const packageJson = join(component.dir, "package.json");
|
|
58
|
+
const workspacePackageJson = componentIsInWorkspace
|
|
59
|
+
? join(workspaceRoot, "package.json")
|
|
60
|
+
: null;
|
|
61
|
+
|
|
62
|
+
const lockFile = componentIsInWorkspace
|
|
63
|
+
? join(workspaceRoot, "yarn.lock")
|
|
64
|
+
: join(component.dir, "yarn.lock");
|
|
65
|
+
const configFiles = [".yarnrc", ".yarnrc.yml", ".npmrc", ".yarn"]; // ".yarn" is yarn 2 folder
|
|
66
|
+
const rcFiles = (
|
|
67
|
+
componentIsInWorkspace
|
|
68
|
+
? configFiles
|
|
69
|
+
: configFiles.map((f) => join(component.dir, f))
|
|
70
|
+
).filter((f) => existsSync(f));
|
|
71
|
+
|
|
72
|
+
// get all folders that this workspace depend on
|
|
73
|
+
// we will later copy them into the docker build
|
|
74
|
+
const workspaceDependencies = currentWorkspace
|
|
75
|
+
? ([
|
|
76
|
+
...currentWorkspace.workspaceDependencies,
|
|
77
|
+
...currentWorkspace.mismatchedWorkspaceDependencies,
|
|
78
|
+
]
|
|
79
|
+
.map((name) => workspaces.find((w) => w.name === name)?.location)
|
|
80
|
+
.filter(Boolean) as string[])
|
|
81
|
+
: [];
|
|
82
|
+
|
|
83
|
+
const pathsToCopyInDocker = [
|
|
84
|
+
packageJson,
|
|
85
|
+
...(workspacePackageJson ? [workspacePackageJson] : []),
|
|
86
|
+
lockFile,
|
|
87
|
+
...rcFiles,
|
|
88
|
+
...workspaceDependencies,
|
|
89
|
+
];
|
|
90
|
+
return {
|
|
91
|
+
type: "yarn",
|
|
92
|
+
workspaces,
|
|
93
|
+
version,
|
|
94
|
+
isClassic,
|
|
95
|
+
currentWorkspace,
|
|
96
|
+
componentIsInWorkspace,
|
|
97
|
+
pathsToCopyInDocker,
|
|
98
|
+
};
|
|
99
|
+
};
|