@catladder/pipeline 0.0.6 → 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.
@@ -59,7 +59,7 @@ var createDockerBuildJob = function (context, _a) {
59
59
  return __assign(__assign({}, base), { script: __spreadArray(__spreadArray([], __read(script)), [
60
60
  "docker login --username gitlab-ci-token --password $CI_JOB_TOKEN $CI_REGISTRY",
61
61
  "docker pull $CACHE_IMAGE || true",
62
- "docker build --network host --cache-from $CACHE_IMAGE --tag $IMAGE_NAME:$IMAGE_TAG $DOCKER_DIR",
62
+ "docker build --network host --cache-from $CACHE_IMAGE --tag $IMAGE_NAME:$IMAGE_TAG -f $APP_DIR/Dockerfile .",
63
63
  "docker push $IMAGE_NAME:$IMAGE_TAG",
64
64
  "docker tag $IMAGE_NAME:$IMAGE_TAG $CACHE_IMAGE",
65
65
  "docker push $CACHE_IMAGE",
@@ -3,8 +3,10 @@ exports.__esModule = true;
3
3
  exports.getBuildDefaults = exports.buildJobCreators = void 0;
4
4
  var node_1 = require("./node");
5
5
  exports.buildJobCreators = {
6
- node: node_1.createNodeJobs
6
+ node: node_1.createNodeJobs,
7
+ "node-static": node_1.createNodeJobs
7
8
  };
8
9
  exports.getBuildDefaults = {
9
- node: node_1.getNodeDefaults
10
+ node: node_1.getNodeDefaults,
11
+ "node-static": node_1.getNodeStaticDefaults
10
12
  };
@@ -1,5 +1,6 @@
1
1
  import { GitlabJobs } from "../types/gitlab-types";
2
2
  import { Context } from "../types/context";
3
- import { BuildConfigNode } from "./types";
3
+ import { BuildConfigNode, BuildConfigNodeStatic } from "./types";
4
4
  export declare const createNodeJobs: (context: Context) => GitlabJobs;
5
5
  export declare const getNodeDefaults: () => Partial<BuildConfigNode>;
6
+ export declare const getNodeStaticDefaults: () => Partial<BuildConfigNodeStatic>;
@@ -32,7 +32,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
32
32
  return to;
33
33
  };
34
34
  exports.__esModule = true;
35
- exports.getNodeDefaults = exports.createNodeJobs = void 0;
35
+ exports.getNodeStaticDefaults = exports.getNodeDefaults = exports.createNodeJobs = void 0;
36
36
  var docker_1 = require("./docker");
37
37
  var types_1 = require("./types");
38
38
  var baseRetry = {
@@ -44,19 +44,26 @@ var getYarnInstall = function (context) { return [
44
44
  "if [ -f ./.nvmrc ]; then source /root/.nvm/nvm.sh && nvm install <<< .nvmrc; fi",
45
45
  "yarn install --frozen-lockfile",
46
46
  ]; };
47
+ var getNodeCache = function (context) { return [
48
+ {
49
+ key: "node-modules",
50
+ policy: "pull-push",
51
+ paths: ["node_modules", "**/node_modules/"]
52
+ },
53
+ ]; };
54
+ var getNextCache = function (context) { return [
55
+ {
56
+ key: "next-cache",
57
+ policy: "pull-push",
58
+ paths: [context.componentConfig.dir + "/.next/cache/"]
59
+ },
60
+ ]; };
47
61
  var createNodeTestJobs = function (context) {
48
- var cache = [
49
- {
50
- key: "node-modules",
51
- policy: "pull-push",
52
- paths: ["node_modules", "**/node_modules/"]
53
- },
54
- ];
55
62
  var base = {
56
63
  variables: {
57
64
  APP_PATH: context.componentConfig.dir
58
65
  },
59
- cache: cache,
66
+ cache: getNodeCache(context),
60
67
  stage: "test",
61
68
  interruptible: true,
62
69
  needs: [],
@@ -83,7 +90,7 @@ var createNodeTestJobs = function (context) {
83
90
  };
84
91
  var createNodeBuildJobs = function (context) {
85
92
  var buildConfig = context.componentConfig.build;
86
- if (!types_1.isOfType(buildConfig, "node")) {
93
+ if (!types_1.isOfType(buildConfig, "node") && !types_1.isOfType(buildConfig, "node-static")) {
87
94
  // should not happen
88
95
  throw new Error("deploy config is not kubernetes");
89
96
  }
@@ -97,6 +104,7 @@ var createNodeBuildJobs = function (context) {
97
104
  name: "app-build",
98
105
  job: {
99
106
  needs: [],
107
+ cache: __spreadArray(__spreadArray([], __read(getNodeCache(context))), __read(getNextCache(context))),
100
108
  variables: context.environment.variables,
101
109
  retry: baseRetry,
102
110
  interruptible: true,
@@ -115,7 +123,7 @@ var createNodeBuildJobs = function (context) {
115
123
  name: "docker-build",
116
124
  job: __assign(__assign({}, docker_1.createDockerBuildJob(context, {
117
125
  script: [
118
- buildConfig.runtime === "static"
126
+ buildConfig.type === "node-static"
119
127
  ? "ensureNginxDockerfile"
120
128
  : "ensureNodeDockerfile",
121
129
  ]
@@ -130,8 +138,13 @@ exports.createNodeJobs = createNodeJobs;
130
138
  var getNodeDefaults = function () {
131
139
  return {
132
140
  startCommand: "yarn start",
133
- runtime: "dynamic",
134
141
  buildCommand: "yarn build"
135
142
  };
136
143
  };
137
144
  exports.getNodeDefaults = getNodeDefaults;
145
+ var getNodeStaticDefaults = function () {
146
+ return {
147
+ buildCommand: "yarn build"
148
+ };
149
+ };
150
+ exports.getNodeStaticDefaults = getNodeStaticDefaults;
@@ -3,10 +3,16 @@ export declare type BuildConfigBase = {
3
3
  };
4
4
  export declare type BuildConfigNode = {
5
5
  type: "node";
6
- runtime?: "dynamic" | "static";
7
6
  buildCommand?: string;
8
7
  } & BuildConfigBase;
9
- export declare type BuildConfig = BuildConfigNode;
10
- export declare const isOfType: <T extends "node">(t: BuildConfig, type: T) => t is Extract<BuildConfigNode, {
8
+ export declare type BuildConfigNodeStatic = {
9
+ type: "node-static";
10
+ buildCommand?: string;
11
+ startCommand: never;
12
+ };
13
+ export declare type BuildConfig = BuildConfigNode | BuildConfigNodeStatic;
14
+ export declare const isOfType: <T extends "node" | "node-static">(t: BuildConfig, type: T) => t is Extract<BuildConfigNode, {
15
+ type: T;
16
+ }> | Extract<BuildConfigNodeStatic, {
11
17
  type: T;
12
18
  }>;
@@ -0,0 +1,3 @@
1
+ import { Config } from "../types/config";
2
+ import { Context } from "../types/context";
3
+ export declare const createContext: (componentName: string, config: Config, env: string) => Context;
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __read = (this && this.__read) || function (o, n) {
14
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
15
+ if (!m) return o;
16
+ var i = m.call(o), r, ar = [], e;
17
+ try {
18
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19
+ }
20
+ catch (error) { e = { error: error }; }
21
+ finally {
22
+ try {
23
+ if (r && !r.done && (m = i["return"])) m.call(i);
24
+ }
25
+ finally { if (e) throw e.error; }
26
+ }
27
+ return ar;
28
+ };
29
+ var __importDefault = (this && this.__importDefault) || function (mod) {
30
+ return (mod && mod.__esModule) ? mod : { "default": mod };
31
+ };
32
+ exports.__esModule = true;
33
+ exports.createContext = void 0;
34
+ var lodash_1 = require("lodash");
35
+ var slugify_1 = __importDefault(require("slugify"));
36
+ var build_1 = require("../build");
37
+ var deploy_1 = require("../deploy");
38
+ var getEnvironment = function (config, componentName, env, commitInfo) {
39
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
40
+ var componentConfig = config.components[componentName];
41
+ if (!componentConfig) {
42
+ throw new Error("unknown component " + componentName);
43
+ }
44
+ var defaultConfig = componentConfig;
45
+ var envConfig = (_b = (_a = componentConfig.env) === null || _a === void 0 ? void 0 : _a[env]) !== null && _b !== void 0 ? _b : {};
46
+ var mergedConfig = lodash_1.merge({}, defaultConfig, envConfig);
47
+ var publicEnvVars = (_d = (_c = mergedConfig.vars) === null || _c === void 0 ? void 0 : _c.public) !== null && _d !== void 0 ? _d : {};
48
+ var secretEnvVarsRaw = (_f = (_e = mergedConfig.vars) === null || _e === void 0 ? void 0 : _e.secret) !== null && _f !== void 0 ? _f : {}; // TODO, map to gl secrets?
49
+ var secretEnvVars = {}; // TODO
50
+ var referencedRaw = (_h = (_g = mergedConfig.vars) === null || _g === void 0 ? void 0 : _g.fromComponents) !== null && _h !== void 0 ? _h : {};
51
+ var referenced = Object.entries(referencedRaw).reduce(function (acc, _a) {
52
+ var _b = __read(_a, 2), otherApp = _b[0], mapping = _b[1];
53
+ // TODO: prevent infinit looop
54
+ var variables = getEnvironment(config, otherApp, env, commitInfo).variables;
55
+ return Object.fromEntries(Object.entries(mapping).map(function (_a) {
56
+ var _b = __read(_a, 2), ourKey = _b[0], otherKey = _b[1];
57
+ return [
58
+ ourKey,
59
+ variables[otherKey],
60
+ ];
61
+ }));
62
+ }, {});
63
+ var envType = (_l = (_k = (_j = componentConfig.env) === null || _j === void 0 ? void 0 : _j[env]) === null || _k === void 0 ? void 0 : _k.type) !== null && _l !== void 0 ? _l : env;
64
+ var environmentName = envType === "review"
65
+ ? env + "/" + componentName + "/" + commitInfo.refName
66
+ : env + "/" + componentName;
67
+ var KUBE_APP_NAME = envType === "review"
68
+ ? componentName + "-" + commitInfo.refSlug
69
+ : componentName;
70
+ var KUBE_NAMESPACE = config.customerName + "-" + config.appName + "-" + env;
71
+ var APP_SLUG = slugify_1["default"](KUBE_APP_NAME);
72
+ var HOST_CANONICAL = config.appName + "-" + APP_SLUG + "." + config.customerName + ".panter.cloud";
73
+ var hostname = (_m = mergedConfig.hostname) !== null && _m !== void 0 ? _m : HOST_CANONICAL;
74
+ var url = "https://" + hostname;
75
+ var predefinedVariables = {
76
+ HOST_CANONICAL: HOST_CANONICAL,
77
+ ROOT_URL: url,
78
+ KUBE_NAMESPACE: KUBE_NAMESPACE,
79
+ KUBE_APP_NAME: KUBE_APP_NAME,
80
+ ENV_SHORT: env,
81
+ APP_DIR: componentConfig.dir
82
+ };
83
+ var variables = __assign(__assign(__assign(__assign({}, predefinedVariables), publicEnvVars), secretEnvVars), referenced);
84
+ return {
85
+ hostname: hostname,
86
+ fullName: environmentName,
87
+ shortName: env,
88
+ url: url,
89
+ variables: variables
90
+ };
91
+ };
92
+ var createContext = function (componentName, config, env) {
93
+ var _a, _b, _c, _d;
94
+ if (!/^[a-z0-9-]+$/.test(componentName)) {
95
+ throw new Error("componentName may only contain lower case letters, numbers and -");
96
+ }
97
+ var rawConfig = config.components[componentName];
98
+ if (!rawConfig) {
99
+ throw new Error("unknown component " + componentName);
100
+ }
101
+ // envs can override the config
102
+ var envConfig = (_b = (_a = rawConfig.env) === null || _a === void 0 ? void 0 : _a[env]) !== null && _b !== void 0 ? _b : {};
103
+ var componentConfigWithoutDefaults = lodash_1.merge({}, rawConfig, envConfig);
104
+ // fill in defaults of build and deploy
105
+ var defaults = {
106
+ build: build_1.getBuildDefaults[componentConfigWithoutDefaults.build.type](),
107
+ deploy: deploy_1.getDeployDefaults[componentConfigWithoutDefaults.deploy.type]()
108
+ };
109
+ var componentConfig = lodash_1.merge({}, defaults, componentConfigWithoutDefaults);
110
+ var commit = {
111
+ refName: (_c = process.env.CI_COMMIT_REF_NAME) !== null && _c !== void 0 ? _c : "unknown",
112
+ refSlug: (_d = process.env.CI_COMMIT_REF_SLUG) !== null && _d !== void 0 ? _d : "unknown"
113
+ };
114
+ return {
115
+ fullConfig: config,
116
+ componentConfig: componentConfig,
117
+ componentName: componentName,
118
+ environment: getEnvironment(config, componentName, env, commit),
119
+ commit: commit
120
+ };
121
+ };
122
+ exports.createContext = createContext;
@@ -1,5 +1,3 @@
1
- import { GitlabJobDef } from "../types/gitlab-types";
2
1
  import { Config } from "../types/config";
3
- import { Context } from "../types/context";
4
- export declare const createContext: (componentName: string, config: Config, env: string) => Context;
2
+ import { GitlabJobDef } from "../types/gitlab-types";
5
3
  export declare const createJobs: (envs: string[], config: Config, componentName: string) => Record<string, GitlabJobDef>;
@@ -31,101 +31,16 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
31
31
  to[j] = from[i];
32
32
  return to;
33
33
  };
34
- var __importDefault = (this && this.__importDefault) || function (mod) {
35
- return (mod && mod.__esModule) ? mod : { "default": mod };
36
- };
37
34
  exports.__esModule = true;
38
- exports.createJobs = exports.createContext = void 0;
39
- var lodash_1 = require("lodash");
40
- var slugify_1 = __importDefault(require("slugify"));
41
- var deploy_1 = require("../deploy");
35
+ exports.createJobs = void 0;
42
36
  var build_1 = require("../build");
37
+ var context_1 = require("../context");
38
+ var deploy_1 = require("../deploy");
43
39
  var createRawJobs = function (context) {
44
40
  var buildJobs = build_1.buildJobCreators[context.componentConfig.build.type](context);
45
41
  var deployJobs = deploy_1.deployJobCreators[context.componentConfig.deploy.type](context);
46
42
  return __spreadArray(__spreadArray([], __read(buildJobs)), __read(deployJobs));
47
43
  };
48
- var getEnvironment = function (config, componentName, env, commitInfo) {
49
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
50
- var componentConfig = config.components[componentName];
51
- if (!componentConfig) {
52
- throw new Error("unknown component " + componentName);
53
- }
54
- var defaultConfig = componentConfig;
55
- var envConfig = (_b = (_a = componentConfig.env) === null || _a === void 0 ? void 0 : _a[env]) !== null && _b !== void 0 ? _b : {};
56
- var mergedConfig = lodash_1.merge({}, defaultConfig, envConfig);
57
- var publicEnvVars = (_d = (_c = mergedConfig.vars) === null || _c === void 0 ? void 0 : _c.public) !== null && _d !== void 0 ? _d : {};
58
- var secretEnvVarsRaw = (_f = (_e = mergedConfig.vars) === null || _e === void 0 ? void 0 : _e.secret) !== null && _f !== void 0 ? _f : {}; // TODO, map to gl secrets?
59
- var secretEnvVars = {}; // TODO
60
- var referencedRaw = (_h = (_g = mergedConfig.vars) === null || _g === void 0 ? void 0 : _g.fromComponents) !== null && _h !== void 0 ? _h : {};
61
- var referenced = Object.entries(referencedRaw).reduce(function (acc, _a) {
62
- var _b = __read(_a, 2), otherApp = _b[0], mapping = _b[1];
63
- // TODO: prevent infinit looop
64
- var variables = getEnvironment(config, otherApp, env, commitInfo).variables;
65
- return Object.fromEntries(Object.entries(mapping).map(function (_a) {
66
- var _b = __read(_a, 2), ourKey = _b[0], otherKey = _b[1];
67
- return [
68
- ourKey,
69
- variables[otherKey],
70
- ];
71
- }));
72
- }, {});
73
- var envType = (_l = (_k = (_j = componentConfig.env) === null || _j === void 0 ? void 0 : _j[env]) === null || _k === void 0 ? void 0 : _k.type) !== null && _l !== void 0 ? _l : env;
74
- var environmentName = envType === "review"
75
- ? env + "-" + componentName + "/" + commitInfo.refName
76
- : env + "-" + componentName;
77
- var KUBE_APP_NAME = envType === "review"
78
- ? componentName + "-" + commitInfo.refSlug
79
- : componentName;
80
- var KUBE_NAMESPACE = config.customerName + "-" + config.appName + "-" + env;
81
- var APP_SLUG = slugify_1["default"](KUBE_APP_NAME);
82
- var HOST_CANONICAL = config.appName + "-" + APP_SLUG + "." + config.customerName + ".panter.cloud";
83
- var hostname = (_m = mergedConfig.hostname) !== null && _m !== void 0 ? _m : HOST_CANONICAL;
84
- var url = "https://" + hostname;
85
- var predefinedVariables = {
86
- HOST_CANONICAL: HOST_CANONICAL,
87
- ROOT_URL: url,
88
- KUBE_NAMESPACE: KUBE_NAMESPACE,
89
- KUBE_APP_NAME: KUBE_APP_NAME,
90
- ENV_SHORT: env
91
- };
92
- var variables = __assign(__assign(__assign(__assign({}, predefinedVariables), publicEnvVars), secretEnvVars), referenced);
93
- return {
94
- hostname: hostname,
95
- fullName: environmentName,
96
- shortName: env,
97
- url: url,
98
- variables: variables
99
- };
100
- };
101
- var createContext = function (componentName, config, env) {
102
- var _a, _b, _c, _d;
103
- var rawConfig = config.components[componentName];
104
- if (!rawConfig) {
105
- throw new Error("unknown component " + componentName);
106
- }
107
- // envs can override the config
108
- var envConfig = (_b = (_a = rawConfig.env) === null || _a === void 0 ? void 0 : _a[env]) !== null && _b !== void 0 ? _b : {};
109
- var componentConfigWithoutDefaults = lodash_1.merge({}, rawConfig, envConfig);
110
- // fill in defaults of build and deploy
111
- var defaults = {
112
- build: build_1.getBuildDefaults[componentConfigWithoutDefaults.build.type](),
113
- deploy: deploy_1.getDeployDefaults[componentConfigWithoutDefaults.deploy.type]()
114
- };
115
- var componentConfig = lodash_1.merge({}, componentConfigWithoutDefaults, defaults);
116
- var commit = {
117
- refName: (_c = process.env.CI_COMMIT_REF_NAME) !== null && _c !== void 0 ? _c : "unknown",
118
- refSlug: (_d = process.env.CI_COMMIT_REF_SLUG) !== null && _d !== void 0 ? _d : "unknown"
119
- };
120
- return {
121
- fullConfig: config,
122
- componentConfig: componentConfig,
123
- componentName: componentName,
124
- environment: getEnvironment(config, componentName, env, commit),
125
- commit: commit
126
- };
127
- };
128
- exports.createContext = createContext;
129
44
  var getFullJobName = function (name, componentName, env) {
130
45
  if (env) {
131
46
  return env + " " + componentName + " " + name;
@@ -140,7 +55,7 @@ var replaceReferences = function (def, componentName, env) {
140
55
  };
141
56
  var createJobs = function (envs, config, componentName) {
142
57
  return envs.reduce(function (acc, env) {
143
- var context = exports.createContext(componentName, config, env);
58
+ var context = context_1.createContext(componentName, config, env);
144
59
  var jobs = createRawJobs(context);
145
60
  return __assign(__assign({}, acc), jobs.reduce(function (acc, _a) {
146
61
  var _b;
@@ -54,7 +54,7 @@ describe("createPipeline", function () {
54
54
  appName: "test",
55
55
  customerName: "pan",
56
56
  components: {
57
- myApp: {
57
+ "my-app": {
58
58
  dir: "myapp",
59
59
  build: {
60
60
  type: "node"
@@ -74,12 +74,12 @@ describe("createPipeline", function () {
74
74
  _a = _b.sent(), image = _a.image, stages = _a.stages, workflow = _a.workflow, jobs = __rest(_a, ["image", "stages", "workflow"]);
75
75
  expect(image).toEqual("git.panter.ch:5001/catladder/gitlab-ci/pipeline:$PIPELINE_IMAGE_TAG");
76
76
  expect(Object.keys(jobs)).toEqual([
77
- "myApp audit",
78
- "myApp lint",
79
- "myApp test",
80
- "dev myApp app-build",
81
- "dev myApp docker-build",
82
- "dev myApp deploy-to-kubernetes",
77
+ "my-app audit",
78
+ "my-app lint",
79
+ "my-app test",
80
+ "dev my-app app-build",
81
+ "dev my-app docker-build",
82
+ "dev my-app deploy-to-kubernetes",
83
83
  ]);
84
84
  return [2 /*return*/];
85
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@catladder/pipeline",
3
- "version": "0.0.6",
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 $DOCKER_DIR",
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 createNodeTestJobs = (context: Context): GitlabJobs => {
22
- const cache: GitlabJobCache[] = [
23
- {
24
- key: "node-modules",
25
- policy: "pull-push",
26
- paths: ["node_modules", "**/node_modules/"],
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.runtime === "static"
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
- runtime: "dynamic",
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 BuildConfig = BuildConfigNode;
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 { GitlabJobDef, GitlabJobs } from "../types/gitlab-types";
4
-
5
- import { Config, DefaultEnvConfig } from "../types/config";
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 { deployJobCreators, getDeployDefaults } from "../deploy";
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
- myApp: {
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
- "myApp audit",
33
- "myApp lint",
34
- "myApp test",
35
- "dev myApp app-build",
36
- "dev myApp docker-build",
37
- "dev myApp deploy-to-kubernetes",
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
  });