Skip to content

Commit 9fea5d2

Browse files
authored
ci(idp-sql): run idp-sql tests in testing isolation (#3985)
* ci(idp-sql): run idp-sql tests in testing isolation * add secret * update tests run, copied from eventarc/audit-storage * debug: swap order * Revert "debug: swap order" This reverts commit 00e8114. * debug: update firebase-admin version * add env, secrets * correct exit code on retry * dynamic service name * wip: pass service account as env, to test * logging: CLOUD_LOGGING_ONLY * correct YAML is useful * dynamicsubtitutions * rename token as not to confuse with new default envvar * use new envvar * update SA usage * add custom audience * cleanup * remove platform, extra SA var * lint * more lint * format * add sample version value * correct audience * lint * disable cleanup for debugging * add test to dev list * attempt proxy powered * lint * attempt: proxy shell * lint * format * try using x-headers * fix: headers * pass db user/name if supplied * revert "try using x-headers" * debugging: where 400 error coming from? * reenable cleanup * try capturing the token error * lint * use explicitly named secret reference * restore: try x-headers (debug) * Revert "restore: try x-headers (debug)" This reverts commit a0bcccf. * revert custom audience (not required if not using ID_TOKEN)
1 parent 1099bd7 commit 9fea5d2

9 files changed

+129
-35
lines changed

.github/config/nodejs-dev.jsonc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@
202202
"run/image-processing",
203203
"run/jobs",
204204
"run/logging-manual",
205+
"run/idp-sql",
205206
"run/markdown-preview/editor",
206207
"run/markdown-preview/renderer",
207208
"run/pubsub",

.github/config/nodejs-prod.jsonc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@
9292
"functions/slack", // TypeError [ERR_INVALID_ARG_TYPE]: The "key" argument must be of type ... Received undefined
9393
"healthcare/fhir", // Error: Cannot find module 'whatwg-url'
9494
"iam/deny", // PERMISSION_DENIED: Permission iam.googleapis.com/denypolicies.create denied on resource cloudresourcemanager.googleapis.com/projects/long-door-651
95-
"run/idp-sql", // (untested) Error: Invalid contents in the credentials file
9695
"storagetransfer", // CredentialsError: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
9796
"video-intelligence", // PERMISSION_DENIED: The caller does not have permission
9897
"workflows", // SyntaxError: Cannot use import statement outside a module

run/idp-sql/ci-setup.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"env": {
3+
"SERVICE_NAME": "idp-sql-${RUN_ID}",
4+
"SAMPLE_VERSION": "${RUN_ID}",
5+
"CLOUD_SQL_CONNECTION_NAME": "nodejs-docs-samples-tests:us-central1:test-postgres-instance",
6+
"DB_NAME": "ci-database",
7+
"DB_USER": "ci-user"
8+
},
9+
"secrets": {
10+
"IDP_KEY": "nodejs-docs-samples-tests/long-door-651-idp-key",
11+
"DB_PASSWORD": "nodejs-docs-samples-tests/nodejs-docs-samples-test-postgres-instance-ci-user-password" }
12+
}

run/idp-sql/package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
},
1515
"scripts": {
1616
"start": "node index.js",
17-
"test": "c8 mocha -p -j 2 test/app.test.js --timeout=120000 --exit",
18-
"system-test": "c8 mocha -p -j 2 test/system.test.js --timeout=1800000 --exit"
17+
"unit-test": "c8 mocha -p -j 2 test/app.test.js --timeout=120000 --exit",
18+
"system-test": "test/proxy-setup.sh && c8 mocha -p -j 2 test/system.test.js --timeout=1800000 --exit",
19+
"all-test": "npm run unit-test && npm run system-test",
20+
"test": "npm -- run all-test"
1921
},
2022
"dependencies": {
2123
"express": "^4.16.2",
22-
"firebase-admin": "^12.0.0",
24+
"firebase-admin": "^13.0.0",
2325
"gcp-metadata": "^6.0.0",
2426
"google-auth-library": "^9.0.0",
2527
"handlebars": "^4.7.6",

run/idp-sql/test/e2e_test_cleanup.yaml

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
# Copyright 2021 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
116
steps:
217

318
- id: 'Delete resources'
@@ -12,11 +27,15 @@ steps:
1227
./test/retry.sh "gcloud container images describe gcr.io/${PROJECT_ID}/${_SERVICE}:${_VERSION}" \
1328
"gcloud container images delete gcr.io/${PROJECT_ID}/${_SERVICE}:${_VERSION} --quiet"
1429
15-
./test/retry.sh "gcloud run services describe ${_SERVICE} --region ${_REGION} --platform ${_PLATFORM}" \
16-
"gcloud run services delete ${_SERVICE} --region ${_REGION} --platform ${_PLATFORM} --quiet"
30+
./test/retry.sh "gcloud run services describe ${_SERVICE} --region ${_REGION}" \
31+
"gcloud run services delete ${_SERVICE} --region ${_REGION} --quiet"
1732
1833
substitutions:
1934
_SERVICE: idp-sql
2035
_VERSION: manual
2136
_REGION: us-central1
22-
_PLATFORM: managed
37+
38+
serviceAccount: 'projects/${PROJECT_ID}/serviceAccounts/${_SERVICE_ACCOUNT}'
39+
options:
40+
logging: CLOUD_LOGGING_ONLY
41+
dynamicSubstitutions: true

run/idp-sql/test/e2e_test_setup.yaml

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
# Copyright 2021 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
116
steps:
217

318
- id: 'Add a Secret to Secret Manager'
@@ -12,9 +27,13 @@ steps:
1227
sed -i "s/\"DB_USER\": \"postgres\"/\"DB_USER\": \"${_DB_USER}\"/" postgres-secrets.json
1328
1429
./test/retry.sh "gcloud secrets create ${_SERVICE}-secrets \
15-
--replication-policy="automatic" \
30+
--replication-policy=automatic \
1631
--data-file=postgres-secrets.json"
1732
33+
./test/retry.sh "gcloud secrets add-iam-policy-binding ${_SERVICE}-secrets \
34+
--member=serviceAccount:${_SERVICE_ACCOUNT} \
35+
--role=roles/secretmanager.secretAccessor"
36+
1837
- id: 'Build Container Image'
1938
name: 'gcr.io/cloud-builders/docker'
2039
entrypoint: '/bin/bash'
@@ -37,11 +56,11 @@ steps:
3756
args:
3857
- '-c'
3958
- |
40-
./test/retry.sh "gcloud beta run deploy ${_SERVICE} \
59+
./test/retry.sh "gcloud run deploy ${_SERVICE} \
4160
--image gcr.io/${PROJECT_ID}/${_SERVICE}:${_VERSION} \
4261
--allow-unauthenticated \
4362
--region ${_REGION} \
44-
--platform ${_PLATFORM} \
63+
--service-account ${_SERVICE_ACCOUNT} \
4564
--add-cloudsql-instances ${_CLOUD_SQL_CONNECTION_NAME} \
4665
--update-secrets CLOUD_SQL_CREDENTIALS_SECRET=${_SERVICE}-secrets:latest"
4766
@@ -52,8 +71,13 @@ substitutions:
5271
_SERVICE: idp-sql
5372
_VERSION: manual
5473
_REGION: us-central1
55-
_PLATFORM: managed
5674
_CLOUD_SQL_CONNECTION_NAME: $PROJECT_ID:us-central1:idp-sql-instance
5775
_DB_NAME: postgres
5876
_DB_USER: postgres
5977
_DB_PASSWORD: password1234
78+
_SERVICE_ACCOUNT: ${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com
79+
80+
serviceAccount: 'projects/${PROJECT_ID}/serviceAccounts/${_SERVICE_ACCOUNT}'
81+
options:
82+
logging: CLOUD_LOGGING_ONLY
83+
dynamicSubstitutions: true

run/idp-sql/test/proxy-setup.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Proof of concept: setting up proxy
16+
17+
curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.15.1/cloud-sql-proxy.linux.amd64
18+
chmod +x cloud-sql-proxy
19+
cloud-sql-proxy -dir=/cloudsql -instances=$INSTANCE_CONNECTION_NAME &

run/idp-sql/test/retry.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ do
5959
if ((attempt_num==max_attempts))
6060
then
6161
echo "Attempt $attempt_num / $max_attempts failed! No more retries left!"
62-
exit
62+
exit 1
6363
else
6464
echo "Attempt $attempt_num / $max_attempts failed!"
6565
sleep $((attempt_num++))

run/idp-sql/test/system.test.js

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ describe('System Tests', () => {
3232
console.log('"SERVICE_NAME" env var not found. Defaulting to "idp-sql"');
3333
SERVICE_NAME = 'idp-sql';
3434
}
35+
36+
const {SERVICE_ACCOUNT} = process.env;
3537
const {SAMPLE_VERSION} = process.env;
3638
const PLATFORM = 'managed';
3739
const REGION = 'us-central1';
@@ -41,6 +43,9 @@ describe('System Tests', () => {
4143
if (!CLOUD_SQL_CONNECTION_NAME) {
4244
throw Error('"CLOUD_SQL_CONNECTION_NAME" env var not found.');
4345
}
46+
47+
const {DB_NAME} = process.env;
48+
const {DB_USER} = process.env;
4449
const {DB_PASSWORD} = process.env;
4550
if (!DB_PASSWORD) {
4651
throw Error('"DB_PASSWORD" env var not found.');
@@ -52,15 +57,19 @@ describe('System Tests', () => {
5257
throw Error('"IDP_KEY" env var not found.');
5358
}
5459

55-
let BASE_URL, ID_TOKEN;
60+
let BASE_URL, CUSTOM_TOKEN;
5661
before(async () => {
5762
// Deploy service using Cloud Build
5863
let buildCmd =
5964
`gcloud builds submit --project ${GOOGLE_CLOUD_PROJECT} ` +
6065
'--config ./test/e2e_test_setup.yaml ' +
61-
`--substitutions _SERVICE=${SERVICE_NAME},_PLATFORM=${PLATFORM},_REGION=${REGION}` +
66+
`--substitutions _SERVICE=${SERVICE_NAME},_REGION=${REGION}` +
6267
`,_DB_PASSWORD=${DB_PASSWORD},_CLOUD_SQL_CONNECTION_NAME=${CLOUD_SQL_CONNECTION_NAME}`;
68+
69+
if (SERVICE_ACCOUNT) buildCmd += `,_SERVICE_ACCOUNT=${SERVICE_ACCOUNT}`;
6370
if (SAMPLE_VERSION) buildCmd += `,_VERSION=${SAMPLE_VERSION}`;
71+
if (DB_USER) buildCmd += `,_DB_USER=${DB_USER}`;
72+
if (DB_NAME) buildCmd += `,_DB_NAME=${DB_NAME}`;
6473

6574
console.log('Starting Cloud Build...');
6675
execSync(buildCmd, {timeout: 240000, shell: true}); // timeout at 4 mins
@@ -82,34 +91,43 @@ describe('System Tests', () => {
8291
}
8392

8493
// Retrieve ID token for testing
94+
95+
console.log('Retrieving IDP token...');
8596
const customToken = await admin.auth().createCustomToken('a-user-id');
86-
const response = await got(
87-
`https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=${IDP_KEY}`,
88-
{
89-
method: 'POST',
90-
retry: {
91-
limit: 5,
92-
statusCodes: [404, 401, 403, 500],
93-
methods: ['POST'],
94-
},
95-
body: JSON.stringify({
96-
token: customToken,
97-
returnSecureToken: true,
98-
}),
99-
}
100-
);
97+
try {
98+
const response = await got(
99+
`https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=${IDP_KEY}`,
100+
{
101+
method: 'POST',
102+
retry: {
103+
limit: 5,
104+
statusCodes: [404, 401, 403, 500],
105+
methods: ['POST'],
106+
},
107+
body: JSON.stringify({
108+
token: customToken,
109+
returnSecureToken: true,
110+
}),
111+
}
112+
);
113+
const tokens = JSON.parse(response.body);
114+
CUSTOM_TOKEN = tokens.idToken;
115+
} catch (err) {
116+
throw Error('IDP Token retrieval failed: ', err.response.body);
117+
}
118+
119+
if (!CUSTOM_TOKEN) throw Error('Unable to acquire an IDP token.');
101120

102-
const tokens = JSON.parse(response.body);
103-
ID_TOKEN = tokens.idToken;
104-
if (!ID_TOKEN) throw Error('Unable to acquire an ID token.');
121+
console.log('Retrieved IDP token');
105122
});
106123

107124
after(() => {
108125
let cleanUpCmd =
109126
`gcloud builds submit --project ${GOOGLE_CLOUD_PROJECT} ` +
110127
'--config ./test/e2e_test_cleanup.yaml ' +
111-
`--substitutions _SERVICE=${SERVICE_NAME},_PLATFORM=${PLATFORM},_REGION=${REGION}`;
128+
`--substitutions _SERVICE=${SERVICE_NAME},_REGION=${REGION}`;
112129
if (SAMPLE_VERSION) cleanUpCmd += `,_VERSION=${SAMPLE_VERSION}`;
130+
if (SERVICE_ACCOUNT) cleanUpCmd += `,_SERVICE_ACCOUNT=${SERVICE_ACCOUNT}`;
113131

114132
execSync(cleanUpCmd, {shell: true});
115133
});
@@ -128,14 +146,14 @@ describe('System Tests', () => {
128146
});
129147

130148
it('Can make a POST request with token', async () => {
131-
assert(ID_TOKEN && ID_TOKEN.length > 0);
149+
assert(CUSTOM_TOKEN && CUSTOM_TOKEN.length > 0);
132150

133151
const options = {
134152
prefixUrl: BASE_URL.trim(),
135153
method: 'POST',
136154
form: {team: 'DOGS'},
137155
headers: {
138-
Authorization: `Bearer ${ID_TOKEN.trim()}`,
156+
Authorization: `Bearer ${CUSTOM_TOKEN.trim()}`,
139157
},
140158
retry: {
141159
limit: 5,

0 commit comments

Comments
 (0)