@catladder/pipeline 1.54.0 → 1.55.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/index.d.ts +2 -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 +61 -24
- package/dist/deploy/cloudRun/index.d.ts +1 -6
- package/dist/deploy/cloudRun/index.js +51 -31
- package/dist/deploy/index.d.ts +7 -20
- package/dist/deploy/index.js +8 -21
- 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 +27 -23
- package/dist/deploy/types/index.d.ts +2 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/config.d.ts +1 -0
- package/dist/types/environmentContext.d.ts +22 -0
- package/dist/types/environmentContext.js +3 -0
- package/package.json +1 -1
- package/src/build/index.ts +4 -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 +75 -24
- package/src/deploy/cloudRun/index.ts +12 -23
- package/src/deploy/index.ts +11 -23
- package/src/deploy/kubernetes/additionalSecretKeys.ts +7 -7
- package/src/deploy/kubernetes/index.ts +2 -2
- package/src/deploy/types/googleCloudRun.ts +25 -23
- package/src/types/config.ts +2 -0
- package/src/types/environmentContext.ts +26 -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: {},
|
|
@@ -7,6 +7,10 @@ import { getRunnerImage } from "../../runner";
|
|
|
7
7
|
import type { Context } from "../../types/context";
|
|
8
8
|
import type { CatladderJob } from "../../types/jobs";
|
|
9
9
|
import { getBaseDeploymentJob, getBaseDeploymentStopJob } from "../base";
|
|
10
|
+
import type {
|
|
11
|
+
DeployConfigCloudRunJob,
|
|
12
|
+
DeployConfigCloudRunService,
|
|
13
|
+
} from "../types";
|
|
10
14
|
import { isOfDeployType } from "../types";
|
|
11
15
|
import { gcloudServiceAccountLoginCommands } from "./utils/gcloudServiceAccountLoginCommands";
|
|
12
16
|
|
|
@@ -17,7 +21,7 @@ export const createGoogleCloudRunDeployJobs = (
|
|
|
17
21
|
if (deployConfig === false) {
|
|
18
22
|
return [];
|
|
19
23
|
}
|
|
20
|
-
if (!isOfDeployType(deployConfig, "google-cloudrun"
|
|
24
|
+
if (!isOfDeployType(deployConfig, "google-cloudrun")) {
|
|
21
25
|
// should not happen
|
|
22
26
|
throw new Error("deploy config is wrong");
|
|
23
27
|
}
|
|
@@ -46,46 +50,87 @@ export const createGoogleCloudRunDeployJobs = (
|
|
|
46
50
|
.join(",");
|
|
47
51
|
|
|
48
52
|
const commonArgs = `--project ${deployConfig.projectId} --region=${deployConfig.region}`;
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
|
|
54
|
+
const commonDeployArgs = `--image ${gcloudImageName} ${commonArgs} --labels ${labelsString}`;
|
|
55
|
+
const serviceName = context.environment.fullName.toLowerCase();
|
|
56
|
+
|
|
57
|
+
const getServiceDeployScript = (
|
|
58
|
+
service?: DeployConfigCloudRunService | true
|
|
59
|
+
) => {
|
|
51
60
|
const command =
|
|
52
|
-
|
|
61
|
+
service !== true
|
|
62
|
+
? service?.command ?? context.componentConfig.build.startCommand
|
|
63
|
+
: undefined;
|
|
64
|
+
|
|
53
65
|
const commandArg = command
|
|
54
66
|
? `--command="${command.split(" ").join(",")}"`
|
|
55
67
|
: "";
|
|
56
68
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
return `gcloud run deploy ${serviceName} ${commandArg} ${commonDeployArgs} --env-vars-file=____envvars.yaml --allow-unauthenticated`;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const getJobDeployScripts = (
|
|
73
|
+
jobName: string,
|
|
74
|
+
job: DeployConfigCloudRunJob
|
|
75
|
+
) => {
|
|
76
|
+
// due to some oversight from google, jobs create does not accept `--env-vars-file` 🤦
|
|
77
|
+
// lucky, update on the other hand accepts it... so let's just imediatly update it
|
|
78
|
+
|
|
79
|
+
// also we cannot upsert a job, so we have to create it and catch the error and then update
|
|
80
|
+
const args = `${jobName} --command="${job.command
|
|
81
|
+
.split(" ")
|
|
82
|
+
.join(",")}" ${commonDeployArgs}`;
|
|
83
|
+
return [
|
|
84
|
+
"set +e", // disable fail job on error
|
|
85
|
+
`gcloud beta run jobs create ${args}`,
|
|
86
|
+
"set -e", // reenable
|
|
87
|
+
`gcloud beta run jobs update ${args} --env-vars-file=____envvars.yaml`,
|
|
88
|
+
];
|
|
64
89
|
};
|
|
65
90
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
const commonStopArgs = `${commonArgs} --quiet`;
|
|
69
|
-
if (deployConfig.type === "google-cloudrun") {
|
|
70
|
-
return `gcloud run services delete ${name} ${commonStopArgs}`;
|
|
71
|
-
}
|
|
72
|
-
if (deployConfig.type === "google-cloudrun-job") {
|
|
73
|
-
return `gcloud beta run jobs delete ${name} ${commonStopArgs}`;
|
|
74
|
-
}
|
|
91
|
+
const getJobRunScript = (jobName: string) => {
|
|
92
|
+
return `gcloud beta run jobs execute ${jobName} ${commonArgs}`;
|
|
75
93
|
};
|
|
76
94
|
|
|
77
|
-
const
|
|
95
|
+
const getFullJobName = (name: string) =>
|
|
96
|
+
context.environment.fullName.toLowerCase() + "-" + name;
|
|
97
|
+
|
|
98
|
+
const jobsWithNames = Object.entries(deployConfig.jobs ?? {}).map(
|
|
99
|
+
([name, job]) => [getFullJobName(name), job] as const
|
|
100
|
+
);
|
|
101
|
+
const cloudRunDeployScripts = [
|
|
78
102
|
`echo "$ENV_VARS" > ____envvars.yaml`, // TODO: split secrets out
|
|
79
|
-
|
|
103
|
+
|
|
104
|
+
...jobsWithNames
|
|
105
|
+
.map(([name, job]) => getJobDeployScripts(name, job))
|
|
106
|
+
.flat(),
|
|
107
|
+
|
|
108
|
+
...(deployConfig.service !== false
|
|
109
|
+
? [getServiceDeployScript(deployConfig.service)]
|
|
110
|
+
: []),
|
|
111
|
+
|
|
112
|
+
...jobsWithNames
|
|
113
|
+
.filter(([name, job]) => job.when === "postDeploy")
|
|
114
|
+
.map(([name, job]) => getJobRunScript(name)),
|
|
80
115
|
`docker image rm ${gcloudImageName}`,
|
|
81
116
|
];
|
|
82
117
|
|
|
118
|
+
const cloudRunStopScripts = [
|
|
119
|
+
...(deployConfig.service !== false
|
|
120
|
+
? [`gcloud run services delete ${serviceName}`]
|
|
121
|
+
: []),
|
|
122
|
+
...Object.entries(deployConfig.jobs ?? {}).map(
|
|
123
|
+
([jobName, job]) => `gcloud beta run jobs delete ${jobName}`
|
|
124
|
+
),
|
|
125
|
+
];
|
|
126
|
+
|
|
83
127
|
const baseStopJob = getBaseDeploymentStopJob(context);
|
|
84
128
|
|
|
85
129
|
return [
|
|
86
130
|
merge({}, baseDeploymentJob, getDockerJobBaseProps(context), {
|
|
87
131
|
artifacts: { paths: ["____envvars.yaml"] },
|
|
88
132
|
variables: {
|
|
133
|
+
CLOUDSDK_CORE_DISABLE_PROMPTS: "1",
|
|
89
134
|
ENV_VARS: dump(allEnvVars, {
|
|
90
135
|
lineWidth: -1,
|
|
91
136
|
quotingType: "'",
|
|
@@ -93,12 +138,18 @@ export const createGoogleCloudRunDeployJobs = (
|
|
|
93
138
|
}),
|
|
94
139
|
},
|
|
95
140
|
image: getRunnerImage("gcloud"),
|
|
96
|
-
script: [...pushImageToArtifactsRegistry, ...
|
|
141
|
+
script: [...pushImageToArtifactsRegistry, ...cloudRunDeployScripts],
|
|
97
142
|
}),
|
|
98
143
|
|
|
99
144
|
merge({}, baseStopJob, {
|
|
100
145
|
image: getRunnerImage("gcloud"),
|
|
101
|
-
|
|
146
|
+
variables: {
|
|
147
|
+
CLOUDSDK_CORE_DISABLE_PROMPTS: "1",
|
|
148
|
+
},
|
|
149
|
+
script: [
|
|
150
|
+
...gcloudServiceAccountLoginCommands(context),
|
|
151
|
+
...cloudRunStopScripts,
|
|
152
|
+
],
|
|
102
153
|
}),
|
|
103
154
|
];
|
|
104
155
|
};
|
|
@@ -11,7 +11,7 @@ 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: ({ fullName, env, componentName }) => {
|
|
14
|
+
getAdditionalEnvVars: ({ fullName, env, componentName, deployConfigRaw }) => {
|
|
15
15
|
const HOST_CANONICAL =
|
|
16
16
|
fullName.toLowerCase() +
|
|
17
17
|
"-" +
|
|
@@ -19,30 +19,19 @@ export const GCLOUD_RUN_DEPLOY_TYPE: DeployTypeDefinition<"google-cloudrun"> = {
|
|
|
19
19
|
getSecretVarName(env, componentName, GCLOUD_RUN_CANONICAL_HOST_SUFFIX)
|
|
20
20
|
];
|
|
21
21
|
|
|
22
|
+
const jobTriggers =
|
|
23
|
+
deployConfigRaw && deployConfigRaw.jobs
|
|
24
|
+
? Object.fromEntries(
|
|
25
|
+
Object.entries(deployConfigRaw.jobs).map(([name, job]) => [
|
|
26
|
+
"CLOUD_RUN_JOB_TRIGGER_URL_" + name,
|
|
27
|
+
`https://${deployConfigRaw.region}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${deployConfigRaw.projectId}/jobs/${name}:run`,
|
|
28
|
+
])
|
|
29
|
+
)
|
|
30
|
+
: {};
|
|
31
|
+
|
|
22
32
|
return {
|
|
23
33
|
HOST_CANONICAL,
|
|
34
|
+
...jobTriggers,
|
|
24
35
|
};
|
|
25
36
|
},
|
|
26
37
|
};
|
|
27
|
-
|
|
28
|
-
export const GCLOUD_RUN_JOB_DEPLOY_TYPE: DeployTypeDefinition<"google-cloudrun-job"> =
|
|
29
|
-
{
|
|
30
|
-
jobs: createGoogleCloudRunDeployJobs,
|
|
31
|
-
defaults: () => ({}),
|
|
32
|
-
additionalSecretKeys: () => [GCLOUD_DEPLOY_CREDENTIALS_KEY],
|
|
33
|
-
getAdditionalEnvVars: ({ deployConfig, fullName }) => {
|
|
34
|
-
if (!deployConfig) {
|
|
35
|
-
return {};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const jobName = fullName.toLowerCase();
|
|
39
|
-
const CLOUD_RUN_JOB_TRIGGER_URL = `https://${deployConfig.region}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${deployConfig.projectId}/jobs/${jobName}:run`;
|
|
40
|
-
|
|
41
|
-
return { CLOUD_RUN_JOB_TRIGGER_URL };
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const GCLOUD_RUN_DEPLOY_TYPES = {
|
|
46
|
-
"google-cloudrun": GCLOUD_RUN_DEPLOY_TYPE,
|
|
47
|
-
"google-cloudrun-job": GCLOUD_RUN_JOB_DEPLOY_TYPE,
|
|
48
|
-
};
|