@catladder/pipeline 1.55.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.
Files changed (41) hide show
  1. package/dist/build/index.d.ts +2 -1
  2. package/dist/build/types.d.ts +3 -0
  3. package/dist/bundles/catladder-gitlab/index.js +3 -3
  4. package/dist/constants.js +1 -1
  5. package/dist/context/getEnvConfig.d.ts +2 -0
  6. package/dist/context/getEnvConfig.js +26 -0
  7. package/dist/context/getEnvType.d.ts +4 -0
  8. package/dist/context/getEnvType.js +18 -0
  9. package/dist/context/getEnvironment.d.ts +2 -4
  10. package/dist/context/getEnvironment.js +15 -195
  11. package/dist/context/getEnvironmentContext.d.ts +4 -0
  12. package/dist/context/getEnvironmentContext.js +36 -0
  13. package/dist/context/getEnvironmentVariables.d.ts +10 -0
  14. package/dist/context/getEnvironmentVariables.js +322 -0
  15. package/dist/context/index.d.ts +1 -0
  16. package/dist/context/index.js +12 -16
  17. package/dist/deploy/cloudRun/index.js +3 -3
  18. package/dist/deploy/index.d.ts +7 -20
  19. package/dist/deploy/index.js +4 -4
  20. package/dist/deploy/kubernetes/additionalSecretKeys.d.ts +3 -3
  21. package/dist/deploy/kubernetes/additionalSecretKeys.js +5 -5
  22. package/dist/deploy/kubernetes/index.js +2 -2
  23. package/dist/tsconfig.tsbuildinfo +1 -1
  24. package/dist/types/config.d.ts +1 -0
  25. package/dist/types/environmentContext.d.ts +22 -0
  26. package/dist/types/environmentContext.js +3 -0
  27. package/package.json +1 -1
  28. package/src/build/index.ts +4 -1
  29. package/src/build/types.ts +6 -0
  30. package/src/context/getEnvConfig.ts +21 -0
  31. package/src/context/getEnvType.ts +17 -0
  32. package/src/context/getEnvironment.ts +16 -164
  33. package/src/context/getEnvironmentContext.ts +57 -0
  34. package/src/context/getEnvironmentVariables.ts +152 -0
  35. package/src/context/index.ts +17 -14
  36. package/src/deploy/cloudRun/index.ts +4 -4
  37. package/src/deploy/index.ts +9 -21
  38. package/src/deploy/kubernetes/additionalSecretKeys.ts +7 -7
  39. package/src/deploy/kubernetes/index.ts +2 -2
  40. package/src/types/config.ts +2 -0
  41. package/src/types/environmentContext.ts +26 -0
@@ -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);
@@ -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
- const rawConfig = config.components[componentName];
25
- if (!rawConfig) {
26
- throw new Error("unknown component " + componentName);
27
- }
28
- // envs can override the config
29
- const envConfig = rawConfig.env?.[env] ?? {};
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
- // fill in defaults of build and deploy
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[componentConfigWithoutDefaults.build.type].defaults(),
41
+ BUILD_TYPES[
42
+ componentConfigWithoutDefaults.build.type as BuildConfigType
43
+ ].defaults(envContext),
43
44
  deploy:
44
- DEPLOY_TYPES[componentConfigWithoutDefaults.deploy.type].defaults(),
45
+ DEPLOY_TYPES[
46
+ componentConfigWithoutDefaults.deploy.type as DeployConfigType
47
+ ].defaults(envContext),
45
48
  }
46
49
  : {
47
50
  build: {},
@@ -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, deployConfig }) => {
14
+ getAdditionalEnvVars: ({ fullName, env, componentName, deployConfigRaw }) => {
15
15
  const HOST_CANONICAL =
16
16
  fullName.toLowerCase() +
17
17
  "-" +
@@ -20,11 +20,11 @@ export const GCLOUD_RUN_DEPLOY_TYPE: DeployTypeDefinition<"google-cloudrun"> = {
20
20
  ];
21
21
 
22
22
  const jobTriggers =
23
- deployConfig && deployConfig.jobs
23
+ deployConfigRaw && deployConfigRaw.jobs
24
24
  ? Object.fromEntries(
25
- Object.entries(deployConfig.jobs).map(([name, job]) => [
25
+ Object.entries(deployConfigRaw.jobs).map(([name, job]) => [
26
26
  "CLOUD_RUN_JOB_TRIGGER_URL_" + name,
27
- `https://${deployConfig.region}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${deployConfig.projectId}/jobs/${name}:run`,
27
+ `https://${deployConfigRaw.region}-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/${deployConfigRaw.projectId}/jobs/${name}:run`,
28
28
  ])
29
29
  )
30
30
  : {};
@@ -1,39 +1,27 @@
1
- import type { Config, EnvType } from "../types";
2
- import type { CommitInfo, Context } from "../types/context";
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: () => Partial<DeployConfigGeneric<T>>;
30
- additionalSecretKeys: (envVarContext: EnvVarContext<T>) => string[];
17
+ defaults: (
18
+ envContext: EnvironmentContext<any, T>
19
+ ) => Partial<DeployConfigGeneric<T>>;
20
+ additionalSecretKeys: (envContext: EnvironmentContext<any, T>) => string[];
31
21
  getAdditionalEnvVars: (
32
- envVarContext: EnvVarContext<T>
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 { EnvVarContext } from "..";
1
+ import type { EnvironmentContext } from "../../types/environmentContext";
2
2
 
3
3
  export const additionalKubernetesSecretKeys = ({
4
- deployConfig,
5
- }: EnvVarContext<"kubernetes">) => {
6
- if (!deployConfig) {
4
+ deployConfigRaw,
5
+ }: EnvironmentContext<any, "kubernetes">) => {
6
+ if (!deployConfigRaw) {
7
7
  return [];
8
8
  }
9
9
  const keys = [];
10
- if (deployConfig.values?.mongodb?.enabled) {
10
+ if (deployConfigRaw.values?.mongodb?.enabled) {
11
11
  keys.push("MONGODB_ROOT_PASSWORD");
12
- if (deployConfig.values.mongodb.architecture === "replicaset") {
12
+ if (deployConfigRaw.values.mongodb.architecture === "replicaset") {
13
13
  keys.push("MONGODB_REPLICASET_KEY");
14
14
  }
15
15
  }
16
16
 
17
- if (deployConfig.values?.cloudsql?.enabled) {
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
- deployConfig,
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
- (deployConfig && deployConfig.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
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
@@ -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
@@ -0,0 +1,26 @@
1
+ import type { BuildConfigGeneric, BuildConfigType } from "../build";
2
+ import type { DeployConfigGeneric } from "../deploy";
3
+ import type { DeployConfigType } from "../deploy";
4
+ import type { Config, EnvConfigWithComponent, EnvType } from "./config";
5
+ import type { CommitInfo } from "./context";
6
+
7
+ export type EnvironmentContext<
8
+ B extends BuildConfigType,
9
+ D extends DeployConfigType
10
+ > = {
11
+ envConfigRaw: EnvConfigWithComponent;
12
+ buildConfigRaw: false | BuildConfigGeneric<B>;
13
+ deployConfigRaw: false | DeployConfigGeneric<D>;
14
+ commitInfo?: CommitInfo;
15
+ env: string;
16
+ envType: EnvType;
17
+ componentName: string;
18
+ fullName: string;
19
+ environmentSlug: string;
20
+ gitlabEnvironmentName: string;
21
+
22
+ /**
23
+ * the full catladder config
24
+ */
25
+ fullConfig: Config;
26
+ };