Skip to content

Commit 59f9481

Browse files
authored
Merge branch 'main' into ariwete-imagemagick
2 parents 1a6ab73 + 9a866b8 commit 59f9481

File tree

122 files changed

+542
-5147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+542
-5147
lines changed

.github/config/README.md

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# Node.js setup
2+
3+
The CI setup file is an _optional_ file to configure the testing infrastructure runtime environment on a per-package basis.
4+
It _must_ be named `ci-setup.json` and be located in the same directory as the `package.json` file.
5+
6+
For example:
7+
8+
```sh
9+
my-product/
10+
└─ my-package/
11+
├─ package.json # package file
12+
└─ ci-setup.json # setup file
13+
```
14+
15+
## Default values
16+
17+
Here are the default values to be used if a `ci-setup.json` file is not present, or only some fields are defined.
18+
19+
```js
20+
{
21+
"env": {},
22+
"secrets": {},
23+
"node-version": 20,
24+
"timeout-minutes": 10,
25+
}
26+
```
27+
28+
These are defined in the [`nodejs-prod.jsonc`](nodejs-prod.jsonc) config file.
29+
30+
### Environment variables
31+
32+
Environment variables are defined as a dictionary where the key is the environment variable name, and the value is the variable’s value.
33+
34+
For example:
35+
36+
```js
37+
{
38+
"env": {
39+
"MY_VAR": "my-value",
40+
"MY_OTHER_VAR": "my-other-value"
41+
}
42+
}
43+
```
44+
45+
The test infrastructure then exports them as environment variables.
46+
47+
### Automatic environment variables
48+
49+
Additionally to the environment variables you define in the `ci-setup.json` file, the test infrastructure always exports the following environment variables:
50+
51+
- `PROJECT_ID`: The project used by the testing infrastructure.
52+
- `RUN_ID`: A random unique identifier, different on every test run.
53+
- `SERVICE_ACCOUNT`: The email of the testing service account.
54+
55+
> **Note**: An environment variable explicitly defined under `env` with the same name as an automatic variable overrides the automatic variable.
56+
57+
### Environment variable interpolation
58+
59+
Environment variables support using variable interpolation in the format `$VAR` or `${VAR}`.
60+
Secrets do not support this to avoid accidentally exposing secrets.
61+
62+
This can be useful for fully qualified resource names like `projects/$PROJECT_ID/resources/my-resource-id`, or to create unique resource names like `my-resource-$RUN_ID`.
63+
64+
## Unique resources
65+
66+
If a test creates and destroys their own resources, make sure the resource names are different for each run.
67+
This can be done by appending a unique identifier to each resource ID. We can use the `$RUN_ID` environment variable.
68+
69+
For example:
70+
71+
```js
72+
{
73+
"env": {
74+
"DATABASE": "projects/$PROJECT_ID/databases/my-db-$RUN_ID"
75+
}
76+
}
77+
```
78+
79+
For more information, see
80+
[Concurrent runs](https://github.com/GoogleCloudPlatform/cloud-samples-tools/blob/main/docs/testing-guidelines.md#concurrent-runs)
81+
in our testing guidelines.
82+
83+
### Secrets
84+
85+
Secrets can be defined as a dictionary where the key is the environment variable to which it’s exported to, and the value is the
86+
[Secret Manager](https://cloud.google.com/security/products/secret-manager)
87+
secret ID in the format `project-id/secret-id`.
88+
89+
For example:
90+
91+
```js
92+
{
93+
"secrets": {
94+
"MY_SECRET": "$PROJECT_ID/my-secret-id",
95+
"MY_OTHER_SECRET": "$PROJECT_ID/my-other-secret-id"
96+
}
97+
}
98+
```
99+
100+
The test infrastructure then fetches the actual secret data and exports them as environment variables.
101+
102+
### Automatic secret values
103+
104+
Additional to any secret values you define in the `ci-setup.json` file, the test infrastructure always exports the following secret value:
105+
106+
- `ID_TOKEN`: an ID token for interacting with private Cloud Run services.
107+
108+
109+
<details>
110+
<summary>
111+
Adapting <b>`ID_TOKEN`</b> use in system testing
112+
</summary>
113+
114+
Due to organization policies, Cloud Run services cannot be deployed with public
115+
access. This means authentication is required in order to perform integration
116+
testing. We do this by using ID Tokens (JWT) provided by [Google GitHub Actions
117+
Auth](https://github.com/google-github-actions/auth/blob/main/docs/EXAMPLES.md#generating-an-id-token-jwt).
118+
119+
By default, the audience of a Cloud Run service is [the full URL of the service
120+
itself](https://cloud.google.com/run/docs/configuring/custom-audiences#:~:text=By%20convention%2C%20the%20audience%20is).
121+
Since we cannot know all the URLs for all samples ahead of time (since unique
122+
IDs are in use), we instead define a custom audience in the GitHub Action, then
123+
apply that as an additional audience to all Cloud Run services.
124+
125+
To use this method, some changes are required:
126+
127+
1. As part of testing setup, add a step to customize the Cloud Run service to have the custom audience `https://action.test/`
128+
129+
```shell
130+
gcloud run services deploy ${_SERVICE} \
131+
... \
132+
--add-custom-audiences="https://action.test/"
133+
```
134+
135+
1. Use the environment variable ID_TOKEN in any Authorization: Bearer calls.
136+
137+
For example, a curl command:
138+
139+
```shell
140+
# ❌ Previous version: calls gcloud
141+
curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://my-service-hash.a.run.app
142+
143+
# ✅ New version: uses environment variable
144+
curl -H "Authorization: Bearer ${ID_TOKEN}" https://my-service-hash.a.run.app
145+
```
146+
147+
For example, a Node.JS script:
148+
149+
```javascript
150+
// ❌ Previous version: auth.getIdTokenClient()
151+
const client = await auth.getIdTokenClient(BASE_URL);
152+
const clientHeaders = await client.getRequestHeaders();
153+
ID_TOKEN = clientHeaders['Authorization'].trim();
154+
if (!ID_TOKEN) throw Error('Unable to acquire an ID token.');
155+
156+
// ✅ New version: uses environment variable
157+
{ID_TOKEN} = process.env;
158+
if (!ID_TOKEN) throw Error('"ID_TOKEN" not found in environment variables.');
159+
```
160+
161+
</details>
162+
163+
### Secrets vs environment variables
164+
165+
Most configuration should be directly set with environment variables.
166+
This includes some things which might appear to be sensitive, but aren't.
167+
Minimizing secrets helps reduce maintenance and troubleshooting efforts.
168+
169+
For example, when a secret gets exposed, we must go through all the secrets used on that repository, assess which ones are real secrets and rotate them, and provide a justificatin of secrets that weren't rotated because they're just configurations.
170+
Keeping configurations as environment variables reduces the number of secrets needed to be assessed.
171+
172+
Examples of environment variables:
173+
174+
- Project IDs
175+
- Cloud resource IDs (or ID templates for a set of tests)
176+
- Service accounts emails (they look like email addresses, but aren't)
177+
- Usernames and passwords for _private_ resources (meaning anyone without project permissions cannot access those resources, so they can’t even reach the login)
178+
179+
These items are also likely to appear in logs, and that is OK.
180+
181+
Some things really are secret and if exposed, would create opportunities for unauthorized access, fraud, etc.
182+
The test infrastructure uses [Google Cloud Secret Manager](https://cloud.google.com/security/products/secret-manager) to store and retrieve secrets.
183+
184+
Examples of real secrets:
185+
186+
- API keys
187+
- Auth tokens
188+
- Identity tokens
189+
- Service account credentials (the JSON content with the actual keys)
190+
- Passwords or API keys to 3rd party services needed for testing
191+
- Usernames and passwords for _public_ resources (accessible to anyone)
192+
193+
> **Important**: Test code and scripts should _**never log secret values**_.
194+
> A test run printing a secret will stay in the commit history, even if another commit is made after.
195+
> This requires rotating that secret.
196+
197+
> **Note**: These testing environment variables and secrets are completely separate from [GitHub Actions secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions) and variables.
198+
> GitHub Actions secrets and variables are _not_ used by the testing infrastructure.
199+
200+
### Node version
201+
202+
You can opt in to use a different Node version if you need a specific version functionality.
203+
204+
For example:
205+
206+
```js
207+
{
208+
"_justification": "My reason for using a specific Node version.",
209+
"node-version": 18,
210+
}
211+
```
212+
213+
We **strongly recommend** not overriding this unless it's a version-specific feature or test.
214+
215+
This _might_ raise flags during review.
216+
217+
If you have a valid reason to use a different Node version, please provide a justification as a `_comment`.
218+
219+
> **Note**: In the future, we might implement automatic checks to validate that tests are using the recommended default version.
220+
221+
### Test timeout
222+
223+
If your tests take longer than the default test timeout, you can opt in to override it.
224+
225+
For example:
226+
227+
```js
228+
{
229+
"_justification": "My reason for this test to take longer to run.",
230+
"timeout-minutes": 30,
231+
}
232+
```
233+
234+
> **Note**: Overriding this **will** raise flags during review.
235+
236+
Tests should run fast, and the default timeout should be more than enough for most tests to run.
237+
If your tests are taking longer, consider splitting them into subpackages.
238+
239+
For example:
240+
241+
```sh
242+
my-product/
243+
├─ snippets/
244+
│ ├─ package.json
245+
│ ├─ fast-samples.js
246+
│ ├─ test/
247+
│ │ └─ fast-samples.test.js
248+
│ └─ slow-snippet/
249+
│ ├─ package.json
250+
│ ├─ slow-snippet.js
251+
│ └─ test/
252+
│ └─ slow-snippet.test.js
253+
├─ new-feature/
254+
│ ├─ package.json
255+
│ ├─ new-feature.js
256+
│ └─ test/
257+
│ └─ new-feature.test.js
258+
└─ e2e-sample/
259+
├─ package.json
260+
├─ slow-sample.js
261+
└─ test/
262+
└─ slow-sample.test.js
263+
```
264+
265+
For more information, see
266+
[Keep tests fast](https://github.com/GoogleCloudPlatform/cloud-samples-tools/blob/main/docs/testing-guidelines.md#keep-tests-fast)
267+
in our testing guidelines.
268+
269+
If you have a valid reason to use a different timeout, please provide a justification as a `_comment`.
270+
271+
There is a hard limit of 120 minutes that cannot be overriden.
272+
273+
> **Note**: In the future, we might implement automatic checks to validate that tests run fast to safely reduce the default timeout.

.github/config/nodejs-dev.jsonc

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@
1717
{
1818
"package-file": [ "package.json" ],
1919
"ci-setup-filename": "ci-setup.json",
20+
21+
// If these change, please update the .github/config/README.md too!
2022
"ci-setup-defaults": {
21-
"node-version": 20,
22-
"timeout-minutes": 10,
2323
"env": { },
24-
"secrets": { }
24+
"secrets": { },
25+
"node-version": 20,
26+
"timeout-minutes": 10
2527
},
28+
2629
"ignore": [
30+
// TODO: do not ignore .github/config once everything is in prod
2731
".github/config/", // prevent changes to exclusions from running all tests
2832
".eslintignore",
2933
".eslintrc.json",
@@ -38,11 +42,13 @@
3842
".github/scripts/",
3943
".github/snippet-bot.yml",
4044
".github/trusted-contribution.yml",
45+
// TODO: do not ignore .github/workflows once everything is in prod
46+
".github/workflows/", // prevent removing old tests to trigger everything
4147
".gitignore",
4248
".kokoro/",
4349
".prettierignore",
4450
".prettierrc.js",
45-
"cloud-samples-tools", // checked out by GH action in ci-*.yml
51+
"cloud-samples-tools", // checked out by GH action in ci-*.yml
4652
"CODEOWNERS",
4753
"CODE_OF_CONDUCT.md",
4854
"CONTRIBUTING.md",
@@ -56,17 +62,20 @@
5662
"owlbot.py",
5763
"renovate.json"
5864
],
65+
5966
// These are all working well in prod, so we can exclude them from dev.
6067
// Once all packages are in prod, we can remove this dev config.
6168
"exclude-packages": [
6269
"functions/concepts", // parent directory
6370
"functions/firebase", // parent directory
6471
"functions/helloworld", // parent directory
6572
"functions/http", // parent directory
73+
"functions/http/uploadFile", // no tests exist
6674
"functions/log", // parent directory
6775
"functions/pubsub", // parent directory
6876
"memorystore/redis", // parent directory
6977
"recaptcha_enterprise/demosite/app", // no tests exist
78+
7079
// These tests are already passing in prod, so skip them in dev.
7180
"appengine/building-an-app/build",
7281
"appengine/building-an-app/update",
@@ -77,6 +86,7 @@
7786
"appengine/hello-world/standard",
7887
"appengine/memcached",
7988
"appengine/metadata/flexible_nodejs16_and_earlier",
89+
"appengine/metadata/standard",
8090
"appengine/pubsub",
8191
"appengine/static-files",
8292
"appengine/storage/flexible",
@@ -107,7 +117,9 @@
107117
"endpoints/getting-started",
108118
"endpoints/getting-started-grpc",
109119
"error-reporting",
120+
"eventarc/audit-storage",
110121
"eventarc/generic",
122+
"eventarc/pubsub",
111123
"functions/concepts/afterResponse",
112124
"functions/concepts/afterTimeout",
113125
"functions/concepts/backgroundTermination",
@@ -186,13 +198,17 @@
186198
"run/logging-manual",
187199
"run/markdown-preview/renderer",
188200
"run/pubsub",
201+
"run/system-package",
189202
"run/websockets",
190203
"secret-manager",
191204
"security-center/snippets",
192205
"service-directory/snippets",
193206
"storage-control",
207+
"speech",
208+
"talent",
194209
"texttospeech",
195210
"tpu",
211+
"translate",
196212
"workflows/invoke-private-endpoint"
197213
]
198214
}

0 commit comments

Comments
 (0)