@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.
@@ -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:setup
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:setup
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
@@ -53,7 +53,7 @@
53
53
  }
54
54
  ],
55
55
  "license": "MIT",
56
- "version": "3.9.2",
56
+ "version": "3.10.0",
57
57
  "scripts": {
58
58
  "build:tsc": "yarn tsc",
59
59
  "build": "yarn build:compile && yarn build:inline-variables",
@@ -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:setup",
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
- DATABASE_JDBC_URL,
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
- return {
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
- DATABASE_URL: `${getDatabaseConnectionString(
52
+ };
53
+ return {
54
+ ...dbVars,
55
+ DATABASE_URL: getDatabaseConnectionString(
52
56
  deployConfigRaw.cloudSql,
53
- )}${additionalQueryParamsString}`,
54
- DATABASE_JDBC_URL: DATABASE_JDBC_URL,
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 const DATABASE_JDBC_URL =
61
- "jdbc:postgresql:///$DB_NAME?cloudSqlInstance=$CLOUD_SQL_INSTANCE_CONNECTION_NAME&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=$DB_USER&password=$DB_PASSWORD";
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
- ): string => {
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 DATABASE_JDBC_URL;
155
+ return getDatabaseJdbcUrl(variables, mode);
69
156
  case "rails":
70
- return `postgresql://$DB_USER:$DB_PASSWORD@${encodeURIComponent(
71
- `/cloudsql/${config.instanceConnectionName}`,
72
- )}/$DB_NAME?`;
157
+ return getRailsDatabaseConnectionString(variables, mode);
73
158
  default:
74
159
  // prisma
75
- return "postgresql://$DB_USER:$DB_PASSWORD@localhost/$DB_NAME?host=/cloudsql/$CLOUD_SQL_INSTANCE_CONNECTION_NAME";
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
  */