@catladder/pipeline 0.0.7 → 1.0.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.
- package/babel-inline.json +11 -0
- package/bin/catladder-gitlab.js +3 -0
- package/dist/build/base/constants.d.ts +7 -0
- package/dist/build/base/constants.js +11 -0
- package/dist/build/base/createBuildJob.d.ts +5 -0
- package/dist/build/base/createBuildJob.js +99 -0
- package/dist/build/docker.d.ts +5 -0
- package/dist/build/docker.js +95 -0
- package/dist/build/index.d.ts +12 -0
- package/dist/build/index.js +63 -0
- package/dist/build/node/buildJob.d.ts +3 -0
- package/dist/build/node/buildJob.js +97 -0
- package/dist/build/node/cache.d.ts +4 -0
- package/dist/build/node/cache.js +67 -0
- package/dist/build/node/constants.d.ts +6 -0
- package/dist/build/node/constants.js +10 -0
- package/dist/build/node/index.d.ts +5 -0
- package/dist/build/node/index.js +63 -0
- package/dist/build/node/meteor.d.ts +3 -0
- package/dist/build/node/meteor.js +103 -0
- package/dist/build/node/testJob.d.ts +3 -0
- package/dist/build/node/testJob.js +112 -0
- package/dist/build/node/yarn.d.ts +2 -0
- package/dist/build/node/yarn.js +12 -0
- package/dist/build/tests/storybook.test.d.ts +1 -0
- package/dist/build/tests/storybook.test.js +221 -0
- package/dist/build/types.d.ts +63 -0
- package/dist/build/types.js +16 -0
- package/dist/catladder-gitlab.d.ts +1 -0
- package/dist/catladder-gitlab.js +44 -0
- package/dist/config/configruedEnvs.d.ts +4 -0
- package/dist/config/configruedEnvs.js +86 -0
- package/dist/config/configruedEnvs.test.d.ts +1 -0
- package/dist/config/configruedEnvs.test.js +103 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +24 -0
- package/dist/config/readConfig.d.ts +2 -0
- package/dist/config/readConfig.js +47 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +6 -0
- package/dist/context/index.d.ts +5 -0
- package/dist/context/index.js +211 -0
- package/dist/defaults/index.d.ts +2 -0
- package/dist/defaults/index.js +8 -0
- package/dist/deploy/base.d.ts +9 -0
- package/dist/deploy/base.js +94 -0
- package/dist/deploy/index.d.ts +11 -0
- package/dist/deploy/index.js +34 -0
- package/dist/deploy/kubernetes/cloudsql.d.ts +6 -0
- package/dist/deploy/kubernetes/cloudsql.js +16 -0
- package/dist/deploy/kubernetes/deployJob.d.ts +3 -0
- package/dist/deploy/kubernetes/deployJob.js +148 -0
- package/dist/deploy/kubernetes/index.d.ts +1 -0
- package/dist/deploy/kubernetes/index.js +22 -0
- package/dist/deploy/kubernetes/mongodb.d.ts +15 -0
- package/dist/deploy/kubernetes/mongodb.js +23 -0
- package/dist/deploy/types.d.ts +92 -0
- package/dist/deploy/types.js +16 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +36 -0
- package/dist/pipeline/createChildPipeline.d.ts +9 -0
- package/dist/pipeline/createChildPipeline.js +266 -0
- package/dist/pipeline/createChildPipeline.test.d.ts +1 -0
- package/dist/pipeline/createChildPipeline.test.js +199 -0
- package/dist/pipeline/createJobs.d.ts +3 -0
- package/dist/pipeline/createJobs.js +331 -0
- package/dist/pipeline/index.d.ts +2 -0
- package/dist/pipeline/index.js +24 -0
- package/dist/pipeline/yarnInfo.d.ts +2 -0
- package/dist/pipeline/yarnInfo.js +296 -0
- package/dist/rules/index.d.ts +3 -0
- package/dist/rules/index.js +27 -0
- package/dist/runner/index.d.ts +3 -0
- package/dist/runner/index.js +12 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/config.d.ts +73 -0
- package/dist/types/config.js +80 -0
- package/dist/types/context.d.ts +36 -0
- package/dist/types/context.js +3 -0
- package/dist/types/gitlab-types.d.ts +86 -0
- package/dist/types/gitlab-types.js +5 -0
- package/dist/{scripts/magic/types → types}/index.d.ts +1 -1
- package/dist/types/index.js +26 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +18 -0
- package/package.json +30 -9
- package/src/build/base/constants.ts +7 -0
- package/src/build/base/createBuildJob.ts +46 -0
- package/{scripts/magic → src}/build/docker.ts +15 -2
- package/src/build/index.ts +42 -0
- package/src/build/node/buildJob.ts +54 -0
- package/src/build/node/cache.ts +36 -0
- package/src/build/node/constants.ts +6 -0
- package/src/build/node/index.ts +17 -0
- package/src/build/node/meteor.ts +75 -0
- package/src/build/node/testJob.ts +80 -0
- package/src/build/node/yarn.ts +8 -0
- package/src/build/tests/storybook.test.ts +46 -0
- package/src/build/types.ts +75 -0
- package/src/catladder-gitlab.ts +52 -0
- package/src/config/configruedEnvs.test.ts +97 -0
- package/src/config/configruedEnvs.ts +56 -0
- package/src/config/index.ts +2 -0
- package/src/config/readConfig.ts +36 -0
- package/src/constants.ts +2 -0
- package/src/context/index.ts +194 -0
- package/src/defaults/index.ts +6 -0
- package/src/deploy/base.ts +101 -0
- package/src/deploy/index.ts +19 -0
- package/src/deploy/kubernetes/cloudsql.ts +13 -0
- package/src/deploy/kubernetes/deployJob.ts +116 -0
- package/src/deploy/kubernetes/index.ts +1 -0
- package/src/deploy/kubernetes/mongodb.ts +20 -0
- package/src/deploy/types.ts +60 -0
- package/src/index.ts +8 -0
- package/{scripts/magic/tests/createPipeline.test.ts → src/pipeline/createChildPipeline.test.ts} +5 -4
- package/src/pipeline/createChildPipeline.ts +51 -0
- package/src/pipeline/createJobs.ts +158 -0
- package/src/pipeline/index.ts +2 -0
- package/src/pipeline/yarnInfo.ts +54 -0
- package/src/rules/index.ts +37 -0
- package/src/runner/index.ts +10 -0
- package/src/types/config.ts +88 -0
- package/src/types/context.ts +36 -0
- package/src/types/gitlab-types.ts +94 -0
- package/{scripts/magic → src}/types/index.ts +0 -0
- package/src/utils/index.ts +10 -0
- package/tsconfig.json +4 -2
- package/Dockerfile +0 -84
- package/dist/scripts/createSamplePipeline.d.ts +0 -2
- package/dist/scripts/createSamplePipeline.js +0 -14
- package/dist/scripts/magic/build/docker.d.ts +0 -2
- package/dist/scripts/magic/build/docker.js +0 -68
- package/dist/scripts/magic/build/index.d.ts +0 -9
- package/dist/scripts/magic/build/index.js +0 -12
- package/dist/scripts/magic/build/node.d.ts +0 -6
- package/dist/scripts/magic/build/node.js +0 -150
- package/dist/scripts/magic/build/types.d.ts +0 -18
- package/dist/scripts/magic/build/types.js +0 -7
- package/dist/scripts/magic/context/index.d.ts +0 -3
- package/dist/scripts/magic/context/index.js +0 -122
- package/dist/scripts/magic/createChildPipeline/index.d.ts +0 -3
- package/dist/scripts/magic/createChildPipeline/index.js +0 -68
- package/dist/scripts/magic/createPipeline.d.ts +0 -14
- package/dist/scripts/magic/createPipeline.js +0 -80
- package/dist/scripts/magic/deploy/index.d.ts +0 -9
- package/dist/scripts/magic/deploy/index.js +0 -12
- package/dist/scripts/magic/deploy/kubernetes.d.ts +0 -5
- package/dist/scripts/magic/deploy/kubernetes.js +0 -62
- package/dist/scripts/magic/deploy/types.d.ts +0 -41
- package/dist/scripts/magic/deploy/types.js +0 -7
- package/dist/scripts/magic/index.d.ts +0 -2
- package/dist/scripts/magic/index.js +0 -16
- package/dist/scripts/magic/sample-config.d.ts +0 -3
- package/dist/scripts/magic/sample-config.js +0 -77
- package/dist/scripts/magic/tests/createPipeline.test.d.ts +0 -1
- package/dist/scripts/magic/tests/createPipeline.test.js +0 -89
- package/dist/scripts/magic/types/config.d.ts +0 -49
- package/dist/scripts/magic/types/config.js +0 -17
- package/dist/scripts/magic/types/context.d.ts +0 -19
- package/dist/scripts/magic/types/context.js +0 -2
- package/dist/scripts/magic/types/gitlab-types.d.ts +0 -57
- package/dist/scripts/magic/types/gitlab-types.js +0 -2
- package/dist/scripts/magic/types/index.js +0 -15
- package/dist/scripts/magic.d.ts +0 -2
- package/dist/scripts/magic.js +0 -43
- package/dist/scripts/monorepoGenerate.d.ts +0 -2
- package/dist/scripts/monorepoGenerate.js +0 -164
- package/dist/scripts/printAllValues.d.ts +0 -2
- package/dist/scripts/printAllValues.js +0 -58
- package/dist/scripts/printBuildEnv.d.ts +0 -2
- package/dist/scripts/printBuildEnv.js +0 -77
- package/dist/scripts/utils/extractAllValues.d.ts +0 -1
- package/dist/scripts/utils/extractAllValues.js +0 -78
- package/dist/scripts/utils/extractBuildEnv.d.ts +0 -5
- package/dist/scripts/utils/extractBuildEnv.js +0 -152
- package/dist/scripts/utils/extractValuesFromEnvVars.d.ts +0 -2
- package/dist/scripts/utils/extractValuesFromEnvVars.js +0 -63
- package/dist/scripts/utils/extractValuesFromMr.d.ts +0 -2
- package/dist/scripts/utils/extractValuesFromMr.js +0 -86
- package/dist/tests/extractValuesFromMr.test.d.ts +0 -1
- package/dist/tests/extractValuesFromMr.test.js +0 -68
- package/scripts/createSamplePipeline.ts +0 -10
- package/scripts/getCommitInfo +0 -11
- package/scripts/kubernetesCreateSecret +0 -9
- package/scripts/kubernetesDelete +0 -4
- package/scripts/kubernetesDeploy +0 -55
- package/scripts/kubernetesEnsureNamespace +0 -3
- package/scripts/magic/build/index.ts +0 -18
- package/scripts/magic/build/node.ts +0 -143
- package/scripts/magic/build/types.ts +0 -21
- package/scripts/magic/context/index.ts +0 -127
- package/scripts/magic/createChildPipeline/index.ts +0 -60
- package/scripts/magic/createPipeline.ts +0 -52
- package/scripts/magic/deploy/index.ts +0 -19
- package/scripts/magic/deploy/kubernetes.ts +0 -65
- package/scripts/magic/deploy/types.ts +0 -29
- package/scripts/magic/index.ts +0 -2
- package/scripts/magic/sample-config.ts +0 -78
- package/scripts/magic/types/config.ts +0 -54
- package/scripts/magic/types/context.ts +0 -21
- package/scripts/magic/types/gitlab-types.ts +0 -69
- package/scripts/magic.ts +0 -51
- package/scripts/monorepoGenerate.ts +0 -104
- package/scripts/printAllValues.ts +0 -17
- package/scripts/printBuildEnv.ts +0 -22
- package/scripts/utils/extractAllValues.ts +0 -32
- package/scripts/utils/extractBuildEnv.ts +0 -94
- package/scripts/utils/extractValuesFromEnvVars.ts +0 -21
- package/scripts/utils/extractValuesFromMr.ts +0 -39
- package/tests/extractValuesFromMr.test.ts +0 -156
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export type BuildConfigBase = {
|
|
2
|
+
startCommand?: string;
|
|
3
|
+
extraVars?: Record<string, string>;
|
|
4
|
+
/**
|
|
5
|
+
* define the build command
|
|
6
|
+
*/
|
|
7
|
+
buildCommand?: string | string[] | null;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* customize docker build
|
|
11
|
+
*/
|
|
12
|
+
docker?: {
|
|
13
|
+
additionsBegin?: string[];
|
|
14
|
+
additionsEnd?: string[];
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* customize lint, set false to disable
|
|
19
|
+
*/
|
|
20
|
+
lint?:
|
|
21
|
+
| false
|
|
22
|
+
| {
|
|
23
|
+
command?: string | string[];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* customize test, set false to disable
|
|
28
|
+
*/
|
|
29
|
+
test?:
|
|
30
|
+
| false
|
|
31
|
+
| {
|
|
32
|
+
command?: string | string[];
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* customize audit, set false to disable
|
|
37
|
+
*/
|
|
38
|
+
audit?:
|
|
39
|
+
| false
|
|
40
|
+
| {
|
|
41
|
+
command?: string | string[];
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type BuildConfigNodeBase = BuildConfigBase;
|
|
46
|
+
|
|
47
|
+
export type BuildConfigNode = {
|
|
48
|
+
type: "node";
|
|
49
|
+
} & BuildConfigNodeBase;
|
|
50
|
+
|
|
51
|
+
export type BuildConfigNodeStatic = BuildConfigNodeBase & {
|
|
52
|
+
type: "node-static";
|
|
53
|
+
startCommand?: never;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type BuildConfigMeteor = BuildConfigNodeBase & {
|
|
57
|
+
type: "meteor";
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type BuildConfigStorybook = BuildConfigNodeBase & {
|
|
61
|
+
type: "storybook";
|
|
62
|
+
startCommand?: never;
|
|
63
|
+
};
|
|
64
|
+
export type BuildConfig =
|
|
65
|
+
| BuildConfigNode
|
|
66
|
+
| BuildConfigNodeStatic
|
|
67
|
+
| BuildConfigStorybook
|
|
68
|
+
| BuildConfigMeteor;
|
|
69
|
+
|
|
70
|
+
export const isOfBuildType = <T extends Array<BuildConfig["type"]>>(
|
|
71
|
+
t: BuildConfig,
|
|
72
|
+
...types: T
|
|
73
|
+
): t is Extract<BuildConfig, { type: T[number] }> => {
|
|
74
|
+
return types.includes(t.type);
|
|
75
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { writeFileSync } from "fs";
|
|
2
|
+
import { readConfigSync } from "./config";
|
|
3
|
+
import { PIPELINE_IMAGE_TAG } from "./constants";
|
|
4
|
+
import { createChildPipeline } from "./pipeline";
|
|
5
|
+
import { PipelineTrigger } from "./types";
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
CI_MERGE_REQUEST_ID,
|
|
9
|
+
CI_COMMIT_TAG,
|
|
10
|
+
CI_COMMIT_BRANCH,
|
|
11
|
+
CI_DEFAULT_BRANCH,
|
|
12
|
+
} = process.env;
|
|
13
|
+
|
|
14
|
+
const isDefaultBranch = CI_COMMIT_BRANCH == CI_DEFAULT_BRANCH;
|
|
15
|
+
const isHotfixBranch = false; // TODO: $CI_COMMIT_BRANCH =~ /^[0-9]+\.([0-9]+|x)\.x$/
|
|
16
|
+
const isMergeRequest = Boolean(CI_MERGE_REQUEST_ID);
|
|
17
|
+
const isTaggedRelease = Boolean(CI_COMMIT_TAG);
|
|
18
|
+
|
|
19
|
+
console.info(`catladder version ${PIPELINE_IMAGE_TAG}`);
|
|
20
|
+
|
|
21
|
+
const trigger: PipelineTrigger | null =
|
|
22
|
+
isMergeRequest || isHotfixBranch
|
|
23
|
+
? "mr"
|
|
24
|
+
: isDefaultBranch
|
|
25
|
+
? "mainBranch"
|
|
26
|
+
: isTaggedRelease
|
|
27
|
+
? "taggedRelease"
|
|
28
|
+
: null;
|
|
29
|
+
if (trigger) {
|
|
30
|
+
const config = readConfigSync();
|
|
31
|
+
if (!config) {
|
|
32
|
+
throw new Error("no catladder config found");
|
|
33
|
+
}
|
|
34
|
+
createChildPipeline(trigger, config).then((mainPipeline) => {
|
|
35
|
+
writeFileSync(`__pipeline.yml`, JSON.stringify(mainPipeline, null, 2), {
|
|
36
|
+
encoding: "utf-8",
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
} else {
|
|
40
|
+
throw new Error(
|
|
41
|
+
"no matching trigger: " +
|
|
42
|
+
JSON.stringify(
|
|
43
|
+
{
|
|
44
|
+
isMergeRequest,
|
|
45
|
+
isDefaultBranch,
|
|
46
|
+
isTaggedRelease,
|
|
47
|
+
},
|
|
48
|
+
null,
|
|
49
|
+
2
|
|
50
|
+
)
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { getAllEnvsByTrigger } from ".";
|
|
2
|
+
import { Config } from "../types";
|
|
3
|
+
|
|
4
|
+
describe("getAllEnvsByTrigger", () => {
|
|
5
|
+
const SIMPLE_CONFIG: Config = {
|
|
6
|
+
appName: "my-app",
|
|
7
|
+
customerName: "pan",
|
|
8
|
+
components: {
|
|
9
|
+
app1: {
|
|
10
|
+
dir: "dir1",
|
|
11
|
+
build: {
|
|
12
|
+
type: "node",
|
|
13
|
+
},
|
|
14
|
+
deploy: { type: "kubernetes" },
|
|
15
|
+
},
|
|
16
|
+
app2: {
|
|
17
|
+
dir: "dir2",
|
|
18
|
+
build: {
|
|
19
|
+
type: "node",
|
|
20
|
+
},
|
|
21
|
+
deploy: { type: "kubernetes" },
|
|
22
|
+
env: {
|
|
23
|
+
dev2: {
|
|
24
|
+
type: "dev",
|
|
25
|
+
},
|
|
26
|
+
review2: {
|
|
27
|
+
type: "review",
|
|
28
|
+
},
|
|
29
|
+
stage2: {
|
|
30
|
+
type: "stage",
|
|
31
|
+
},
|
|
32
|
+
prod2: {
|
|
33
|
+
type: "prod",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
app3: {
|
|
38
|
+
dir: "dir2",
|
|
39
|
+
build: {
|
|
40
|
+
type: "node",
|
|
41
|
+
},
|
|
42
|
+
deploy: { type: "kubernetes" },
|
|
43
|
+
env: {
|
|
44
|
+
dev: false,
|
|
45
|
+
review: false,
|
|
46
|
+
stage: false,
|
|
47
|
+
prod: false,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
describe("mainBranch", () => {
|
|
54
|
+
it("always includes dev if not disabled", () => {
|
|
55
|
+
const envs = getAllEnvsByTrigger(SIMPLE_CONFIG, "app1", "mainBranch");
|
|
56
|
+
expect(envs).toEqual(["dev"]);
|
|
57
|
+
});
|
|
58
|
+
it("returns additional dev environments", () => {
|
|
59
|
+
const envs = getAllEnvsByTrigger(SIMPLE_CONFIG, "app2", "mainBranch");
|
|
60
|
+
expect(envs).toEqual(["dev", "dev2"]);
|
|
61
|
+
});
|
|
62
|
+
it("does not include disabled envs", () => {
|
|
63
|
+
const envs = getAllEnvsByTrigger(SIMPLE_CONFIG, "app3", "mainBranch");
|
|
64
|
+
expect(envs).toEqual([]);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe("mr", () => {
|
|
69
|
+
it("always includes review if not disabled", () => {
|
|
70
|
+
const envs = getAllEnvsByTrigger(SIMPLE_CONFIG, "app1", "mr");
|
|
71
|
+
expect(envs).toEqual(["review"]);
|
|
72
|
+
});
|
|
73
|
+
it("returns additional dev environments", () => {
|
|
74
|
+
const envs = getAllEnvsByTrigger(SIMPLE_CONFIG, "app2", "mr");
|
|
75
|
+
expect(envs).toEqual(["review", "review2"]);
|
|
76
|
+
});
|
|
77
|
+
it("does not include disabled envs", () => {
|
|
78
|
+
const envs = getAllEnvsByTrigger(SIMPLE_CONFIG, "app3", "mr");
|
|
79
|
+
expect(envs).toEqual([]);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe("taggedRelease", () => {
|
|
84
|
+
it("always includes review if not disabled", () => {
|
|
85
|
+
const envs = getAllEnvsByTrigger(SIMPLE_CONFIG, "app1", "taggedRelease");
|
|
86
|
+
expect(envs).toEqual(["stage", "prod"]);
|
|
87
|
+
});
|
|
88
|
+
it("returns additional dev environments", () => {
|
|
89
|
+
const envs = getAllEnvsByTrigger(SIMPLE_CONFIG, "app2", "taggedRelease");
|
|
90
|
+
expect(envs).toEqual(["stage", "prod", "stage2", "prod2"]);
|
|
91
|
+
});
|
|
92
|
+
it("does not include disabled envs", () => {
|
|
93
|
+
const envs = getAllEnvsByTrigger(SIMPLE_CONFIG, "app3", "taggedRelease");
|
|
94
|
+
expect(envs).toEqual([]);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Config,
|
|
3
|
+
DEFAULT_ENV_TYPES,
|
|
4
|
+
EnvType,
|
|
5
|
+
getEnvTypesByTrigger,
|
|
6
|
+
PipelineTrigger,
|
|
7
|
+
} from "../types";
|
|
8
|
+
|
|
9
|
+
const getConfiguredAndDefaultEnvs = (
|
|
10
|
+
config: Config,
|
|
11
|
+
componentName: string,
|
|
12
|
+
envTypes: EnvType[]
|
|
13
|
+
) => {
|
|
14
|
+
const configuredEnvs = config.components[componentName].env ?? {};
|
|
15
|
+
// the default envs have the same name as the env types
|
|
16
|
+
// these can be disabled with settimg them to `false`
|
|
17
|
+
// this is the list of all not disabled envs. These are always returned
|
|
18
|
+
const enabledDefaultEnvs = envTypes.filter(
|
|
19
|
+
(e) => configuredEnvs[e] !== false
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const configuredCustomEnvs = Object.entries(
|
|
23
|
+
config.components[componentName].env ?? {}
|
|
24
|
+
)
|
|
25
|
+
.filter(
|
|
26
|
+
([, config]) =>
|
|
27
|
+
config &&
|
|
28
|
+
"type" in config &&
|
|
29
|
+
config.type &&
|
|
30
|
+
envTypes.includes(config.type)
|
|
31
|
+
)
|
|
32
|
+
.map(([envName]) => envName);
|
|
33
|
+
|
|
34
|
+
return [...new Set([...enabledDefaultEnvs, ...configuredCustomEnvs])];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const getAllEnvs = (config: Config, componentName: string) => {
|
|
38
|
+
return getConfiguredAndDefaultEnvs(config, componentName, DEFAULT_ENV_TYPES);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const getAllEnvsInAllComponents = (config: Config) => {
|
|
42
|
+
return [
|
|
43
|
+
...new Set(
|
|
44
|
+
Object.keys(config.components).flatMap((c) => getAllEnvs(config, c))
|
|
45
|
+
),
|
|
46
|
+
];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const getAllEnvsByTrigger = (
|
|
50
|
+
config: Config,
|
|
51
|
+
componentName: string,
|
|
52
|
+
trigger: PipelineTrigger
|
|
53
|
+
) => {
|
|
54
|
+
const envTypesByTrigger = getEnvTypesByTrigger(trigger);
|
|
55
|
+
return getConfiguredAndDefaultEnvs(config, componentName, envTypesByTrigger);
|
|
56
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "fs";
|
|
2
|
+
import { register } from "ts-node";
|
|
3
|
+
import { load } from "js-yaml";
|
|
4
|
+
import { Config } from "../types";
|
|
5
|
+
|
|
6
|
+
// allows us to load ts files
|
|
7
|
+
|
|
8
|
+
const fullPath = (directory: string, ext: string) =>
|
|
9
|
+
directory + "/catladder." + ext;
|
|
10
|
+
|
|
11
|
+
export const readConfigSync = (
|
|
12
|
+
directory: string = process.cwd()
|
|
13
|
+
): Config | null => {
|
|
14
|
+
register({
|
|
15
|
+
cwd: directory,
|
|
16
|
+
transpileOnly: true,
|
|
17
|
+
compilerOptions: {
|
|
18
|
+
module: "commonjs",
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const found = ["ts", "js", "yml", "yaml"].find((extension) =>
|
|
23
|
+
existsSync(fullPath(directory, extension))
|
|
24
|
+
);
|
|
25
|
+
if (found) {
|
|
26
|
+
if (found === "ts" || found === "js") {
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
28
|
+
return require(fullPath(directory, found)).default;
|
|
29
|
+
} else {
|
|
30
|
+
return load(
|
|
31
|
+
readFileSync(fullPath(directory, found), { encoding: "utf-8" })
|
|
32
|
+
) as Config;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
};
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { merge } from "lodash";
|
|
2
|
+
import slugify from "slugify";
|
|
3
|
+
import { BUILD_TYPES } from "../build";
|
|
4
|
+
import { BuildConfig } from "../build/types";
|
|
5
|
+
import { DEPLOY_TYPES } from "../deploy";
|
|
6
|
+
import { DeployConfig } from "../deploy/types";
|
|
7
|
+
import { Config, isKnowEnvType, DevLocalEnvConfig } from "../types/config";
|
|
8
|
+
import { CommitInfo, Context, Environment, YarnInfo } from "../types/context";
|
|
9
|
+
|
|
10
|
+
const sanitizeForEnVar = (s: string) => s.replace(/-/g, "_");
|
|
11
|
+
export const getSecretVarName = (
|
|
12
|
+
env: string,
|
|
13
|
+
componentName: string,
|
|
14
|
+
key: string
|
|
15
|
+
) => `CL_${sanitizeForEnVar(env)}_${sanitizeForEnVar(componentName)}_${key}`; // remove dash from component name
|
|
16
|
+
export const getEnvironment = (
|
|
17
|
+
config: Config,
|
|
18
|
+
componentName: string,
|
|
19
|
+
env: string,
|
|
20
|
+
commitInfo?: CommitInfo,
|
|
21
|
+
skipReferences = false // to prevent infinit loop
|
|
22
|
+
): Environment => {
|
|
23
|
+
const componentConfig = config.components[componentName];
|
|
24
|
+
if (!componentConfig) {
|
|
25
|
+
throw new Error("unknown component " + componentName);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const defaultConfig = componentConfig;
|
|
29
|
+
|
|
30
|
+
const envConfig = componentConfig.env?.[env] ?? {};
|
|
31
|
+
if (envConfig === false) {
|
|
32
|
+
throw new Error("env is disabled: " + env);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const mergedConfig = merge({}, defaultConfig, envConfig);
|
|
36
|
+
|
|
37
|
+
// env type: if its set manually, use that, otherwise use the known env types
|
|
38
|
+
|
|
39
|
+
const basePredefinedVariables = {
|
|
40
|
+
ENV_SHORT: env,
|
|
41
|
+
APP_DIR: componentConfig.dir,
|
|
42
|
+
};
|
|
43
|
+
const envType = envConfig?.type ?? (isKnowEnvType(env) ? env : null);
|
|
44
|
+
if (!envType) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
"Missing type in environment " + env + " in component " + componentName
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const environmentName =
|
|
50
|
+
envType === "review" && commitInfo
|
|
51
|
+
? `${env}/${commitInfo.refName}/${componentName}`
|
|
52
|
+
: `${env}/${componentName}`;
|
|
53
|
+
|
|
54
|
+
const environmentSlug =
|
|
55
|
+
envType === "review" && commitInfo
|
|
56
|
+
? `${env}-${commitInfo.refSlug}-${componentName}`
|
|
57
|
+
: `${env}-${componentName}`;
|
|
58
|
+
|
|
59
|
+
let predefinedVariables: Record<string, string>;
|
|
60
|
+
let hostname: string;
|
|
61
|
+
let url: string;
|
|
62
|
+
if (envType === "local") {
|
|
63
|
+
const devLocalConfig: DevLocalEnvConfig = mergedConfig;
|
|
64
|
+
const port = devLocalConfig.port ?? 3000;
|
|
65
|
+
hostname = "localhost:" + port;
|
|
66
|
+
url = "http://" + hostname;
|
|
67
|
+
predefinedVariables = {
|
|
68
|
+
ROOT_URL: url,
|
|
69
|
+
PORT: port.toString(),
|
|
70
|
+
};
|
|
71
|
+
} else {
|
|
72
|
+
const KUBE_NAMESPACE = `${config.customerName}-${config.appName}-${env}`;
|
|
73
|
+
const RELEASE_NAME = `${config.customerName}-${config.appName}-${environmentSlug}`;
|
|
74
|
+
|
|
75
|
+
const componentSlug = slugify(componentName);
|
|
76
|
+
const envInUrl =
|
|
77
|
+
envType === "review" && commitInfo ? `${commitInfo.refSlug}.${env}` : env;
|
|
78
|
+
|
|
79
|
+
const HOST_CANONICAL = `${config.appName}-${componentSlug}.${envInUrl}.${config.customerName}.panter.cloud`;
|
|
80
|
+
|
|
81
|
+
hostname = mergedConfig?.hostname ?? HOST_CANONICAL;
|
|
82
|
+
const url = `https://${hostname}`;
|
|
83
|
+
|
|
84
|
+
const KUBE_APP_NAME =
|
|
85
|
+
envType === "review" && commitInfo
|
|
86
|
+
? `${componentName}-${commitInfo.refSlug}`
|
|
87
|
+
: componentName;
|
|
88
|
+
|
|
89
|
+
predefinedVariables = {
|
|
90
|
+
...basePredefinedVariables,
|
|
91
|
+
HOST_CANONICAL,
|
|
92
|
+
ROOT_URL: url,
|
|
93
|
+
KUBE_NAMESPACE,
|
|
94
|
+
KUBE_APP_NAME,
|
|
95
|
+
RELEASE_NAME,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const publicEnvVars = mergedConfig.vars?.public ?? {};
|
|
99
|
+
const secretEnvVarKeys = mergedConfig.vars?.secret ?? [];
|
|
100
|
+
const secretEnvVars = Object.fromEntries(
|
|
101
|
+
secretEnvVarKeys.map((key) => [
|
|
102
|
+
key,
|
|
103
|
+
`$${getSecretVarName(env, componentName, key)}`,
|
|
104
|
+
])
|
|
105
|
+
);
|
|
106
|
+
const referencedRaw = mergedConfig.vars?.fromComponents ?? {};
|
|
107
|
+
|
|
108
|
+
const referenced = skipReferences
|
|
109
|
+
? {}
|
|
110
|
+
: Object.entries(referencedRaw).reduce((acc, [otherApp, mapping]) => {
|
|
111
|
+
const { envVars } = getEnvironment(
|
|
112
|
+
config,
|
|
113
|
+
otherApp,
|
|
114
|
+
env,
|
|
115
|
+
commitInfo,
|
|
116
|
+
true // prevent infinit loop
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
...acc,
|
|
121
|
+
...Object.fromEntries(
|
|
122
|
+
Object.entries(mapping).map(([ourKey, otherKey]) => [
|
|
123
|
+
ourKey,
|
|
124
|
+
envVars[otherKey],
|
|
125
|
+
])
|
|
126
|
+
),
|
|
127
|
+
};
|
|
128
|
+
}, {});
|
|
129
|
+
|
|
130
|
+
const envVars = {
|
|
131
|
+
...predefinedVariables,
|
|
132
|
+
...secretEnvVars,
|
|
133
|
+
...referenced,
|
|
134
|
+
...publicEnvVars,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
envType,
|
|
139
|
+
hostname,
|
|
140
|
+
fullName: environmentName,
|
|
141
|
+
slug: environmentSlug,
|
|
142
|
+
shortName: env,
|
|
143
|
+
url: predefinedVariables.ROOT_URL,
|
|
144
|
+
envVars,
|
|
145
|
+
secretEnvVarKeys,
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const createContext = (
|
|
150
|
+
config: Config,
|
|
151
|
+
componentName: string,
|
|
152
|
+
env: string,
|
|
153
|
+
commitInfo?: CommitInfo,
|
|
154
|
+
yarnInfo?: YarnInfo
|
|
155
|
+
): Context => {
|
|
156
|
+
if (!/^[a-z0-9-]+$/.test(componentName)) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
"componentName may only contain lower case letters, numbers and -"
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
const rawConfig = config.components[componentName];
|
|
162
|
+
if (!rawConfig) {
|
|
163
|
+
throw new Error("unknown component " + componentName);
|
|
164
|
+
}
|
|
165
|
+
// envs can override the config
|
|
166
|
+
const envConfig = rawConfig.env?.[env] ?? {};
|
|
167
|
+
const componentConfigWithoutDefaults = merge({}, rawConfig, envConfig);
|
|
168
|
+
|
|
169
|
+
// fill in defaults of build and deploy
|
|
170
|
+
const defaults: {
|
|
171
|
+
build: Partial<BuildConfig>;
|
|
172
|
+
deploy: Partial<DeployConfig>;
|
|
173
|
+
} = componentConfigWithoutDefaults.deploy
|
|
174
|
+
? {
|
|
175
|
+
build:
|
|
176
|
+
BUILD_TYPES[componentConfigWithoutDefaults.build.type].defaults(),
|
|
177
|
+
deploy:
|
|
178
|
+
DEPLOY_TYPES[componentConfigWithoutDefaults.deploy.type].defaults(),
|
|
179
|
+
}
|
|
180
|
+
: {
|
|
181
|
+
build: {},
|
|
182
|
+
deploy: {},
|
|
183
|
+
};
|
|
184
|
+
const componentConfig = merge({}, defaults, componentConfigWithoutDefaults);
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
fullConfig: config,
|
|
188
|
+
componentConfig,
|
|
189
|
+
componentName,
|
|
190
|
+
environment: getEnvironment(config, componentName, env, commitInfo),
|
|
191
|
+
commitInfo,
|
|
192
|
+
yarnInfo,
|
|
193
|
+
};
|
|
194
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { GitlabJob, Context, GitlabJobDef } from "../types";
|
|
2
|
+
|
|
3
|
+
export const DEPLOY_JOB_NAME = "🚀 Deploy";
|
|
4
|
+
export const STOP_JOB_NAME = "🛑 Stop ⚠️";
|
|
5
|
+
|
|
6
|
+
const DEPLOY_RUNNER_VARIABLES = {
|
|
7
|
+
KUBERNETES_CPU_REQUEST: "0.5",
|
|
8
|
+
KUBERNETES_CPU_LIMIT: "1",
|
|
9
|
+
KUBERNETES_MEMORY_REQUEST: "200Mi",
|
|
10
|
+
KUBERNETES_MEMORY_LIMIT: "500Mi",
|
|
11
|
+
};
|
|
12
|
+
type JobWithoutScript = Omit<GitlabJob, "job"> & {
|
|
13
|
+
job: Omit<GitlabJobDef, "script">;
|
|
14
|
+
};
|
|
15
|
+
export const getBaseDeploymentJob = (context: Context): JobWithoutScript => {
|
|
16
|
+
const environment = {
|
|
17
|
+
name: context.environment.fullName,
|
|
18
|
+
url: context.environment.url,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const autoStop =
|
|
22
|
+
context.environment.envType === "review"
|
|
23
|
+
? "2 weeks"
|
|
24
|
+
: context.environment.envType === "dev"
|
|
25
|
+
? "3 weeks"
|
|
26
|
+
: undefined;
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
name: DEPLOY_JOB_NAME,
|
|
30
|
+
envMode: "stagePerEnv", // makes it easier to run manual tasks er env
|
|
31
|
+
// we don't want to deploy when there is a broken test
|
|
32
|
+
needsStages: [
|
|
33
|
+
{
|
|
34
|
+
stage: "build",
|
|
35
|
+
artifacts: false,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
stage: "test",
|
|
39
|
+
artifacts: false,
|
|
40
|
+
},
|
|
41
|
+
], // workaround for https://gitlab.com/gitlab-org/gitlab/-/issues/220758
|
|
42
|
+
job: {
|
|
43
|
+
rules: [
|
|
44
|
+
context.environment.envType === "prod"
|
|
45
|
+
? {
|
|
46
|
+
when: "manual",
|
|
47
|
+
}
|
|
48
|
+
: {
|
|
49
|
+
when: "on_success",
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
stage: "deploy",
|
|
53
|
+
dependencies: [],
|
|
54
|
+
variables: {
|
|
55
|
+
...DEPLOY_RUNNER_VARIABLES,
|
|
56
|
+
},
|
|
57
|
+
environment: {
|
|
58
|
+
...environment,
|
|
59
|
+
on_stop: STOP_JOB_NAME,
|
|
60
|
+
auto_stop_in: autoStop,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const getBaseDeploymentStopJob = (
|
|
67
|
+
context: Context
|
|
68
|
+
): JobWithoutScript => {
|
|
69
|
+
const environment = {
|
|
70
|
+
name: context.environment.fullName,
|
|
71
|
+
url: context.environment.url,
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
name: STOP_JOB_NAME,
|
|
75
|
+
envMode: "stagePerEnv", // makes it easier to run manual tasks er env
|
|
76
|
+
job: {
|
|
77
|
+
needs: [DEPLOY_JOB_NAME],
|
|
78
|
+
rules: [
|
|
79
|
+
{
|
|
80
|
+
if: "$CI_COMMIT_BRANCH =~ /^[0-9]+\\.([0-9]+|x)\\.x$/", // automatic on hotfix branches
|
|
81
|
+
when: "on_success",
|
|
82
|
+
allow_failure: true,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
when: "manual",
|
|
86
|
+
allow_failure: true,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
variables: {
|
|
90
|
+
...DEPLOY_RUNNER_VARIABLES,
|
|
91
|
+
GIT_STRATEGY: "none",
|
|
92
|
+
},
|
|
93
|
+
stage: "stop",
|
|
94
|
+
dependencies: [],
|
|
95
|
+
environment: {
|
|
96
|
+
...environment,
|
|
97
|
+
action: "stop",
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { GitlabJobs } from "../types/gitlab-types";
|
|
2
|
+
import { Context } from "../types/context";
|
|
3
|
+
import { createKubernetesDeployJobs } from "./kubernetes";
|
|
4
|
+
import { DeployConfig } from "./types";
|
|
5
|
+
|
|
6
|
+
export type DeployTypes = {
|
|
7
|
+
[type in DeployConfig["type"]]: {
|
|
8
|
+
jobs: (context: Context) => GitlabJobs;
|
|
9
|
+
defaults: () => Partial<Extract<DeployConfig, { type: type }>>;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export * from "./types";
|
|
14
|
+
export const DEPLOY_TYPES: DeployTypes = {
|
|
15
|
+
kubernetes: {
|
|
16
|
+
jobs: createKubernetesDeployJobs,
|
|
17
|
+
defaults: () => ({}),
|
|
18
|
+
},
|
|
19
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Context, getSecretVarName } from "../..";
|
|
2
|
+
|
|
3
|
+
export const createCloudsqlBaseConfig = (context: Context) => {
|
|
4
|
+
return {
|
|
5
|
+
cloudsql: {
|
|
6
|
+
proxyCredentials: `$${getSecretVarName(
|
|
7
|
+
context.environment.shortName,
|
|
8
|
+
context.componentName,
|
|
9
|
+
"cloudsqlProxyCredentials"
|
|
10
|
+
)}`,
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
};
|