@catladder/pipeline 1.55.0 → 1.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/catladder-gitlab-dev.js +3 -0
- package/dist/build/index.d.ts +2 -1
- package/dist/build/node/cache.js +8 -1
- package/dist/build/node/yarn.js +1 -1
- package/dist/build/types.d.ts +3 -0
- package/dist/bundles/catladder-gitlab/index.js +3 -3
- package/dist/constants.js +1 -1
- package/dist/context/getEnvConfig.d.ts +2 -0
- package/dist/context/getEnvConfig.js +26 -0
- package/dist/context/getEnvType.d.ts +4 -0
- package/dist/context/getEnvType.js +18 -0
- package/dist/context/getEnvironment.d.ts +2 -4
- package/dist/context/getEnvironment.js +15 -195
- package/dist/context/getEnvironmentContext.d.ts +4 -0
- package/dist/context/getEnvironmentContext.js +36 -0
- package/dist/context/getEnvironmentVariables.d.ts +10 -0
- package/dist/context/getEnvironmentVariables.js +322 -0
- package/dist/context/index.d.ts +1 -0
- package/dist/context/index.js +12 -16
- package/dist/deploy/cloudRun/deployJob.js +19 -5
- package/dist/deploy/cloudRun/index.js +7 -7
- package/dist/deploy/index.d.ts +7 -20
- package/dist/deploy/index.js +4 -4
- package/dist/deploy/kubernetes/additionalSecretKeys.d.ts +3 -3
- package/dist/deploy/kubernetes/additionalSecretKeys.js +5 -5
- package/dist/deploy/kubernetes/index.js +2 -2
- package/dist/deploy/types/googleCloudRun.d.ts +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/config.d.ts +1 -0
- package/dist/types/context.d.ts +6 -0
- package/dist/types/environmentContext.d.ts +22 -0
- package/dist/types/environmentContext.js +3 -0
- package/dist/utils/gitlab.d.ts +1 -0
- package/dist/utils/gitlab.js +46 -0
- package/examples/test.catladder.ts +26 -0
- package/package.json +1 -1
- package/src/build/index.ts +4 -1
- package/src/build/node/cache.ts +13 -5
- package/src/build/node/yarn.ts +1 -1
- package/src/build/types.ts +6 -0
- package/src/context/getEnvConfig.ts +21 -0
- package/src/context/getEnvType.ts +17 -0
- package/src/context/getEnvironment.ts +16 -164
- package/src/context/getEnvironmentContext.ts +57 -0
- package/src/context/getEnvironmentVariables.ts +152 -0
- package/src/context/index.ts +17 -14
- package/src/deploy/cloudRun/deployJob.ts +9 -5
- package/src/deploy/cloudRun/index.ts +5 -4
- package/src/deploy/index.ts +9 -21
- package/src/deploy/kubernetes/additionalSecretKeys.ts +7 -7
- package/src/deploy/kubernetes/index.ts +2 -2
- package/src/deploy/types/googleCloudRun.ts +1 -1
- package/src/types/config.ts +2 -0
- package/src/types/context.ts +8 -0
- package/src/types/environmentContext.ts +26 -0
- package/src/utils/gitlab.ts +5 -0
|
@@ -1,187 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import type { CommitInfo, Context, Environment } from "../types/context";
|
|
7
|
-
import { mergeWithMergingArrays } from "../utils";
|
|
8
|
-
import {
|
|
9
|
-
resolveReferences,
|
|
10
|
-
translateLegacyFromComponents,
|
|
11
|
-
} from "./resolveReferences";
|
|
1
|
+
import type { Config } from "../types/config";
|
|
2
|
+
|
|
3
|
+
import type { CommitInfo, Environment } from "../types/context";
|
|
4
|
+
import { getEnvironmentContext } from "./getEnvironmentContext";
|
|
5
|
+
import { getEnvironmentVariables } from "./getEnvironmentVariables";
|
|
12
6
|
|
|
13
7
|
export const getEnvironment = async (
|
|
14
8
|
config: Config,
|
|
15
9
|
componentName: string,
|
|
16
10
|
env: string,
|
|
17
|
-
commitInfo?: CommitInfo
|
|
18
|
-
alreadyVisited: Record<string, Record<string, boolean>> = {} // to prevent endless loop
|
|
11
|
+
commitInfo?: CommitInfo
|
|
19
12
|
): Promise<Environment> => {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
const envType = envConfig?.type ?? (isKnowEnvType(env) ? env : null);
|
|
23
|
-
|
|
24
|
-
if (!envType) {
|
|
25
|
-
throw new Error(
|
|
26
|
-
"Missing type in environment " + env + " in component " + componentName
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const basePredefinedVariables = {
|
|
31
|
-
ENV_SHORT: env,
|
|
32
|
-
APP_DIR: envConfig.dir,
|
|
33
|
-
ENV_TYPE: envType,
|
|
34
|
-
};
|
|
13
|
+
const { envVars, secretEnvVarKeys, host, url } =
|
|
14
|
+
await getEnvironmentVariables(config, componentName, env, commitInfo);
|
|
35
15
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
? `${env}/${commitInfo.refName}/${componentName}`
|
|
39
|
-
: `${env}/${componentName}`;
|
|
40
|
-
|
|
41
|
-
const environmentSlug =
|
|
42
|
-
envType === "review" && commitInfo
|
|
43
|
-
? `${env}-${commitInfo.reviewSlug}-${componentName}`
|
|
44
|
-
: `${env}-${componentName}`;
|
|
45
|
-
|
|
46
|
-
let predefinedVariables: Record<string, string>;
|
|
47
|
-
let host: string;
|
|
48
|
-
let url: string;
|
|
49
|
-
const fullName = `${config.customerName}-${config.appName}-${environmentSlug}`;
|
|
50
|
-
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
|
-
const envVarContext: EnvVarContext<any> = {
|
|
53
|
-
deployConfig: envConfig.deploy,
|
|
54
|
-
fullName,
|
|
55
|
-
envType,
|
|
56
|
-
commitInfo,
|
|
57
|
-
componentName,
|
|
16
|
+
const envContext = getEnvironmentContext(
|
|
17
|
+
config,
|
|
58
18
|
env,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (envType === "local") {
|
|
63
|
-
const devLocalConfig: DevLocalEnvConfig = envConfig;
|
|
64
|
-
const port = devLocalConfig.port ?? 3000;
|
|
65
|
-
host = "localhost:" + port;
|
|
66
|
-
url = "http://" + host;
|
|
67
|
-
predefinedVariables = {
|
|
68
|
-
ENV_SHORT: "local",
|
|
69
|
-
ROOT_URL: url,
|
|
70
|
-
PORT: port.toString(),
|
|
71
|
-
};
|
|
72
|
-
} else {
|
|
73
|
-
const additionalEnvVars = envConfig.deploy
|
|
74
|
-
? DEPLOY_TYPES[envConfig.deploy.type].getAdditionalEnvVars(envVarContext)
|
|
75
|
-
: {};
|
|
76
|
-
|
|
77
|
-
host =
|
|
78
|
-
envConfig?.host ??
|
|
79
|
-
additionalEnvVars.HOST_CANONICAL ??
|
|
80
|
-
"unknown-host.example.com";
|
|
81
|
-
url = `https://${host}`;
|
|
82
|
-
|
|
83
|
-
predefinedVariables = {
|
|
84
|
-
...basePredefinedVariables,
|
|
85
|
-
HOST: host,
|
|
86
|
-
ROOT_URL: url,
|
|
87
|
-
...additionalEnvVars,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
const publicEnvVarsRaw = envConfig.vars?.public ?? {};
|
|
91
|
-
|
|
92
|
-
const additionalSecretKeys = envConfig.deploy
|
|
93
|
-
? DEPLOY_TYPES[envConfig.deploy.type].additionalSecretKeys(envVarContext)
|
|
94
|
-
: [];
|
|
95
|
-
|
|
96
|
-
const secretEnvVarKeys = [
|
|
97
|
-
...(envConfig.vars?.secret ?? []),
|
|
98
|
-
...additionalSecretKeys,
|
|
99
|
-
];
|
|
100
|
-
const secretEnvVars = Object.fromEntries(
|
|
101
|
-
secretEnvVarKeys.map((key) => [
|
|
102
|
-
key,
|
|
103
|
-
`$${getSecretVarName(env, componentName, key)}`,
|
|
104
|
-
])
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
// this is deprecated, we now support: $componentname:FOO
|
|
108
|
-
const legacyFromComponents = envConfig.vars?.fromComponents ?? {};
|
|
109
|
-
const publicEnvVarsRawWithLegasyFromComponents = merge(
|
|
110
|
-
{},
|
|
111
|
-
translateLegacyFromComponents(legacyFromComponents),
|
|
112
|
-
publicEnvVarsRaw
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
const publicEnvVarsRawSanitized = Object.fromEntries(
|
|
116
|
-
Object.entries(publicEnvVarsRawWithLegasyFromComponents).map(
|
|
117
|
-
([key, value]) => [
|
|
118
|
-
key,
|
|
119
|
-
isObject(value) ? JSON.stringify(value) : `${value}`,
|
|
120
|
-
]
|
|
121
|
-
)
|
|
19
|
+
componentName,
|
|
20
|
+
commitInfo
|
|
122
21
|
);
|
|
123
22
|
|
|
124
|
-
const
|
|
125
|
-
...predefinedVariables,
|
|
126
|
-
...secretEnvVars,
|
|
127
|
-
...publicEnvVarsRawSanitized,
|
|
128
|
-
});
|
|
23
|
+
const envType = envContext.envType;
|
|
129
24
|
|
|
130
|
-
const envVars = await resolveReferences(
|
|
131
|
-
envVarsRaw,
|
|
132
|
-
async (componentName, variableName, alreadyVisited) => {
|
|
133
|
-
const { envVars } = await getEnvironment(
|
|
134
|
-
config,
|
|
135
|
-
componentName,
|
|
136
|
-
env,
|
|
137
|
-
commitInfo,
|
|
138
|
-
alreadyVisited
|
|
139
|
-
);
|
|
140
|
-
return envVars[variableName];
|
|
141
|
-
},
|
|
142
|
-
alreadyVisited
|
|
143
|
-
);
|
|
144
25
|
return {
|
|
145
26
|
envType,
|
|
146
27
|
host,
|
|
147
28
|
url,
|
|
148
29
|
gitlabEnvironment: {
|
|
149
|
-
name: gitlabEnvironmentName,
|
|
30
|
+
name: envContext.gitlabEnvironmentName,
|
|
150
31
|
url,
|
|
151
32
|
},
|
|
152
|
-
fullName,
|
|
153
|
-
slug: environmentSlug,
|
|
33
|
+
fullName: envContext.fullName,
|
|
34
|
+
slug: envContext.environmentSlug,
|
|
154
35
|
shortName: env,
|
|
155
36
|
envVars,
|
|
156
37
|
secretEnvVarKeys,
|
|
157
38
|
};
|
|
158
39
|
};
|
|
159
|
-
|
|
160
|
-
const sanitizeForEnVar = (s: string) => s.replace(/-/g, "_");
|
|
161
|
-
export const getSecretVarName = (
|
|
162
|
-
env: string,
|
|
163
|
-
componentName: string,
|
|
164
|
-
key: string
|
|
165
|
-
) => `CL_${sanitizeForEnVar(env)}_${sanitizeForEnVar(componentName)}_${key}`; // remove dash from component name
|
|
166
|
-
|
|
167
|
-
const addIndexVar = (vars: Record<string, unknown>) => ({
|
|
168
|
-
...vars,
|
|
169
|
-
_ALL_ENV_VAR_KEYS: JSON.stringify(Object.keys(vars)),
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
export const getSecretVarNameForContext = (context: Context, key: string) =>
|
|
173
|
-
getSecretVarName(context.environment.shortName, context.componentName, key);
|
|
174
|
-
|
|
175
|
-
const getEnvConfig = (config: Config, componentName: string, env: string) => {
|
|
176
|
-
const defaultConfig = config.components[componentName];
|
|
177
|
-
if (!defaultConfig) {
|
|
178
|
-
throw new Error("unknown component " + componentName);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const envCustomizations = defaultConfig.env?.[env] ?? {};
|
|
182
|
-
if (envCustomizations === false) {
|
|
183
|
-
throw new Error("env is disabled: " + env);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return mergeWithMergingArrays(defaultConfig, envCustomizations);
|
|
187
|
-
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Config, EnvConfigWithComponent } from "../types/config";
|
|
2
|
+
|
|
3
|
+
import type { CommitInfo } from "../types/context";
|
|
4
|
+
import type { EnvironmentContext } from "../types/environmentContext";
|
|
5
|
+
import { getEnvConfig } from "./getEnvConfig";
|
|
6
|
+
import { getEnvType } from "./getEnvType";
|
|
7
|
+
|
|
8
|
+
const getEnvironmentSlug = (
|
|
9
|
+
envConfig: EnvConfigWithComponent,
|
|
10
|
+
env: string,
|
|
11
|
+
componentName: string,
|
|
12
|
+
commitInfo?: CommitInfo
|
|
13
|
+
) => {
|
|
14
|
+
const envType = getEnvType(env, envConfig);
|
|
15
|
+
|
|
16
|
+
return envType === "review" && commitInfo
|
|
17
|
+
? `${env}-${commitInfo.reviewSlug}-${componentName}`
|
|
18
|
+
: `${env}-${componentName}`;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const getEnvironmentContext = (
|
|
22
|
+
config: Config,
|
|
23
|
+
env: string,
|
|
24
|
+
componentName: string,
|
|
25
|
+
commitInfo?: CommitInfo
|
|
26
|
+
): EnvironmentContext<any, any> => {
|
|
27
|
+
const envConfigRaw = getEnvConfig(config, componentName, env);
|
|
28
|
+
const envType = getEnvType(env, envConfigRaw);
|
|
29
|
+
|
|
30
|
+
const environmentSlug = getEnvironmentSlug(
|
|
31
|
+
envConfigRaw,
|
|
32
|
+
env,
|
|
33
|
+
componentName,
|
|
34
|
+
commitInfo
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const gitlabEnvironmentName =
|
|
38
|
+
envType === "review" && commitInfo
|
|
39
|
+
? `${env}/${commitInfo.refName}/${componentName}`
|
|
40
|
+
: `${env}/${componentName}`;
|
|
41
|
+
|
|
42
|
+
const fullName = `${config.customerName}-${config.appName}-${environmentSlug}`;
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
envConfigRaw,
|
|
46
|
+
deployConfigRaw: envConfigRaw.deploy,
|
|
47
|
+
buildConfigRaw: envConfigRaw.build,
|
|
48
|
+
environmentSlug,
|
|
49
|
+
gitlabEnvironmentName,
|
|
50
|
+
fullName,
|
|
51
|
+
envType,
|
|
52
|
+
commitInfo,
|
|
53
|
+
componentName,
|
|
54
|
+
env,
|
|
55
|
+
fullConfig: config,
|
|
56
|
+
};
|
|
57
|
+
};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { isObject, merge } from "lodash";
|
|
2
|
+
import { DEPLOY_TYPES } from "../deploy";
|
|
3
|
+
import type { CommitInfo, Context } from "../types";
|
|
4
|
+
import type { Config, DevLocalEnvConfig } from "../types/config";
|
|
5
|
+
|
|
6
|
+
import { getEnvironmentContext } from "./getEnvironmentContext";
|
|
7
|
+
import {
|
|
8
|
+
resolveReferences,
|
|
9
|
+
translateLegacyFromComponents,
|
|
10
|
+
} from "./resolveReferences";
|
|
11
|
+
|
|
12
|
+
export const getEnvironmentVariables = async (
|
|
13
|
+
config: Config,
|
|
14
|
+
componentName: string,
|
|
15
|
+
env: string,
|
|
16
|
+
commitInfo?: CommitInfo,
|
|
17
|
+
alreadyVisited: Record<string, Record<string, boolean>> = {} // to prevent endless loop
|
|
18
|
+
): Promise<{
|
|
19
|
+
envVars: Record<string, string>;
|
|
20
|
+
secretEnvVarKeys: string[];
|
|
21
|
+
host: string;
|
|
22
|
+
url: string;
|
|
23
|
+
}> => {
|
|
24
|
+
const environmentContext = getEnvironmentContext(
|
|
25
|
+
config,
|
|
26
|
+
env,
|
|
27
|
+
componentName,
|
|
28
|
+
commitInfo
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const { envConfigRaw, deployConfigRaw, envType } = environmentContext;
|
|
32
|
+
|
|
33
|
+
const basePredefinedVariables = {
|
|
34
|
+
ENV_SHORT: env,
|
|
35
|
+
APP_DIR: envConfigRaw.dir,
|
|
36
|
+
ENV_TYPE: envType,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
let predefinedVariables: Record<string, string>;
|
|
40
|
+
let host: string;
|
|
41
|
+
let url: string;
|
|
42
|
+
|
|
43
|
+
if (envType === "local") {
|
|
44
|
+
const devLocalConfig: DevLocalEnvConfig = envConfigRaw;
|
|
45
|
+
const port = devLocalConfig.port ?? 3000;
|
|
46
|
+
host = "localhost:" + port;
|
|
47
|
+
url = "http://" + host;
|
|
48
|
+
predefinedVariables = {
|
|
49
|
+
ENV_SHORT: "local",
|
|
50
|
+
ROOT_URL: url,
|
|
51
|
+
PORT: port.toString(),
|
|
52
|
+
};
|
|
53
|
+
} else {
|
|
54
|
+
const additionalEnvVars = deployConfigRaw
|
|
55
|
+
? DEPLOY_TYPES[deployConfigRaw.type].getAdditionalEnvVars(
|
|
56
|
+
environmentContext
|
|
57
|
+
)
|
|
58
|
+
: {};
|
|
59
|
+
|
|
60
|
+
host =
|
|
61
|
+
envConfigRaw?.host ??
|
|
62
|
+
additionalEnvVars.HOST_CANONICAL ??
|
|
63
|
+
"unknown-host.example.com";
|
|
64
|
+
url = `https://${host}`;
|
|
65
|
+
|
|
66
|
+
predefinedVariables = {
|
|
67
|
+
...basePredefinedVariables,
|
|
68
|
+
HOST: host,
|
|
69
|
+
ROOT_URL: url,
|
|
70
|
+
...additionalEnvVars,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const publicEnvVarsRaw = envConfigRaw.vars?.public ?? {};
|
|
74
|
+
|
|
75
|
+
const additionalSecretKeys = deployConfigRaw
|
|
76
|
+
? DEPLOY_TYPES[deployConfigRaw.type].additionalSecretKeys(
|
|
77
|
+
environmentContext
|
|
78
|
+
)
|
|
79
|
+
: [];
|
|
80
|
+
|
|
81
|
+
const secretEnvVarKeys = [
|
|
82
|
+
...(envConfigRaw.vars?.secret ?? []),
|
|
83
|
+
...additionalSecretKeys,
|
|
84
|
+
];
|
|
85
|
+
const secretEnvVars = Object.fromEntries(
|
|
86
|
+
secretEnvVarKeys.map((key) => [
|
|
87
|
+
key,
|
|
88
|
+
`$${getSecretVarName(env, componentName, key)}`,
|
|
89
|
+
])
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
// this is deprecated, we now support: $componentname:FOO
|
|
93
|
+
const legacyFromComponents = envConfigRaw.vars?.fromComponents ?? {};
|
|
94
|
+
const publicEnvVarsRawWithLegasyFromComponents = merge(
|
|
95
|
+
{},
|
|
96
|
+
translateLegacyFromComponents(legacyFromComponents),
|
|
97
|
+
publicEnvVarsRaw
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const publicEnvVarsRawSanitized = Object.fromEntries(
|
|
101
|
+
Object.entries(publicEnvVarsRawWithLegasyFromComponents).map(
|
|
102
|
+
([key, value]) => [
|
|
103
|
+
key,
|
|
104
|
+
isObject(value) ? JSON.stringify(value) : `${value}`,
|
|
105
|
+
]
|
|
106
|
+
)
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
const envVarsRaw = addIndexVar({
|
|
110
|
+
...predefinedVariables,
|
|
111
|
+
...secretEnvVars,
|
|
112
|
+
...publicEnvVarsRawSanitized,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const envVars = await resolveReferences(
|
|
116
|
+
envVarsRaw,
|
|
117
|
+
async (otherComponentName, variableName, alreadyVisited) => {
|
|
118
|
+
const { envVars: otherEnvVars } = await getEnvironmentVariables(
|
|
119
|
+
config,
|
|
120
|
+
otherComponentName,
|
|
121
|
+
env,
|
|
122
|
+
commitInfo,
|
|
123
|
+
alreadyVisited
|
|
124
|
+
);
|
|
125
|
+
return otherEnvVars[variableName];
|
|
126
|
+
},
|
|
127
|
+
alreadyVisited
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
envVars,
|
|
132
|
+
secretEnvVarKeys,
|
|
133
|
+
host,
|
|
134
|
+
url,
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const sanitizeForEnVar = (s: string) => s.replace(/-/g, "_");
|
|
139
|
+
|
|
140
|
+
export const getSecretVarName = (
|
|
141
|
+
env: string,
|
|
142
|
+
componentName: string,
|
|
143
|
+
key: string
|
|
144
|
+
) => `CL_${sanitizeForEnVar(env)}_${sanitizeForEnVar(componentName)}_${key}`; // remove dash from component name
|
|
145
|
+
|
|
146
|
+
const addIndexVar = (vars: Record<string, unknown>) => ({
|
|
147
|
+
...vars,
|
|
148
|
+
_ALL_ENV_VAR_KEYS: JSON.stringify(Object.keys(vars)),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
export const getSecretVarNameForContext = (context: Context, key: string) =>
|
|
152
|
+
getSecretVarName(context.environment.shortName, context.componentName, key);
|
package/src/context/index.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { BUILD_TYPES } from "../build";
|
|
2
|
-
import type { BuildConfig } from "../build/types";
|
|
2
|
+
import type { BuildConfig, BuildConfigType } from "../build/types";
|
|
3
3
|
import { DEPLOY_TYPES } from "../deploy";
|
|
4
|
-
import type { DeployConfig } from "../deploy/types";
|
|
4
|
+
import type { DeployConfig, DeployConfigType } from "../deploy/types";
|
|
5
5
|
import type { Config } from "../types/config";
|
|
6
6
|
import type { CommitInfo, Context, PackageManagerInfo } from "../types/context";
|
|
7
7
|
import { mergeWithMergingArrays } from "../utils";
|
|
8
8
|
import { getEnvironment } from "./getEnvironment";
|
|
9
|
+
import { getEnvironmentContext } from "./getEnvironmentContext";
|
|
9
10
|
|
|
10
11
|
export * from "./getEnvironment";
|
|
12
|
+
export * from "./getEnvironmentVariables";
|
|
11
13
|
|
|
12
14
|
export const createContext = async (
|
|
13
15
|
config: Config,
|
|
@@ -21,27 +23,28 @@ export const createContext = async (
|
|
|
21
23
|
"componentName may only contain lower case letters, numbers and -"
|
|
22
24
|
);
|
|
23
25
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const componentConfigWithoutDefaults = mergeWithMergingArrays(
|
|
31
|
-
rawConfig,
|
|
32
|
-
envConfig
|
|
26
|
+
|
|
27
|
+
const envContext = getEnvironmentContext(
|
|
28
|
+
config,
|
|
29
|
+
env,
|
|
30
|
+
componentName,
|
|
31
|
+
commitInfo
|
|
33
32
|
);
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
const componentConfigWithoutDefaults = envContext.envConfigRaw;
|
|
36
35
|
const defaults: {
|
|
37
36
|
build: Partial<BuildConfig>;
|
|
38
37
|
deploy: Partial<DeployConfig>;
|
|
39
38
|
} = componentConfigWithoutDefaults.deploy
|
|
40
39
|
? {
|
|
41
40
|
build:
|
|
42
|
-
BUILD_TYPES[
|
|
41
|
+
BUILD_TYPES[
|
|
42
|
+
componentConfigWithoutDefaults.build.type as BuildConfigType
|
|
43
|
+
].defaults(envContext),
|
|
43
44
|
deploy:
|
|
44
|
-
DEPLOY_TYPES[
|
|
45
|
+
DEPLOY_TYPES[
|
|
46
|
+
componentConfigWithoutDefaults.deploy.type as DeployConfigType
|
|
47
|
+
].defaults(envContext),
|
|
45
48
|
}
|
|
46
49
|
: {
|
|
47
50
|
build: {},
|
|
@@ -14,6 +14,8 @@ import type {
|
|
|
14
14
|
import { isOfDeployType } from "../types";
|
|
15
15
|
import { gcloudServiceAccountLoginCommands } from "./utils/gcloudServiceAccountLoginCommands";
|
|
16
16
|
|
|
17
|
+
import { allowFailureInScripts } from "../../utils/gitlab";
|
|
18
|
+
|
|
17
19
|
export const createGoogleCloudRunDeployJobs = (
|
|
18
20
|
context: Context
|
|
19
21
|
): CatladderJob[] => {
|
|
@@ -69,7 +71,7 @@ export const createGoogleCloudRunDeployJobs = (
|
|
|
69
71
|
return `gcloud run deploy ${serviceName} ${commandArg} ${commonDeployArgs} --env-vars-file=____envvars.yaml --allow-unauthenticated`;
|
|
70
72
|
};
|
|
71
73
|
|
|
72
|
-
const
|
|
74
|
+
const getJobCreateScripts = (
|
|
73
75
|
jobName: string,
|
|
74
76
|
job: DeployConfigCloudRunJob
|
|
75
77
|
) => {
|
|
@@ -81,9 +83,7 @@ export const createGoogleCloudRunDeployJobs = (
|
|
|
81
83
|
.split(" ")
|
|
82
84
|
.join(",")}" ${commonDeployArgs}`;
|
|
83
85
|
return [
|
|
84
|
-
|
|
85
|
-
`gcloud beta run jobs create ${args}`,
|
|
86
|
-
"set -e", // reenable
|
|
86
|
+
...allowFailureInScripts([`gcloud beta run jobs create ${args}`]),
|
|
87
87
|
`gcloud beta run jobs update ${args} --env-vars-file=____envvars.yaml`,
|
|
88
88
|
];
|
|
89
89
|
};
|
|
@@ -100,10 +100,14 @@ export const createGoogleCloudRunDeployJobs = (
|
|
|
100
100
|
);
|
|
101
101
|
const cloudRunDeployScripts = [
|
|
102
102
|
`echo "$ENV_VARS" > ____envvars.yaml`, // TODO: split secrets out
|
|
103
|
+
`cat ____envvars.yaml`,
|
|
103
104
|
|
|
104
105
|
...jobsWithNames
|
|
105
|
-
.map(([name, job]) =>
|
|
106
|
+
.map(([name, job]) => getJobCreateScripts(name, job))
|
|
106
107
|
.flat(),
|
|
108
|
+
...jobsWithNames
|
|
109
|
+
.filter(([name, job]) => job.when === "preDeploy")
|
|
110
|
+
.map(([name, job]) => getJobRunScript(name)),
|
|
107
111
|
|
|
108
112
|
...(deployConfig.service !== false
|
|
109
113
|
? [getServiceDeployScript(deployConfig.service)]
|
|
@@ -11,7 +11,8 @@ export const GCLOUD_RUN_DEPLOY_TYPE: DeployTypeDefinition<"google-cloudrun"> = {
|
|
|
11
11
|
jobs: createGoogleCloudRunDeployJobs,
|
|
12
12
|
defaults: () => ({}),
|
|
13
13
|
additionalSecretKeys: () => [GCLOUD_DEPLOY_CREDENTIALS_KEY],
|
|
14
|
-
getAdditionalEnvVars: (
|
|
14
|
+
getAdditionalEnvVars: (ctx) => {
|
|
15
|
+
const { fullName, env, componentName, deployConfigRaw } = ctx;
|
|
15
16
|
const HOST_CANONICAL =
|
|
16
17
|
fullName.toLowerCase() +
|
|
17
18
|
"-" +
|
|
@@ -20,11 +21,11 @@ export const GCLOUD_RUN_DEPLOY_TYPE: DeployTypeDefinition<"google-cloudrun"> = {
|
|
|
20
21
|
];
|
|
21
22
|
|
|
22
23
|
const jobTriggers =
|
|
23
|
-
|
|
24
|
+
deployConfigRaw && deployConfigRaw.jobs
|
|
24
25
|
? Object.fromEntries(
|
|
25
|
-
Object.entries(
|
|
26
|
+
Object.entries(deployConfigRaw.jobs).map(([name, job]) => [
|
|
26
27
|
"CLOUD_RUN_JOB_TRIGGER_URL_" + name,
|
|
27
|
-
`https://${
|
|
28
|
+
`https://${deployConfigRaw.region}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${deployConfigRaw.projectId}/jobs/${name}:run`,
|
|
28
29
|
])
|
|
29
30
|
)
|
|
30
31
|
: {};
|
package/src/deploy/index.ts
CHANGED
|
@@ -1,39 +1,27 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { Context } from "../types/context";
|
|
2
|
+
import type { EnvironmentContext } from "../types/environmentContext";
|
|
3
3
|
import type { CatladderJob } from "../types/jobs";
|
|
4
4
|
import { GCLOUD_RUN_DEPLOY_TYPE } from "./cloudRun";
|
|
5
5
|
import { CUSTOM_DEPLOY_TYPE } from "./custom";
|
|
6
6
|
import { DOCKER_TAG_DEPLOY_TYPE } from "./dockerTag";
|
|
7
7
|
import { KUBERNETES_DEPLOY_TYPE } from "./kubernetes";
|
|
8
8
|
import type { DeployConfigGeneric, DeployConfigType } from "./types";
|
|
9
|
+
export * from "./cloudRun";
|
|
10
|
+
export * from "./cloudSql";
|
|
9
11
|
export * from "./kubernetes";
|
|
10
12
|
export * from "./types";
|
|
11
13
|
export * from "./utils";
|
|
12
14
|
|
|
13
|
-
export type EnvVarContext<D extends DeployConfigType> = {
|
|
14
|
-
deployConfig: false | DeployConfigGeneric<D>;
|
|
15
|
-
commitInfo?: CommitInfo;
|
|
16
|
-
env: string;
|
|
17
|
-
envType: EnvType;
|
|
18
|
-
componentName: string;
|
|
19
|
-
fullName: string;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* the full catladder config
|
|
23
|
-
*/
|
|
24
|
-
fullConfig: Config;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
15
|
export type DeployTypeDefinition<T extends DeployConfigType> = {
|
|
28
16
|
jobs: (context: Context) => CatladderJob[];
|
|
29
|
-
defaults: (
|
|
30
|
-
|
|
17
|
+
defaults: (
|
|
18
|
+
envContext: EnvironmentContext<any, T>
|
|
19
|
+
) => Partial<DeployConfigGeneric<T>>;
|
|
20
|
+
additionalSecretKeys: (envContext: EnvironmentContext<any, T>) => string[];
|
|
31
21
|
getAdditionalEnvVars: (
|
|
32
|
-
|
|
22
|
+
envContext: EnvironmentContext<any, T>
|
|
33
23
|
) => Record<string, string | undefined | null>;
|
|
34
24
|
};
|
|
35
|
-
export * from "./cloudSql";
|
|
36
|
-
export * from "./cloudRun";
|
|
37
25
|
export type DeployTypes = {
|
|
38
26
|
[T in DeployConfigType]: DeployTypeDefinition<T>;
|
|
39
27
|
};
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EnvironmentContext } from "../../types/environmentContext";
|
|
2
2
|
|
|
3
3
|
export const additionalKubernetesSecretKeys = ({
|
|
4
|
-
|
|
5
|
-
}:
|
|
6
|
-
if (!
|
|
4
|
+
deployConfigRaw,
|
|
5
|
+
}: EnvironmentContext<any, "kubernetes">) => {
|
|
6
|
+
if (!deployConfigRaw) {
|
|
7
7
|
return [];
|
|
8
8
|
}
|
|
9
9
|
const keys = [];
|
|
10
|
-
if (
|
|
10
|
+
if (deployConfigRaw.values?.mongodb?.enabled) {
|
|
11
11
|
keys.push("MONGODB_ROOT_PASSWORD");
|
|
12
|
-
if (
|
|
12
|
+
if (deployConfigRaw.values.mongodb.architecture === "replicaset") {
|
|
13
13
|
keys.push("MONGODB_REPLICASET_KEY");
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (
|
|
17
|
+
if (deployConfigRaw.values?.cloudsql?.enabled) {
|
|
18
18
|
keys.push("POSTGRESQL_PASSWORD");
|
|
19
19
|
keys.push("cloudsqlProxyCredentials");
|
|
20
20
|
}
|
|
@@ -11,7 +11,7 @@ export const KUBERNETES_DEPLOY_TYPE: DeployTypeDefinition<"kubernetes"> = {
|
|
|
11
11
|
getAdditionalEnvVars: ({
|
|
12
12
|
componentName,
|
|
13
13
|
fullConfig,
|
|
14
|
-
|
|
14
|
+
deployConfigRaw,
|
|
15
15
|
env,
|
|
16
16
|
envType,
|
|
17
17
|
commitInfo,
|
|
@@ -27,7 +27,7 @@ export const KUBERNETES_DEPLOY_TYPE: DeployTypeDefinition<"kubernetes"> = {
|
|
|
27
27
|
: env;
|
|
28
28
|
|
|
29
29
|
const domainCanonical =
|
|
30
|
-
(
|
|
30
|
+
(deployConfigRaw && deployConfigRaw.cluster?.domainCanonical) || // for convenience, we allow clusters to define a canonical domain, because a cluster has a fixed ip and you will usually have a domain pointing to that cluster
|
|
31
31
|
fullConfig.domainCanonical ||
|
|
32
32
|
"panter.cloud";
|
|
33
33
|
const HOST_CANONICAL = `${componentSlug}.${envInUrl}.${fullConfig.appName}.${fullConfig.customerName}.${domainCanonical}`; // default for kubernetes and rest
|
package/src/types/config.ts
CHANGED
|
@@ -104,6 +104,8 @@ export type EnvConfig<E extends EnvType = EnvType> = {
|
|
|
104
104
|
host?: string;
|
|
105
105
|
} & PartialDeep<DefaultEnvConfig>;
|
|
106
106
|
|
|
107
|
+
export type EnvConfigWithComponent = EnvConfig<EnvType> & ComponentConfig;
|
|
108
|
+
|
|
107
109
|
export type Env = {
|
|
108
110
|
/**
|
|
109
111
|
* local is a special env that is only used in local development
|
package/src/types/context.ts
CHANGED
|
@@ -12,6 +12,7 @@ export type Environment = {
|
|
|
12
12
|
* the full name of the app. We use this as RELEASE_NAME in kubernetes and the service name in google cloud run
|
|
13
13
|
*/
|
|
14
14
|
fullName: string;
|
|
15
|
+
|
|
15
16
|
gitlabEnvironment: {
|
|
16
17
|
name: string;
|
|
17
18
|
url: string;
|
|
@@ -51,6 +52,13 @@ export type YarnPackageManagerInfo = {
|
|
|
51
52
|
};
|
|
52
53
|
|
|
53
54
|
export type PackageManagerInfo = YarnPackageManagerInfo;
|
|
55
|
+
|
|
56
|
+
export type ContextBeforeConfig = {
|
|
57
|
+
componentName: string;
|
|
58
|
+
fullConfig: Config;
|
|
59
|
+
commitInfo?: CommitInfo;
|
|
60
|
+
packageManagerInfo?: PackageManagerInfo;
|
|
61
|
+
};
|
|
54
62
|
export type Context = {
|
|
55
63
|
componentName: string;
|
|
56
64
|
componentConfig: ComponentConfig;
|