-
Notifications
You must be signed in to change notification settings - Fork 2k
feat: testing isolation #3872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat: testing isolation #3872
Changes from 125 commits
Commits
Show all changes
137 commits
Select commit
Hold shift + click to select a range
e6c4a9c
add samples testing tooling
4b4b3fd
edit to trigger tests
f96d2cf
update reusable workflow path
cb10e4f
make relative path
99ffa49
fix config
011cac8
inline workflow
24ae0ff
install before lint
8c15093
install before lint on Makefile
f35e5a6
install gts
3a1703e
install repo wide deps
159548d
add test action
1fc7db8
add project id
2a31b48
add auth credentials
cb1af68
add id-token permissions
6fc0660
use service account
c4b09fe
cleanup
8082788
modify ignored file
784e8e8
revert change
0a13f40
make change to trigger tests
f7e547f
include e2e-test
34fd1ef
check whether to e2e-test
70ed258
add e2e-test configuration
359bf41
add e2e-test as extra config
1dd8e9e
also check for substring as match
edc1692
pass entire path to match
5d730e2
mark as experimental
7e724a5
add experimental emoji
5c63239
test on node 18 and 22
4665437
reorder matrix
f7287f8
use wip directly without service account
d8494d2
use kokoro service account
a3e85be
trigger all tests on root changes
6108a4a
do not fail fast
27ba947
make lint a global job
188e47d
separate nodejs versions
4c40beb
add checkout to reusable workflow
cb51d95
add contents read permission
9811b3c
skip testing everything on root changes
1b08c9a
give contents read permissions
5591184
call reusable workflow correctly
7848775
reusable workflow for nodejs test
fb8760d
change names
6815794
more explicit names
42b40c9
only show version number
4ec1a19
test all
9e3bc3e
use node 20
04448a6
create service account file
48cf1e6
adjust token lifetime
88e2d38
lower node version
c21429e
do not test all
153c94c
use node 16
b236312
use node 20
c1f7300
restore language test
04cc1e2
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
bc91620
add install and more comments
4f8a45b
assign and print variables in the same line
03b7f1e
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
4511504
change to trigger tests
8d169b5
test all
a818e6e
exclude special tests
f451f21
more packages to exclude
1262f3e
support exclude-packages and json comments
69192c8
use jsonc extension
5b3f469
use flag package
8bb4dc5
remove unused actions for config
0928722
restore changes
1710ed3
use correct config
6fe8059
better error messages
9b6ee80
improve error messages
5d06e66
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
9afaa2a
use io/fs.WalkDir
72e204c
rename variable
0854b06
experiment with nightly tests
3f96c33
remove e2e-test for now
f995455
use ternary operator
4aabf3b
disable pr tests temporarily
c96ca22
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
e7f56a1
use diffs file
9ee8f52
print git diff outputs as well
21b97df
remove git utils
5991759
initial prototype for nightlies
5f6cc38
update workflow command
84223b2
only sprintf when wildcard is there
7e69a04
print on success too
ca4a100
improve error messages
8cb15e0
disable parallelism
22cbf8f
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
d335ec1
improve error reporting
ee375a6
clean before each test
b99d1dc
include parallel flag
9139ce5
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
f6d05a2
re-enable tests and disable nightlies experiment
61412f3
disable fail-fast
30f24ee
revert clean commands
333f06a
add files to ignore
ba3c057
ignore speech package
a4e91f9
ignore translate package
e80bcd0
add license headers and support multi-line comments
1fb450b
revert and add build to lint
0f60ed1
move tools to single command
f71163d
update workflow to new command
400db0e
Add comment for cron schedule
26b5d2b
run nightlies each on their own job
2784119
fix typo on path
cc7d9a0
better messages
d944a39
exclude talent package
51bc759
document affected
da62a12
reorganize files
82cb3ba
use script to run tests
91f2e62
run all tests
1786146
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
4033572
fix syntax error
9a7d172
do not fail on npm install
34db331
print outputs immediately
069d376
increment failures atomically
8732c07
disable nightly batch job
fba5bc6
install repo root package
d138552
use log.Fatalf
9ba7912
add unit tests and testing instructions
35c9c3d
move tools directory
7926134
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
4f58bcd
fix tests pkg path
f965b2d
run tests on action
932c00a
add go linting
5012283
use double star on paths
22f4361
use variadic argument prints
b7e6c59
remove everything related to run-all
de73036
add tool summary
c74db78
use pointer for methods
25b6929
use table based testing
cc7fd6b
return nil if error
687262b
use manual test checks
0b6d130
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
ed6906f
moved tests to source directory
f3f88e6
update test command
947ea28
Merge branch 'main' into testing-isolation
iennae a3cb72d
comment schedule trigger
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # If you prefer the allow list template instead of the deny list, see community template: | ||
| # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore | ||
| # | ||
| # Binaries for programs and plugins | ||
| *.exe | ||
| *.exe~ | ||
| *.dll | ||
| *.so | ||
| *.dylib | ||
|
|
||
| # Test binary, built with `go test -c` | ||
| *.test | ||
|
|
||
| # Output of the go coverage tool, specifically when used with LiteIDE | ||
| *.out | ||
|
|
||
| # Dependency directories (remove the comment below to include it) | ||
| # vendor/ | ||
|
|
||
| # Go workspace file | ||
| go.work | ||
| go.work.sum | ||
|
|
||
| # env file | ||
| .env |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| # Cloud Samples tools | ||
|
|
||
| This is a collection of tools used for Cloud Samples maintenance and infrastructure. | ||
|
|
||
| ## Config files | ||
|
|
||
| For this tools, we refer to a **package** as an isolated directory, which contains a "package file". | ||
| For example, `package.json` in Node.js, `requirements.txt` in Python, `go.mod` in Go, or `pom.xml` in Java. | ||
|
|
||
| Each language has different configurations. | ||
| We define them in config files in the repository, this way the tooling keeps language agnostic and each repository can have different configurations. | ||
|
|
||
| The config file can be a `.json` file, or a `.jsonc` (JSON with comments) file. | ||
| For `.jsonc` files, it supports both `// single line comments` and `/* multi-line comments */`. | ||
|
|
||
| For example: | ||
|
|
||
| ```jsonc | ||
| { | ||
| // The package file where the tests should be run (required). | ||
| "package-file": "package.json", | ||
|
|
||
| // Match diffs only on .js and .ts files | ||
| // Defaults to match all files. | ||
| "match": ["*.js", "*.ts"], | ||
|
|
||
| // Ignore diffs on the README, text files, and anything under node_modules/. | ||
| // Defaults to not ignore anything. | ||
| "ignore": ["README.md", "*.txt", "node_modules/"], | ||
|
|
||
| // Skip these packages, these could be handled by a different config. | ||
| // Defaults to not exclude anything. | ||
| "exclude-packages": ["path/to/slow-to-test", "special-config-package"], | ||
| } | ||
| ``` | ||
|
|
||
| For more information, see [`pkg/utils/config.go`](pkg/utils/config.go). | ||
|
|
||
| ## Building | ||
|
|
||
| To build the tools, we must change to the directory where the tools package is defined. | ||
| We can run it in a subshell using parentheses to keep our working directory from changing. | ||
|
|
||
| ```sh | ||
| (cd .github/workflows/samples-tools && go build -o /tmp/tools ./cmd/*) | ||
| ``` | ||
|
|
||
| ## Running the tools unit tests | ||
|
|
||
| To the tools tests, we must change to the directory where the tools package is defined. | ||
| We can run it in a subshell using parentheses to keep our working directory from changing. | ||
|
|
||
| ```sh | ||
| (cd .github/workflows/samples-tools && go test ./test) | ||
| ``` | ||
|
|
||
| ## Finding affected packages | ||
|
|
||
| > This must run at the repository root directory. | ||
|
|
||
| First, generate a file with all the diffs. | ||
| This file should be one file per line. | ||
|
|
||
| You can use `git diff` to test on files that have changed in your branch. | ||
| You can also create the file manually if you want to test something without commiting changes to your branch. | ||
|
|
||
| ```sh | ||
| git --no-pager diff --name-only HEAD origin/main | tee /tmp/diffs.txt | ||
| ``` | ||
|
|
||
| Now we can check which packages have been affected. | ||
| We pass the config file and the diffs file as positional arguments. | ||
|
|
||
| ```sh | ||
| /tmp/tools affected .github/config/nodejs.jsonc /tmp/diffs.txt | ||
| ``` | ||
|
|
||
| ## Running on all packages | ||
|
|
||
| > This must run at the repository root directory. | ||
|
|
||
| We pass the config file and a bash script to run as positional arguments. | ||
| The script must receive a single positional argument in `$1` as the package name. | ||
| For example, the script should be called like `bash path/to/my-script.sh path/to/package`. | ||
|
|
||
| ```sh | ||
| # To run all the Node.js tests. | ||
| /tmp/tools run-all ./github/config/nodejs.jsonc ./github/scripts/nodejs-test.sh | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| /* | ||
| Copyright 2024 Google LLC | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| https://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
|
|
||
| package main | ||
|
|
||
| import ( | ||
| "cloud-samples-tools/pkg/utils" | ||
| "encoding/json" | ||
| "fmt" | ||
| "log" | ||
| "os" | ||
| "strings" | ||
| ) | ||
|
|
||
| func main() { | ||
davidcavazos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| command := "" | ||
| if len(os.Args) > 1 { | ||
| command = os.Args[1] | ||
| } else { | ||
| fmt.Fprintf(os.Stderr, "❌ no command specified\n") | ||
| printUsage(os.Stderr) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| switch command { | ||
| case "affected": | ||
| configFile := "" | ||
| if len(os.Args) > 2 { | ||
| configFile = os.Args[2] | ||
| } else { | ||
| fmt.Fprintf(os.Stderr, "❌ no config file specified\n") | ||
| printUsage(os.Stderr) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| diffsFile := "" | ||
| if len(os.Args) > 3 { | ||
| diffsFile = os.Args[3] | ||
| } else { | ||
| fmt.Fprintf(os.Stderr, "❌ no diffs file specified\n") | ||
| printUsage(os.Stderr) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| affectedCmd(configFile, diffsFile) | ||
|
|
||
| case "run-all": | ||
| configFile := "" | ||
| if len(os.Args) > 2 { | ||
| configFile = os.Args[2] | ||
| } else { | ||
| fmt.Fprintf(os.Stderr, "❌ no config file specified\n") | ||
| printUsage(os.Stderr) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| script := "" | ||
| if len(os.Args) > 3 { | ||
| script = os.Args[3] | ||
| } else { | ||
| fmt.Fprintf(os.Stderr, "❌ no script file specified\n") | ||
| printUsage(os.Stderr) | ||
| os.Exit(1) | ||
| } | ||
|
|
||
| runAllCmd(configFile, script) | ||
|
|
||
| default: | ||
| fmt.Fprintf(os.Stderr, "❌ unknown command: %s\n", command) | ||
| printUsage(os.Stderr) | ||
| os.Exit(1) | ||
| } | ||
| } | ||
|
|
||
| func printUsage(f *os.File) { | ||
| fmt.Fprintf(f, "usage: tools <command> ...\n") | ||
| fmt.Fprintf(f, "\n") | ||
| fmt.Fprintf(f, "commands:\n") | ||
| fmt.Fprintf(f, " affected path/to/config.jsonc path/to/diffs.txt\n") | ||
| fmt.Fprintf(f, " run-all path/to/config.jsonc path/to/script.sh\n") | ||
| } | ||
|
|
||
| func affectedCmd(configFile string, diffsFile string) { | ||
| config, err := utils.LoadConfig(configFile) | ||
| if err != nil { | ||
| log.Fatalf("❌ error loading the config file: %v\n%v\n", configFile, err) | ||
| } | ||
|
|
||
| diffsBytes, err := os.ReadFile(diffsFile) | ||
| if err != nil { | ||
| log.Fatalf("❌ error getting the diffs: %v\n%v\n", diffsFile, err) | ||
| } | ||
| diffs := strings.Split(string(diffsBytes), "\n") | ||
|
|
||
| packages, err := utils.Affected(config, diffs) | ||
| if err != nil { | ||
| log.Fatalf("❌ error finding the affected packages.\n%v\n", err) | ||
| } | ||
| if len(packages) > 256 { | ||
| log.Fatalf( | ||
| "❌ Error: GitHub Actions only supports up to 256 packages, got %v packages, for more details see:\n%v\n", | ||
| len(packages), | ||
| "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow", | ||
| ) | ||
| } | ||
|
|
||
| packagesJson, err := json.Marshal(packages) | ||
| if err != nil { | ||
| log.Fatalf("❌ error marshaling packages to JSON.\n%v\n", err) | ||
| } | ||
|
|
||
| fmt.Println(string(packagesJson)) | ||
| } | ||
|
|
||
| func runAllCmd(configFile string, script string) { | ||
| config, err := utils.LoadConfig(configFile) | ||
| if err != nil { | ||
| log.Fatalf("❌ error loading the config file: %v\n%v\n", configFile, err) | ||
| } | ||
|
|
||
| packages, err := utils.FindAllPackages(".", config) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "❌ error finding packages.\n%v\n", err) | ||
| } | ||
|
|
||
| maxGoroutines := 16 | ||
davidcavazos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| failed := utils.RunAll(packages, script, maxGoroutines) | ||
|
|
||
| fmt.Printf(strings.Repeat("-", 80) + "\n") | ||
| fmt.Printf("Total tests: %v\n", len(packages)) | ||
| fmt.Printf("Failed tests: %v\n", failed) | ||
|
|
||
| if failed > 0 { | ||
| log.Fatalf("❌ some tests failed, exit with code 1.") | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| module cloud-samples-tools | ||
|
|
||
| go 1.22.0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| /* | ||
| Copyright 2024 Google LLC | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| https://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
|
|
||
| package utils | ||
|
|
||
| import ( | ||
| "slices" | ||
| ) | ||
|
|
||
| func Affected(config Config, diffs []string) ([]string, error) { | ||
davidcavazos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| changed := Changed(config, diffs) | ||
| if slices.Contains(changed, ".") { | ||
|
||
| return FindAllPackages(".", config) | ||
| } | ||
| return changed, nil | ||
| } | ||
|
|
||
| func Changed(config Config, diffs []string) []string { | ||
davidcavazos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| changedUnique := make(map[string]bool) | ||
| for _, diff := range diffs { | ||
| if !config.Matches(diff) { | ||
| continue | ||
| } | ||
| pkg := config.FindPackage(diff) | ||
| if slices.Contains(config.ExcludePackages, pkg) { | ||
| continue | ||
| } | ||
| changedUnique[pkg] = true | ||
| } | ||
|
|
||
| if len(changedUnique) == 0 { | ||
| return []string{"."} | ||
| } | ||
|
|
||
| changed := make([]string, 0, len(changedUnique)) | ||
| for pkg := range changedUnique { | ||
| changed = append(changed, pkg) | ||
| } | ||
| return changed | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.