@catladder/pipeline 0.0.3 → 0.0.7
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/scripts/createSamplePipeline.d.ts +2 -0
- package/dist/scripts/createSamplePipeline.js +14 -0
- package/dist/scripts/magic/build/docker.d.ts +2 -0
- package/dist/scripts/magic/build/docker.js +68 -0
- package/dist/scripts/magic/build/index.d.ts +9 -0
- package/dist/scripts/magic/build/index.js +12 -0
- package/dist/scripts/magic/build/node.d.ts +6 -0
- package/dist/scripts/magic/build/node.js +150 -0
- package/dist/scripts/magic/build/types.d.ts +18 -0
- package/dist/scripts/magic/build/types.js +7 -0
- package/dist/scripts/magic/context/index.d.ts +3 -0
- package/dist/scripts/magic/context/index.js +122 -0
- package/dist/scripts/magic/createChildPipeline/index.d.ts +3 -0
- package/dist/scripts/magic/createChildPipeline/index.js +68 -0
- package/dist/scripts/magic/createPipeline.d.ts +14 -0
- package/dist/scripts/magic/createPipeline.js +80 -0
- package/dist/scripts/magic/deploy/index.d.ts +9 -0
- package/dist/scripts/magic/deploy/index.js +12 -0
- package/dist/scripts/magic/deploy/kubernetes.d.ts +5 -0
- package/dist/scripts/magic/deploy/kubernetes.js +62 -0
- package/dist/scripts/magic/deploy/types.d.ts +41 -0
- package/dist/scripts/magic/deploy/types.js +7 -0
- package/dist/scripts/magic/index.d.ts +2 -0
- package/dist/scripts/magic/sample-config.d.ts +3 -0
- package/dist/scripts/magic/sample-config.js +77 -0
- package/dist/scripts/magic/tests/createPipeline.test.d.ts +1 -0
- package/dist/scripts/magic/tests/createPipeline.test.js +89 -0
- package/dist/scripts/magic/types/config.d.ts +49 -0
- package/dist/scripts/magic/types/config.js +17 -0
- package/dist/scripts/magic/types/context.d.ts +19 -0
- package/dist/scripts/magic/types/context.js +2 -0
- package/dist/scripts/magic/types/gitlab-types.d.ts +57 -0
- package/dist/scripts/magic/types/gitlab-types.js +2 -0
- package/dist/scripts/magic/types/index.d.ts +3 -0
- package/dist/scripts/magic/types/index.js +15 -0
- package/dist/scripts/magic.d.ts +2 -0
- package/dist/scripts/magic.js +43 -0
- package/dist/scripts/monorepoGenerate.d.ts +2 -0
- package/dist/scripts/monorepoGenerate.js +164 -0
- package/dist/scripts/printAllValues.d.ts +2 -0
- package/dist/scripts/printAllValues.js +58 -0
- package/dist/scripts/printBuildEnv.d.ts +2 -0
- package/dist/scripts/printBuildEnv.js +77 -0
- package/dist/scripts/utils/extractAllValues.d.ts +1 -0
- package/dist/scripts/utils/extractAllValues.js +78 -0
- package/dist/scripts/utils/extractBuildEnv.d.ts +5 -0
- package/dist/scripts/utils/extractBuildEnv.js +152 -0
- package/dist/scripts/utils/extractValuesFromEnvVars.d.ts +2 -0
- package/dist/scripts/utils/extractValuesFromEnvVars.js +63 -0
- package/dist/scripts/utils/extractValuesFromMr.d.ts +2 -0
- package/dist/scripts/utils/extractValuesFromMr.js +86 -0
- package/dist/tests/extractValuesFromMr.test.d.ts +1 -0
- package/dist/tests/extractValuesFromMr.test.js +68 -0
- package/package.json +3 -2
- package/scripts/magic/build/docker.ts +2 -2
- package/scripts/magic/build/index.ts +3 -1
- package/scripts/magic/build/node.ts +26 -13
- package/scripts/magic/build/types.ts +6 -2
- package/scripts/magic/context/index.ts +127 -0
- package/scripts/magic/createChildPipeline/index.ts +5 -121
- package/scripts/magic/tests/createPipeline.test.ts +7 -7
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (_) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
exports.__esModule = true;
|
|
39
|
+
exports.extractValuesFromMr = exports.extractValuesFromMRMessage = void 0;
|
|
40
|
+
var node_1 = require("@gitbeaker/node"); // Just the Project Resource
|
|
41
|
+
var yaml_1 = require("yaml");
|
|
42
|
+
var lodash_1 = require("lodash");
|
|
43
|
+
var _a = process.env, GL_TOKEN = _a.GL_TOKEN, CI_SERVER_URL = _a.CI_SERVER_URL;
|
|
44
|
+
var gitlabApi = new node_1.Gitlab({
|
|
45
|
+
token: GL_TOKEN,
|
|
46
|
+
host: CI_SERVER_URL
|
|
47
|
+
});
|
|
48
|
+
var getMRInfo = function (projectId, mrId) { return __awaiter(void 0, void 0, void 0, function () {
|
|
49
|
+
return __generator(this, function (_a) {
|
|
50
|
+
switch (_a.label) {
|
|
51
|
+
case 0: return [4 /*yield*/, gitlabApi.MergeRequests.show(projectId, mrId)];
|
|
52
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}); };
|
|
56
|
+
var extractValuesFromMRMessage = function (mrMessage) {
|
|
57
|
+
var codeBlocks = Array.from(mrMessage.matchAll(/```.*([^`]+)```/gm)).map(function (match) { return match[1]; });
|
|
58
|
+
return codeBlocks.reduce(function (values, block) {
|
|
59
|
+
if (values === void 0) { values = {}; }
|
|
60
|
+
if (block.includes("$env") || block.includes("$values"))
|
|
61
|
+
try {
|
|
62
|
+
var _a = yaml_1.parse(block), $values = _a.$values, $env = _a.$env;
|
|
63
|
+
if ($values)
|
|
64
|
+
lodash_1.merge(values, $values);
|
|
65
|
+
if ($env)
|
|
66
|
+
lodash_1.merge(values, { env: { public: $env } });
|
|
67
|
+
return values;
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
console.warn(e);
|
|
71
|
+
}
|
|
72
|
+
}, {});
|
|
73
|
+
};
|
|
74
|
+
exports.extractValuesFromMRMessage = extractValuesFromMRMessage;
|
|
75
|
+
var extractValuesFromMr = function (projectId, mergeRequestId) { return __awaiter(void 0, void 0, void 0, function () {
|
|
76
|
+
var mrInfo;
|
|
77
|
+
return __generator(this, function (_a) {
|
|
78
|
+
switch (_a.label) {
|
|
79
|
+
case 0: return [4 /*yield*/, getMRInfo(projectId, mergeRequestId)];
|
|
80
|
+
case 1:
|
|
81
|
+
mrInfo = _a.sent();
|
|
82
|
+
return [2 /*return*/, exports.extractValuesFromMRMessage(mrInfo.description)];
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}); };
|
|
86
|
+
exports.extractValuesFromMr = extractValuesFromMr;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
exports.__esModule = true;
|
|
3
|
+
var extractValuesFromMr_1 = require("../scripts/utils/extractValuesFromMr");
|
|
4
|
+
describe("extractValuesFromMr", function () {
|
|
5
|
+
describe("extractValuesFromMRMessage", function () {
|
|
6
|
+
it("can extract $values yaml", function () {
|
|
7
|
+
var result = extractValuesFromMr_1.extractValuesFromMRMessage("\n \n blabla\n\n test\n\n ```\n $values:\n application:\n host: www.foo.com\n env:\n public:\n API_KEY: fooooxxx\n BLA: \"blubb\"\n ```\n ");
|
|
8
|
+
expect(result).toEqual({
|
|
9
|
+
application: {
|
|
10
|
+
host: "www.foo.com"
|
|
11
|
+
},
|
|
12
|
+
env: {
|
|
13
|
+
public: {
|
|
14
|
+
API_KEY: "fooooxxx",
|
|
15
|
+
BLA: "blubb"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
it("can handle $env as shortcut", function () {
|
|
21
|
+
var result = extractValuesFromMr_1.extractValuesFromMRMessage("\n \n blabla\n\n test\n\n ```\n $env:\n API_KEY: fooooxxx\n BLA: \"blubb\"\n \n ```\n ");
|
|
22
|
+
expect(result).toEqual({
|
|
23
|
+
env: {
|
|
24
|
+
public: {
|
|
25
|
+
API_KEY: "fooooxxx",
|
|
26
|
+
BLA: "blubb"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
it("ignores language in backticks", function () {
|
|
32
|
+
var result = extractValuesFromMr_1.extractValuesFromMRMessage("\n \n blabla\n\n test\n\n ```yaml\n $env:\n API_KEY: fooooxxx\n BLA: \"blubb\"\n \n ```\n ");
|
|
33
|
+
expect(result).toEqual({
|
|
34
|
+
env: {
|
|
35
|
+
public: {
|
|
36
|
+
API_KEY: "fooooxxx",
|
|
37
|
+
BLA: "blubb"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it("can handle mixed blocks", function () {
|
|
43
|
+
var result = extractValuesFromMr_1.extractValuesFromMRMessage("\n \n blabla\n\n test\n\n ```\n $values:\n env:\n public:\n FOO: \"bar\"\n\n $env:\n API_KEY: fooooxxx\n BLA: \"blubb\"\n \n ```\n ");
|
|
44
|
+
expect(result).toEqual({
|
|
45
|
+
env: {
|
|
46
|
+
public: {
|
|
47
|
+
FOO: "bar",
|
|
48
|
+
API_KEY: "fooooxxx",
|
|
49
|
+
BLA: "blubb"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
it("can handle multiple blocks", function () {
|
|
55
|
+
var result = extractValuesFromMr_1.extractValuesFromMRMessage("\n \n blabla\n\n test\n\n ```\n $values:\n env:\n public:\n FOO: \"bar\"\n\n $env:\n API_KEY: fooooxxx\n BLA: \"blubb\"\n \n ```\n\n\n fooo\n\n ```\n $values:\n env:\n public:\n FOO: \"blubb\"\n\n $env:\n TEST: test\n \n ```\n ");
|
|
56
|
+
expect(result).toEqual({
|
|
57
|
+
env: {
|
|
58
|
+
public: {
|
|
59
|
+
FOO: "blubb",
|
|
60
|
+
API_KEY: "fooooxxx",
|
|
61
|
+
BLA: "blubb",
|
|
62
|
+
TEST: "test"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@catladder/pipeline",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepack": "yarn tsc"
|
|
6
6
|
},
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"@types/lodash": "^4.14.172",
|
|
11
11
|
"@types/node": "^16.6.1",
|
|
12
|
-
"@types/yargs": "^17.0.5"
|
|
12
|
+
"@types/yargs": "^17.0.5",
|
|
13
|
+
"typescript": "^4.5.4"
|
|
13
14
|
},
|
|
14
15
|
"dependencies": {
|
|
15
16
|
"@gitbeaker/node": "^32.1.2",
|
|
@@ -19,7 +19,7 @@ export const createDockerBuildJob = (
|
|
|
19
19
|
APP_DIR: context.componentConfig.dir,
|
|
20
20
|
DOCKER_HOST: "tcp://0.0.0.0:2375",
|
|
21
21
|
DOCKER_TLS_CERTDIR: "",
|
|
22
|
-
DOCKER_DIR: ".",
|
|
22
|
+
DOCKER_DIR: ".", // relative to componentdir
|
|
23
23
|
IMAGE_TAG: "$CI_COMMIT_SHA",
|
|
24
24
|
DOCKER_DRIVER: "overlay2",
|
|
25
25
|
IMAGE_NAME: "$CI_REGISTRY_IMAGE/" + context.componentName,
|
|
@@ -34,7 +34,7 @@ export const createDockerBuildJob = (
|
|
|
34
34
|
...script,
|
|
35
35
|
"docker login --username gitlab-ci-token --password $CI_JOB_TOKEN $CI_REGISTRY",
|
|
36
36
|
"docker pull $CACHE_IMAGE || true",
|
|
37
|
-
"docker build --network host --cache-from $CACHE_IMAGE --tag $IMAGE_NAME:$IMAGE_TAG $
|
|
37
|
+
"docker build --network host --cache-from $CACHE_IMAGE --tag $IMAGE_NAME:$IMAGE_TAG -f $APP_DIR/Dockerfile .",
|
|
38
38
|
"docker push $IMAGE_NAME:$IMAGE_TAG",
|
|
39
39
|
"docker tag $IMAGE_NAME:$IMAGE_TAG $CACHE_IMAGE",
|
|
40
40
|
"docker push $CACHE_IMAGE",
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { GitlabJobs } from "../types/gitlab-types";
|
|
2
2
|
import { Context } from "../types/context";
|
|
3
|
-
import { createNodeJobs, getNodeDefaults } from "./node";
|
|
3
|
+
import { createNodeJobs, getNodeDefaults, getNodeStaticDefaults } from "./node";
|
|
4
4
|
import { BuildConfig } from "./types";
|
|
5
5
|
|
|
6
6
|
export const buildJobCreators: {
|
|
7
7
|
[type in BuildConfig["type"]]: (context: Context) => GitlabJobs;
|
|
8
8
|
} = {
|
|
9
9
|
node: createNodeJobs,
|
|
10
|
+
"node-static": createNodeJobs,
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
export const getBuildDefaults: {
|
|
13
14
|
[type in BuildConfig["type"]]: () => Partial<BuildConfig>;
|
|
14
15
|
} = {
|
|
15
16
|
node: getNodeDefaults,
|
|
17
|
+
"node-static": getNodeStaticDefaults,
|
|
16
18
|
};
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "../types/gitlab-types";
|
|
7
7
|
import { Context } from "../types/context";
|
|
8
8
|
import { createDockerBuildJob } from "./docker";
|
|
9
|
-
import { BuildConfigNode, isOfType } from "./types";
|
|
9
|
+
import { BuildConfigNode, BuildConfigNodeStatic, isOfType } from "./types";
|
|
10
10
|
|
|
11
11
|
const baseRetry: Retry = {
|
|
12
12
|
max: 2,
|
|
@@ -18,20 +18,27 @@ const getYarnInstall = (context: Context) => [
|
|
|
18
18
|
"if [ -f ./.nvmrc ]; then source /root/.nvm/nvm.sh && nvm install <<< .nvmrc; fi",
|
|
19
19
|
"yarn install --frozen-lockfile",
|
|
20
20
|
];
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
];
|
|
21
|
+
const getNodeCache = (context: Context): GitlabJobCache[] => [
|
|
22
|
+
{
|
|
23
|
+
key: "node-modules",
|
|
24
|
+
policy: "pull-push",
|
|
25
|
+
paths: ["node_modules", "**/node_modules/"],
|
|
26
|
+
},
|
|
27
|
+
];
|
|
29
28
|
|
|
29
|
+
const getNextCache = (context: Context): GitlabJobCache[] => [
|
|
30
|
+
{
|
|
31
|
+
key: "next-cache",
|
|
32
|
+
policy: "pull-push",
|
|
33
|
+
paths: [context.componentConfig.dir + "/.next/cache/"],
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
const createNodeTestJobs = (context: Context): GitlabJobs => {
|
|
30
37
|
const base: Omit<GitlabJobDef, "script"> = {
|
|
31
38
|
variables: {
|
|
32
39
|
APP_PATH: context.componentConfig.dir,
|
|
33
40
|
},
|
|
34
|
-
cache,
|
|
41
|
+
cache: getNodeCache(context),
|
|
35
42
|
stage: "test",
|
|
36
43
|
interruptible: true,
|
|
37
44
|
needs: [],
|
|
@@ -69,7 +76,7 @@ const createNodeTestJobs = (context: Context): GitlabJobs => {
|
|
|
69
76
|
|
|
70
77
|
const createNodeBuildJobs = (context: Context): GitlabJobs => {
|
|
71
78
|
const buildConfig = context.componentConfig.build;
|
|
72
|
-
if (!isOfType(buildConfig, "node")) {
|
|
79
|
+
if (!isOfType(buildConfig, "node") && !isOfType(buildConfig, "node-static")) {
|
|
73
80
|
// should not happen
|
|
74
81
|
throw new Error("deploy config is not kubernetes");
|
|
75
82
|
}
|
|
@@ -86,6 +93,7 @@ const createNodeBuildJobs = (context: Context): GitlabJobs => {
|
|
|
86
93
|
name: "app-build",
|
|
87
94
|
job: {
|
|
88
95
|
needs: [],
|
|
96
|
+
cache: [...getNodeCache(context), ...getNextCache(context)],
|
|
89
97
|
variables: context.environment.variables,
|
|
90
98
|
retry: baseRetry,
|
|
91
99
|
interruptible: true,
|
|
@@ -106,7 +114,7 @@ const createNodeBuildJobs = (context: Context): GitlabJobs => {
|
|
|
106
114
|
job: {
|
|
107
115
|
...createDockerBuildJob(context, {
|
|
108
116
|
script: [
|
|
109
|
-
buildConfig.
|
|
117
|
+
buildConfig.type === "node-static"
|
|
110
118
|
? "ensureNginxDockerfile"
|
|
111
119
|
: "ensureNodeDockerfile",
|
|
112
120
|
], // TOOD: inline
|
|
@@ -124,7 +132,12 @@ export const createNodeJobs = (context: Context): GitlabJobs => {
|
|
|
124
132
|
export const getNodeDefaults = (): Partial<BuildConfigNode> => {
|
|
125
133
|
return {
|
|
126
134
|
startCommand: "yarn start",
|
|
127
|
-
|
|
135
|
+
buildCommand: "yarn build",
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const getNodeStaticDefaults = (): Partial<BuildConfigNodeStatic> => {
|
|
140
|
+
return {
|
|
128
141
|
buildCommand: "yarn build",
|
|
129
142
|
};
|
|
130
143
|
};
|
|
@@ -3,11 +3,15 @@ export type BuildConfigBase = {
|
|
|
3
3
|
};
|
|
4
4
|
export type BuildConfigNode = {
|
|
5
5
|
type: "node";
|
|
6
|
-
runtime?: "dynamic" | "static"; // defaults to dynamic
|
|
7
6
|
buildCommand?: string;
|
|
8
7
|
} & BuildConfigBase;
|
|
9
8
|
|
|
10
|
-
export type
|
|
9
|
+
export type BuildConfigNodeStatic = {
|
|
10
|
+
type: "node-static";
|
|
11
|
+
buildCommand?: string;
|
|
12
|
+
startCommand: never;
|
|
13
|
+
};
|
|
14
|
+
export type BuildConfig = BuildConfigNode | BuildConfigNodeStatic;
|
|
11
15
|
|
|
12
16
|
export const isOfType = <T extends BuildConfig["type"]>(
|
|
13
17
|
t: BuildConfig,
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { merge } from "lodash";
|
|
2
|
+
import slugify from "slugify";
|
|
3
|
+
import { getBuildDefaults } from "../build";
|
|
4
|
+
import { BuildConfig } from "../build/types";
|
|
5
|
+
import { getDeployDefaults } from "../deploy";
|
|
6
|
+
import { DeployConfig } from "../deploy/types";
|
|
7
|
+
import { Config } from "../types/config";
|
|
8
|
+
import { CommitInfo, Context, Environment } from "../types/context";
|
|
9
|
+
|
|
10
|
+
const getEnvironment = (
|
|
11
|
+
config: Config,
|
|
12
|
+
componentName: string,
|
|
13
|
+
env: string,
|
|
14
|
+
commitInfo: CommitInfo
|
|
15
|
+
): Environment => {
|
|
16
|
+
const componentConfig = config.components[componentName];
|
|
17
|
+
if (!componentConfig) {
|
|
18
|
+
throw new Error("unknown component " + componentName);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const defaultConfig = componentConfig;
|
|
22
|
+
const envConfig = componentConfig.env?.[env] ?? {};
|
|
23
|
+
|
|
24
|
+
const mergedConfig = merge({}, defaultConfig, envConfig);
|
|
25
|
+
|
|
26
|
+
const publicEnvVars = mergedConfig.vars?.public ?? {};
|
|
27
|
+
const secretEnvVarsRaw = mergedConfig.vars?.secret ?? {}; // TODO, map to gl secrets?
|
|
28
|
+
const secretEnvVars = {}; // TODO
|
|
29
|
+
const referencedRaw = mergedConfig.vars?.fromComponents ?? {};
|
|
30
|
+
|
|
31
|
+
const referenced = Object.entries(referencedRaw).reduce(
|
|
32
|
+
(acc, [otherApp, mapping]) => {
|
|
33
|
+
// TODO: prevent infinit looop
|
|
34
|
+
const { variables } = getEnvironment(config, otherApp, env, commitInfo);
|
|
35
|
+
|
|
36
|
+
return Object.fromEntries(
|
|
37
|
+
Object.entries(mapping).map(([ourKey, otherKey]) => [
|
|
38
|
+
ourKey,
|
|
39
|
+
variables[otherKey],
|
|
40
|
+
])
|
|
41
|
+
);
|
|
42
|
+
},
|
|
43
|
+
{}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const envType = componentConfig.env?.[env]?.type ?? env;
|
|
47
|
+
const environmentName =
|
|
48
|
+
envType === "review"
|
|
49
|
+
? `${env}/${componentName}/${commitInfo.refName}`
|
|
50
|
+
: `${env}/${componentName}`;
|
|
51
|
+
|
|
52
|
+
const KUBE_APP_NAME =
|
|
53
|
+
envType === "review"
|
|
54
|
+
? `${componentName}-${commitInfo.refSlug}`
|
|
55
|
+
: componentName;
|
|
56
|
+
|
|
57
|
+
const KUBE_NAMESPACE = `${config.customerName}-${config.appName}-${env}`;
|
|
58
|
+
|
|
59
|
+
const APP_SLUG = slugify(KUBE_APP_NAME);
|
|
60
|
+
|
|
61
|
+
const HOST_CANONICAL = `${config.appName}-${APP_SLUG}.${config.customerName}.panter.cloud`;
|
|
62
|
+
|
|
63
|
+
const hostname = mergedConfig.hostname ?? HOST_CANONICAL;
|
|
64
|
+
const url = `https://${hostname}`;
|
|
65
|
+
|
|
66
|
+
const predefinedVariables = {
|
|
67
|
+
HOST_CANONICAL,
|
|
68
|
+
ROOT_URL: url,
|
|
69
|
+
KUBE_NAMESPACE,
|
|
70
|
+
KUBE_APP_NAME,
|
|
71
|
+
ENV_SHORT: env,
|
|
72
|
+
APP_DIR: componentConfig.dir,
|
|
73
|
+
};
|
|
74
|
+
const variables = {
|
|
75
|
+
...predefinedVariables,
|
|
76
|
+
...publicEnvVars,
|
|
77
|
+
...secretEnvVars,
|
|
78
|
+
...referenced,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
hostname,
|
|
83
|
+
fullName: environmentName,
|
|
84
|
+
shortName: env,
|
|
85
|
+
url: url,
|
|
86
|
+
variables,
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const createContext = (
|
|
91
|
+
componentName: string,
|
|
92
|
+
config: Config,
|
|
93
|
+
env: string
|
|
94
|
+
): Context => {
|
|
95
|
+
if (!/^[a-z0-9-]+$/.test(componentName)) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
"componentName may only contain lower case letters, numbers and -"
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
const rawConfig = config.components[componentName];
|
|
101
|
+
if (!rawConfig) {
|
|
102
|
+
throw new Error("unknown component " + componentName);
|
|
103
|
+
}
|
|
104
|
+
// envs can override the config
|
|
105
|
+
const envConfig = rawConfig.env?.[env] ?? {};
|
|
106
|
+
const componentConfigWithoutDefaults = merge({}, rawConfig, envConfig);
|
|
107
|
+
// fill in defaults of build and deploy
|
|
108
|
+
const defaults: {
|
|
109
|
+
build: Partial<BuildConfig>;
|
|
110
|
+
deploy: Partial<DeployConfig>;
|
|
111
|
+
} = {
|
|
112
|
+
build: getBuildDefaults[componentConfigWithoutDefaults.build.type](),
|
|
113
|
+
deploy: getDeployDefaults[componentConfigWithoutDefaults.deploy.type](),
|
|
114
|
+
};
|
|
115
|
+
const componentConfig = merge({}, defaults, componentConfigWithoutDefaults);
|
|
116
|
+
const commit = {
|
|
117
|
+
refName: process.env.CI_COMMIT_REF_NAME ?? "unknown",
|
|
118
|
+
refSlug: process.env.CI_COMMIT_REF_SLUG ?? "unknown",
|
|
119
|
+
};
|
|
120
|
+
return {
|
|
121
|
+
fullConfig: config,
|
|
122
|
+
componentConfig,
|
|
123
|
+
componentName,
|
|
124
|
+
environment: getEnvironment(config, componentName, env, commit),
|
|
125
|
+
commit: commit,
|
|
126
|
+
};
|
|
127
|
+
};
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { merge } from "lodash";
|
|
2
2
|
import slugify from "slugify";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import {
|
|
3
|
+
import { buildJobCreators } from "../build";
|
|
4
|
+
import { createContext } from "../context";
|
|
5
|
+
import { deployJobCreators } from "../deploy";
|
|
6
|
+
import { Config } from "../types/config";
|
|
6
7
|
import { CommitInfo, Context, Environment } from "../types/context";
|
|
7
|
-
import {
|
|
8
|
-
import { buildJobCreators, getBuildDefaults } from "../build";
|
|
9
|
-
import { BuildConfig } from "../build/types";
|
|
10
|
-
import { DeployConfig } from "../deploy/types";
|
|
8
|
+
import { GitlabJobDef, GitlabJobs } from "../types/gitlab-types";
|
|
11
9
|
|
|
12
10
|
const createRawJobs = (context: Context): GitlabJobs => {
|
|
13
11
|
const buildJobs =
|
|
@@ -17,120 +15,6 @@ const createRawJobs = (context: Context): GitlabJobs => {
|
|
|
17
15
|
|
|
18
16
|
return [...buildJobs, ...deployJobs];
|
|
19
17
|
};
|
|
20
|
-
|
|
21
|
-
const getEnvironment = (
|
|
22
|
-
config: Config,
|
|
23
|
-
componentName: string,
|
|
24
|
-
env: string,
|
|
25
|
-
commitInfo: CommitInfo
|
|
26
|
-
): Environment => {
|
|
27
|
-
const componentConfig = config.components[componentName];
|
|
28
|
-
if (!componentConfig) {
|
|
29
|
-
throw new Error("unknown component " + componentName);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const defaultConfig = componentConfig;
|
|
33
|
-
const envConfig = componentConfig.env?.[env] ?? {};
|
|
34
|
-
|
|
35
|
-
const mergedConfig = merge({}, defaultConfig, envConfig);
|
|
36
|
-
|
|
37
|
-
const publicEnvVars = mergedConfig.vars?.public ?? {};
|
|
38
|
-
const secretEnvVarsRaw = mergedConfig.vars?.secret ?? {}; // TODO, map to gl secrets?
|
|
39
|
-
const secretEnvVars = {}; // TODO
|
|
40
|
-
const referencedRaw = mergedConfig.vars?.fromComponents ?? {};
|
|
41
|
-
|
|
42
|
-
const referenced = Object.entries(referencedRaw).reduce(
|
|
43
|
-
(acc, [otherApp, mapping]) => {
|
|
44
|
-
// TODO: prevent infinit looop
|
|
45
|
-
const { variables } = getEnvironment(config, otherApp, env, commitInfo);
|
|
46
|
-
|
|
47
|
-
return Object.fromEntries(
|
|
48
|
-
Object.entries(mapping).map(([ourKey, otherKey]) => [
|
|
49
|
-
ourKey,
|
|
50
|
-
variables[otherKey],
|
|
51
|
-
])
|
|
52
|
-
);
|
|
53
|
-
},
|
|
54
|
-
{}
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
const envType = componentConfig.env?.[env]?.type ?? env;
|
|
58
|
-
const environmentName =
|
|
59
|
-
envType === "review"
|
|
60
|
-
? `${env}-${componentName}/${commitInfo.refName}`
|
|
61
|
-
: `${env}-${componentName}`;
|
|
62
|
-
|
|
63
|
-
const KUBE_APP_NAME =
|
|
64
|
-
envType === "review"
|
|
65
|
-
? `${componentName}-${commitInfo.refSlug}`
|
|
66
|
-
: componentName;
|
|
67
|
-
|
|
68
|
-
const KUBE_NAMESPACE = `${config.customerName}-${config.appName}-${env}`;
|
|
69
|
-
|
|
70
|
-
const APP_SLUG = slugify(KUBE_APP_NAME);
|
|
71
|
-
|
|
72
|
-
const HOST_CANONICAL = `${config.appName}-${APP_SLUG}.${config.customerName}.panter.cloud`;
|
|
73
|
-
|
|
74
|
-
const hostname = mergedConfig.hostname ?? HOST_CANONICAL;
|
|
75
|
-
const url = `https://${hostname}`;
|
|
76
|
-
|
|
77
|
-
const predefinedVariables = {
|
|
78
|
-
HOST_CANONICAL,
|
|
79
|
-
ROOT_URL: url,
|
|
80
|
-
KUBE_NAMESPACE,
|
|
81
|
-
KUBE_APP_NAME,
|
|
82
|
-
ENV_SHORT: env,
|
|
83
|
-
};
|
|
84
|
-
const variables = {
|
|
85
|
-
...predefinedVariables,
|
|
86
|
-
...publicEnvVars,
|
|
87
|
-
...secretEnvVars,
|
|
88
|
-
...referenced,
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
hostname,
|
|
93
|
-
fullName: environmentName,
|
|
94
|
-
shortName: env,
|
|
95
|
-
url: url,
|
|
96
|
-
variables,
|
|
97
|
-
};
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export const createContext = (
|
|
101
|
-
componentName: string,
|
|
102
|
-
config: Config,
|
|
103
|
-
env: string
|
|
104
|
-
): Context => {
|
|
105
|
-
const rawConfig = config.components[componentName];
|
|
106
|
-
if (!rawConfig) {
|
|
107
|
-
throw new Error("unknown component " + componentName);
|
|
108
|
-
}
|
|
109
|
-
// envs can override the config
|
|
110
|
-
const envConfig = rawConfig.env?.[env] ?? {};
|
|
111
|
-
const componentConfigWithoutDefaults = merge({}, rawConfig, envConfig);
|
|
112
|
-
// fill in defaults of build and deploy
|
|
113
|
-
const defaults: {
|
|
114
|
-
build: Partial<BuildConfig>;
|
|
115
|
-
deploy: Partial<DeployConfig>;
|
|
116
|
-
} = {
|
|
117
|
-
build: getBuildDefaults[componentConfigWithoutDefaults.build.type](),
|
|
118
|
-
deploy: getDeployDefaults[componentConfigWithoutDefaults.deploy.type](),
|
|
119
|
-
};
|
|
120
|
-
const componentConfig = merge({}, componentConfigWithoutDefaults, defaults);
|
|
121
|
-
const commit = {
|
|
122
|
-
refName: process.env.CI_COMMIT_REF_NAME ?? "unknown",
|
|
123
|
-
refSlug: process.env.CI_COMMIT_REF_SLUG ?? "unknown",
|
|
124
|
-
};
|
|
125
|
-
return {
|
|
126
|
-
fullConfig: config,
|
|
127
|
-
componentConfig,
|
|
128
|
-
componentName,
|
|
129
|
-
environment: getEnvironment(config, componentName, env, commit),
|
|
130
|
-
commit: commit,
|
|
131
|
-
};
|
|
132
|
-
};
|
|
133
|
-
|
|
134
18
|
const getFullJobName = (name: string, componentName: string, env?: string) => {
|
|
135
19
|
if (env) {
|
|
136
20
|
return `${env} ${componentName} ${name}`;
|
|
@@ -7,7 +7,7 @@ describe("createPipeline", () => {
|
|
|
7
7
|
appName: "test",
|
|
8
8
|
customerName: "pan",
|
|
9
9
|
components: {
|
|
10
|
-
|
|
10
|
+
"my-app": {
|
|
11
11
|
dir: "myapp",
|
|
12
12
|
build: {
|
|
13
13
|
type: "node",
|
|
@@ -29,12 +29,12 @@ describe("createPipeline", () => {
|
|
|
29
29
|
);
|
|
30
30
|
|
|
31
31
|
expect(Object.keys(jobs)).toEqual([
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"dev
|
|
36
|
-
"dev
|
|
37
|
-
"dev
|
|
32
|
+
"my-app audit",
|
|
33
|
+
"my-app lint",
|
|
34
|
+
"my-app test",
|
|
35
|
+
"dev my-app app-build",
|
|
36
|
+
"dev my-app docker-build",
|
|
37
|
+
"dev my-app deploy-to-kubernetes",
|
|
38
38
|
]);
|
|
39
39
|
});
|
|
40
40
|
});
|