@catladder/pipeline 3.9.2 → 3.10.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/dist/build/rails/test.js +1 -1
- package/dist/constants.js +1 -1
- package/dist/deploy/cloudRun/index.js +7 -5
- package/dist/deploy/cloudRun/utils/database.d.ts +21 -2
- package/dist/deploy/cloudRun/utils/database.js +27 -6
- package/dist/deploy/types/googleCloudRun.d.ts +10 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/examples/__snapshots__/cloud-run-with-sql-multiple-dbs.test.ts.snap +4515 -0
- package/examples/__snapshots__/rails-k8s-with-worker-dockerfile.test.ts.snap +1 -1
- package/examples/__snapshots__/rails-k8s-with-worker.test.ts.snap +1 -1
- package/examples/cloud-run-with-sql-multiple-dbs.test.ts +11 -0
- package/examples/cloud-run-with-sql-multiple-dbs.ts +87 -0
- package/package.json +1 -1
- package/src/build/rails/test.ts +1 -1
- package/src/deploy/cloudRun/index.ts +14 -5
- package/src/deploy/cloudRun/utils/database.ts +93 -8
- package/src/deploy/types/googleCloudRun.ts +11 -0
|
@@ -137,7 +137,7 @@ app 🧪 test:
|
|
|
137
137
|
- cd .temp-with-dockerfile
|
|
138
138
|
- bundle config set path 'tmp/cache'
|
|
139
139
|
- bundle install -j $(nproc)
|
|
140
|
-
- bundle exec rake db:
|
|
140
|
+
- bundle exec rake db:test:prepare
|
|
141
141
|
- bundle exec rake assets:precompile assets:clean
|
|
142
142
|
- bundle exec rspec
|
|
143
143
|
cache: *a2
|
|
@@ -137,7 +137,7 @@ app 🧪 test:
|
|
|
137
137
|
- cd .
|
|
138
138
|
- bundle config set path 'tmp/cache'
|
|
139
139
|
- bundle install -j $(nproc)
|
|
140
|
-
- bundle exec rake db:
|
|
140
|
+
- bundle exec rake db:test:prepare
|
|
141
141
|
- bundle exec rake assets:precompile assets:clean
|
|
142
142
|
- bundle exec rspec
|
|
143
143
|
cache: *a2
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createYamlLocalPipeline } from "./__utils__/helpers";
|
|
2
|
+
import config from "./cloud-run-with-sql-multiple-dbs";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This test is auto-generated.
|
|
6
|
+
* Modifications will be overwritten on every `yarn test` run!
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
it("matches snapshot for cloud-run-with-sql-multiple-dbs local pipeline YAML", async () => {
|
|
10
|
+
expect(await createYamlLocalPipeline(config)).toMatchSnapshot();
|
|
11
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ComponentConfig,
|
|
3
|
+
Config,
|
|
4
|
+
DeployConfigCloudRunCloudSql,
|
|
5
|
+
} from "../src";
|
|
6
|
+
|
|
7
|
+
// both dbs currently need to run on the same instance
|
|
8
|
+
const CLOUD_SQL_BASE: DeployConfigCloudRunCloudSql = {
|
|
9
|
+
type: "unmanaged",
|
|
10
|
+
instanceConnectionName: "projectId:region:instancename",
|
|
11
|
+
dbUser: "my-user",
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const DbComponent = (name: string): ComponentConfig => ({
|
|
15
|
+
dir: "packages/" + name,
|
|
16
|
+
build: {
|
|
17
|
+
type: "node",
|
|
18
|
+
},
|
|
19
|
+
deploy: {
|
|
20
|
+
type: "google-cloudrun",
|
|
21
|
+
projectId: "google-project-id",
|
|
22
|
+
region: "europe-west6",
|
|
23
|
+
cloudSql: {
|
|
24
|
+
...CLOUD_SQL_BASE,
|
|
25
|
+
/*
|
|
26
|
+
there is a flaw in the current implementation,
|
|
27
|
+
that the db-url does not embed the env vars like DB_NAME, DB_USER, DB_PASSWORD, etc,
|
|
28
|
+
This leads to the problem that if you reference the DATABASE_URL from another component,
|
|
29
|
+
it will not work properly, as it only contains var names instead of the actual values.
|
|
30
|
+
Setting this to "embedded" will embed the actual values into the db-url, which solves this problem.
|
|
31
|
+
*/
|
|
32
|
+
dbConnectionStringVariablesMode: "embedded",
|
|
33
|
+
},
|
|
34
|
+
service: false,
|
|
35
|
+
jobs: {
|
|
36
|
+
migrate: {
|
|
37
|
+
command: "yarn migrate",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
execute: {
|
|
41
|
+
migrate: {
|
|
42
|
+
type: "job",
|
|
43
|
+
job: "migrate",
|
|
44
|
+
when: "preDeploy",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
const config = {
|
|
50
|
+
appName: "test-app",
|
|
51
|
+
customerName: "pan",
|
|
52
|
+
components: {
|
|
53
|
+
// its good practise to have separated db components
|
|
54
|
+
db1: DbComponent("db1"),
|
|
55
|
+
db2: DbComponent("db2"),
|
|
56
|
+
|
|
57
|
+
api: {
|
|
58
|
+
dir: "api",
|
|
59
|
+
build: {
|
|
60
|
+
type: "node",
|
|
61
|
+
buildCommand: "yarn build:worker",
|
|
62
|
+
},
|
|
63
|
+
deploy: {
|
|
64
|
+
type: "google-cloudrun",
|
|
65
|
+
projectId: "google-project-id",
|
|
66
|
+
region: "europe-west6",
|
|
67
|
+
cloudSql: {
|
|
68
|
+
// currently one db is the default, as it injects additional env vars
|
|
69
|
+
...CLOUD_SQL_BASE,
|
|
70
|
+
dbBaseName: "db1",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
vars: {
|
|
74
|
+
public: {
|
|
75
|
+
// we reference the second db-url
|
|
76
|
+
DATABASE_URL_2: "${db2:DATABASE_URL}",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
} satisfies Config;
|
|
82
|
+
|
|
83
|
+
export default config;
|
|
84
|
+
|
|
85
|
+
export const information = {
|
|
86
|
+
title: "Cloud Run: With SQL Reuse DB",
|
|
87
|
+
};
|
package/package.json
CHANGED
package/src/build/rails/test.ts
CHANGED
|
@@ -93,7 +93,7 @@ export const createRailsTestJobs = (
|
|
|
93
93
|
`cd ${context.build.dir}`,
|
|
94
94
|
...bundlerInstall,
|
|
95
95
|
...(ensureArrayOrNull(buildConfig.test?.command) ?? [
|
|
96
|
-
"bundle exec rake db:
|
|
96
|
+
"bundle exec rake db:test:prepare",
|
|
97
97
|
"bundle exec rake assets:precompile assets:clean",
|
|
98
98
|
"bundle exec rspec",
|
|
99
99
|
]),
|
|
@@ -11,8 +11,9 @@ import { getFullDbName } from "../cloudSql/utils";
|
|
|
11
11
|
import { createGoogleCloudRunDeployJobs } from "./createJobs";
|
|
12
12
|
import { getCloudRunJobExecuteUrl } from "./utils/cloudRunExecutionUrl";
|
|
13
13
|
import {
|
|
14
|
-
|
|
14
|
+
DEFAULT_DB_VARIABLES_MODE,
|
|
15
15
|
getDatabaseConnectionString,
|
|
16
|
+
getDatabaseJdbcUrl,
|
|
16
17
|
} from "./utils/database";
|
|
17
18
|
|
|
18
19
|
export const GCLOUD_DEPLOY_CREDENTIALS_KEY = "GCLOUD_DEPLOY_credentialsKey";
|
|
@@ -42,16 +43,24 @@ const getCloudSqlVariables = ({
|
|
|
42
43
|
.map(([key, value]) => `&${key}=${value}`)
|
|
43
44
|
.join("");
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
const dbVars = {
|
|
46
47
|
CLOUD_SQL_INSTANCE_CONNECTION_NAME:
|
|
47
48
|
deployConfigRaw.cloudSql.instanceConnectionName,
|
|
48
49
|
DB_NAME: DB_NAME,
|
|
49
50
|
DB_USER: deployConfigRaw.cloudSql.dbUser ?? "postgres",
|
|
50
51
|
DB_PASSWORD: "$" + getSecretVarName(env, componentName, "DB_PASSWORD"),
|
|
51
|
-
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
...dbVars,
|
|
55
|
+
DATABASE_URL: getDatabaseConnectionString(
|
|
52
56
|
deployConfigRaw.cloudSql,
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
dbVars,
|
|
58
|
+
).concat(additionalQueryParamsString),
|
|
59
|
+
DATABASE_JDBC_URL: getDatabaseJdbcUrl(
|
|
60
|
+
dbVars,
|
|
61
|
+
deployConfigRaw.cloudSql.dbConnectionStringVariablesMode ??
|
|
62
|
+
DEFAULT_DB_VARIABLES_MODE,
|
|
63
|
+
),
|
|
55
64
|
};
|
|
56
65
|
}
|
|
57
66
|
return {};
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BashExpression,
|
|
3
|
+
joinBashExpressions,
|
|
4
|
+
type StringOrBashExpression,
|
|
5
|
+
} from "../../../bash";
|
|
1
6
|
import type { ComponentContext } from "../../../types";
|
|
2
7
|
import { allowFailureInScripts, repeatOnFailure } from "../../../utils/gitlab";
|
|
3
8
|
import type {
|
|
@@ -57,21 +62,101 @@ export const getDatabaseCreateScript = (
|
|
|
57
62
|
]);
|
|
58
63
|
};
|
|
59
64
|
|
|
60
|
-
export
|
|
61
|
-
|
|
65
|
+
export type DBVariables = {
|
|
66
|
+
CLOUD_SQL_INSTANCE_CONNECTION_NAME: StringOrBashExpression;
|
|
67
|
+
DB_NAME: StringOrBashExpression;
|
|
68
|
+
DB_USER: StringOrBashExpression;
|
|
69
|
+
DB_PASSWORD: StringOrBashExpression;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* controls how variables in the connection string are handled
|
|
74
|
+
*
|
|
75
|
+
* - legacy: variables like $DB_USER will be kept as environment variables to be replaced at runtime (default). It is not using BashExpressions as this was not the case in the past.
|
|
76
|
+
* - embedded: variables will be replaced with their actual values in the connection string
|
|
77
|
+
*
|
|
78
|
+
* We will remove the legacy mode in the future, as it is confusing. But its unclear whether its a breaking change in some edge cases
|
|
79
|
+
*/
|
|
80
|
+
export type DBVariablesMode = "legacy" | "embedded";
|
|
81
|
+
|
|
82
|
+
export const DEFAULT_DB_VARIABLES_MODE: DBVariablesMode = "legacy";
|
|
83
|
+
|
|
84
|
+
const getVariableOrValue = (
|
|
85
|
+
key: keyof DBVariables,
|
|
86
|
+
variables: DBVariables,
|
|
87
|
+
mode: DBVariablesMode,
|
|
88
|
+
): StringOrBashExpression => {
|
|
89
|
+
return mode === "legacy" ? `$${key}` : variables[key];
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const getDatabaseJdbcUrl = (
|
|
93
|
+
variables: DBVariables,
|
|
94
|
+
mode: DBVariablesMode,
|
|
95
|
+
) => {
|
|
96
|
+
const parts = [
|
|
97
|
+
"jdbc:postgresql:///",
|
|
98
|
+
getVariableOrValue("DB_NAME", variables, mode),
|
|
99
|
+
"?cloudSqlInstance=",
|
|
100
|
+
getVariableOrValue("CLOUD_SQL_INSTANCE_CONNECTION_NAME", variables, mode),
|
|
101
|
+
"&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=",
|
|
102
|
+
getVariableOrValue("DB_USER", variables, mode),
|
|
103
|
+
"&password=",
|
|
104
|
+
getVariableOrValue("DB_PASSWORD", variables, mode),
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
return joinBashExpressions(parts);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export const getRailsDatabaseConnectionString = (
|
|
111
|
+
variables: DBVariables,
|
|
112
|
+
mode: DBVariablesMode,
|
|
113
|
+
) => {
|
|
114
|
+
const parts = [
|
|
115
|
+
"postgresql://",
|
|
116
|
+
getVariableOrValue("DB_USER", variables, mode),
|
|
117
|
+
":",
|
|
118
|
+
getVariableOrValue("DB_PASSWORD", variables, mode),
|
|
119
|
+
"@",
|
|
120
|
+
encodeURIComponent(
|
|
121
|
+
`/cloudsql/${variables.CLOUD_SQL_INSTANCE_CONNECTION_NAME}`,
|
|
122
|
+
),
|
|
123
|
+
"/",
|
|
124
|
+
getVariableOrValue("DB_NAME", variables, mode),
|
|
125
|
+
"?",
|
|
126
|
+
];
|
|
127
|
+
return joinBashExpressions(parts);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const getPrismaDatabaseConnectionString = (
|
|
131
|
+
variables: DBVariables,
|
|
132
|
+
mode: DBVariablesMode,
|
|
133
|
+
) => {
|
|
134
|
+
const parts = [
|
|
135
|
+
"postgresql://",
|
|
136
|
+
getVariableOrValue("DB_USER", variables, mode),
|
|
137
|
+
":",
|
|
138
|
+
getVariableOrValue("DB_PASSWORD", variables, mode),
|
|
139
|
+
"@localhost/",
|
|
140
|
+
getVariableOrValue("DB_NAME", variables, mode),
|
|
141
|
+
"?host=/cloudsql/",
|
|
142
|
+
getVariableOrValue("CLOUD_SQL_INSTANCE_CONNECTION_NAME", variables, mode),
|
|
143
|
+
];
|
|
144
|
+
return joinBashExpressions(parts);
|
|
145
|
+
};
|
|
62
146
|
|
|
63
147
|
export const getDatabaseConnectionString = (
|
|
64
148
|
config: DeployConfigCloudRunCloudSql,
|
|
65
|
-
|
|
149
|
+
variables: DBVariables,
|
|
150
|
+
): StringOrBashExpression => {
|
|
151
|
+
const mode =
|
|
152
|
+
config.dbConnectionStringVariablesMode ?? DEFAULT_DB_VARIABLES_MODE;
|
|
66
153
|
switch (config.dbConnectionStringFormat) {
|
|
67
154
|
case "jdbc":
|
|
68
|
-
return
|
|
155
|
+
return getDatabaseJdbcUrl(variables, mode);
|
|
69
156
|
case "rails":
|
|
70
|
-
return
|
|
71
|
-
`/cloudsql/${config.instanceConnectionName}`,
|
|
72
|
-
)}/$DB_NAME?`;
|
|
157
|
+
return getRailsDatabaseConnectionString(variables, mode);
|
|
73
158
|
default:
|
|
74
159
|
// prisma
|
|
75
|
-
return
|
|
160
|
+
return getPrismaDatabaseConnectionString(variables, mode);
|
|
76
161
|
}
|
|
77
162
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { DBVariablesMode } from "../cloudRun/utils/database";
|
|
1
2
|
import type { DeployConfigBase } from "./base";
|
|
2
3
|
|
|
3
4
|
export type Gcloudregion =
|
|
@@ -77,6 +78,16 @@ export type DeployConfigCloudRunCloudSql = {
|
|
|
77
78
|
*/
|
|
78
79
|
dbConnectionStringFormat?: "prisma" | "rails" | "jdbc";
|
|
79
80
|
|
|
81
|
+
/**
|
|
82
|
+
* controls how variables in the connection string are handled
|
|
83
|
+
*
|
|
84
|
+
* - environment: variables like $DB_USER will be kept as environment variables to be replaced at runtime (default)
|
|
85
|
+
* - embedded: variables will be replaced with their actual values in the connection string
|
|
86
|
+
*
|
|
87
|
+
* @default "environment"
|
|
88
|
+
*/
|
|
89
|
+
dbConnectionStringVariablesMode?: DBVariablesMode;
|
|
90
|
+
|
|
80
91
|
/**
|
|
81
92
|
* add additional query params to the database connection string
|
|
82
93
|
*/
|