Skip to content
Merged
Show file tree
Hide file tree
Changes from 125 commits
Commits
Show all changes
137 commits
Select commit Hold shift + click to select a range
e6c4a9c
add samples testing tooling
Sep 20, 2024
4b4b3fd
edit to trigger tests
Sep 20, 2024
f96d2cf
update reusable workflow path
Sep 20, 2024
cb10e4f
make relative path
Sep 20, 2024
99ffa49
fix config
Sep 20, 2024
011cac8
inline workflow
Sep 20, 2024
24ae0ff
install before lint
Sep 20, 2024
8c15093
install before lint on Makefile
Sep 20, 2024
f35e5a6
install gts
Sep 20, 2024
3a1703e
install repo wide deps
Sep 20, 2024
159548d
add test action
Sep 20, 2024
1fc7db8
add project id
Sep 20, 2024
2a31b48
add auth credentials
Sep 21, 2024
cb1af68
add id-token permissions
Sep 21, 2024
6fc0660
use service account
Sep 21, 2024
c4b09fe
cleanup
Sep 21, 2024
8082788
modify ignored file
Sep 23, 2024
784e8e8
revert change
Sep 23, 2024
0a13f40
make change to trigger tests
Sep 23, 2024
f7e547f
include e2e-test
Sep 23, 2024
34fd1ef
check whether to e2e-test
Sep 23, 2024
70ed258
add e2e-test configuration
Sep 23, 2024
359bf41
add e2e-test as extra config
Sep 23, 2024
1dd8e9e
also check for substring as match
Sep 23, 2024
edc1692
pass entire path to match
Sep 23, 2024
5d730e2
mark as experimental
Sep 24, 2024
7e724a5
add experimental emoji
Sep 24, 2024
5c63239
test on node 18 and 22
Sep 24, 2024
4665437
reorder matrix
Sep 24, 2024
f7287f8
use wip directly without service account
Sep 24, 2024
d8494d2
use kokoro service account
Sep 24, 2024
a3e85be
trigger all tests on root changes
Sep 24, 2024
6108a4a
do not fail fast
Sep 24, 2024
27ba947
make lint a global job
Sep 24, 2024
188e47d
separate nodejs versions
Sep 24, 2024
4c40beb
add checkout to reusable workflow
Sep 24, 2024
cb51d95
add contents read permission
Sep 24, 2024
9811b3c
skip testing everything on root changes
Sep 24, 2024
1b08c9a
give contents read permissions
Sep 24, 2024
5591184
call reusable workflow correctly
Sep 24, 2024
7848775
reusable workflow for nodejs test
Sep 24, 2024
fb8760d
change names
Sep 24, 2024
6815794
more explicit names
Sep 24, 2024
42b40c9
only show version number
Sep 24, 2024
4ec1a19
test all
Sep 24, 2024
9e3bc3e
use node 20
Sep 24, 2024
04448a6
create service account file
Sep 24, 2024
48cf1e6
adjust token lifetime
Sep 24, 2024
88e2d38
lower node version
Sep 24, 2024
c21429e
do not test all
Sep 24, 2024
153c94c
use node 16
Sep 24, 2024
b236312
use node 20
Sep 24, 2024
c1f7300
restore language test
Sep 24, 2024
04cc1e2
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
Sep 25, 2024
bc91620
add install and more comments
Sep 25, 2024
4f8a45b
assign and print variables in the same line
Sep 25, 2024
03b7f1e
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
Sep 26, 2024
4511504
change to trigger tests
Sep 26, 2024
8d169b5
test all
Sep 26, 2024
a818e6e
exclude special tests
Sep 26, 2024
f451f21
more packages to exclude
Sep 26, 2024
1262f3e
support exclude-packages and json comments
Sep 30, 2024
69192c8
use jsonc extension
Sep 30, 2024
5b3f469
use flag package
Sep 30, 2024
8bb4dc5
remove unused actions for config
Sep 30, 2024
0928722
restore changes
Sep 30, 2024
1710ed3
use correct config
Sep 30, 2024
6fe8059
better error messages
Oct 1, 2024
9b6ee80
improve error messages
Oct 1, 2024
5d06e66
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
Oct 1, 2024
9afaa2a
use io/fs.WalkDir
Oct 2, 2024
72e204c
rename variable
Oct 2, 2024
0854b06
experiment with nightly tests
Oct 2, 2024
3f96c33
remove e2e-test for now
Oct 2, 2024
f995455
use ternary operator
Oct 2, 2024
4aabf3b
disable pr tests temporarily
Oct 2, 2024
c96ca22
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
Oct 2, 2024
e7f56a1
use diffs file
Oct 2, 2024
9ee8f52
print git diff outputs as well
Oct 2, 2024
21b97df
remove git utils
Oct 2, 2024
5991759
initial prototype for nightlies
Oct 3, 2024
5f6cc38
update workflow command
Oct 3, 2024
84223b2
only sprintf when wildcard is there
Oct 3, 2024
7e69a04
print on success too
Oct 3, 2024
ca4a100
improve error messages
Oct 3, 2024
8cb15e0
disable parallelism
Oct 3, 2024
22cbf8f
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
Oct 3, 2024
d335ec1
improve error reporting
Oct 3, 2024
ee375a6
clean before each test
Oct 3, 2024
b99d1dc
include parallel flag
Oct 3, 2024
9139ce5
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
Oct 3, 2024
f6d05a2
re-enable tests and disable nightlies experiment
Oct 3, 2024
61412f3
disable fail-fast
Oct 3, 2024
30f24ee
revert clean commands
Oct 3, 2024
333f06a
add files to ignore
Oct 3, 2024
ba3c057
ignore speech package
Oct 3, 2024
a4e91f9
ignore translate package
Oct 3, 2024
e80bcd0
add license headers and support multi-line comments
Oct 4, 2024
1fb450b
revert and add build to lint
Oct 4, 2024
0f60ed1
move tools to single command
Oct 4, 2024
f71163d
update workflow to new command
Oct 4, 2024
400db0e
Add comment for cron schedule
Oct 4, 2024
26b5d2b
run nightlies each on their own job
Oct 4, 2024
2784119
fix typo on path
Oct 4, 2024
cc7d9a0
better messages
Oct 4, 2024
d944a39
exclude talent package
Oct 4, 2024
51bc759
document affected
Oct 7, 2024
da62a12
reorganize files
Oct 7, 2024
82cb3ba
use script to run tests
Oct 7, 2024
91f2e62
run all tests
Oct 7, 2024
1786146
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
Oct 7, 2024
4033572
fix syntax error
Oct 7, 2024
9a7d172
do not fail on npm install
Oct 7, 2024
34db331
print outputs immediately
Oct 7, 2024
069d376
increment failures atomically
Oct 7, 2024
8732c07
disable nightly batch job
Oct 7, 2024
fba5bc6
install repo root package
Oct 7, 2024
d138552
use log.Fatalf
Oct 8, 2024
9ba7912
add unit tests and testing instructions
Oct 8, 2024
35c9c3d
move tools directory
Oct 9, 2024
7926134
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
Oct 9, 2024
4f58bcd
fix tests pkg path
Oct 9, 2024
f965b2d
run tests on action
Oct 9, 2024
932c00a
add go linting
Oct 9, 2024
5012283
use double star on paths
Oct 9, 2024
22f4361
use variadic argument prints
Oct 10, 2024
b7e6c59
remove everything related to run-all
Oct 10, 2024
de73036
add tool summary
Oct 10, 2024
c74db78
use pointer for methods
Oct 10, 2024
25b6929
use table based testing
Oct 10, 2024
cc7fd6b
return nil if error
Oct 10, 2024
687262b
use manual test checks
Oct 15, 2024
0b6d130
Merge branch 'main' of github.com:GoogleCloudPlatform/nodejs-docs-sam…
Oct 15, 2024
ed6906f
moved tests to source directory
Oct 21, 2024
f3f88e6
update test command
Oct 21, 2024
947ea28
Merge branch 'main' into testing-isolation
iennae Nov 5, 2024
a3cb72d
comment schedule trigger
Nov 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/cloud-samples-tools/.gitignore
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
89 changes: 89 additions & 0 deletions .github/cloud-samples-tools/README.md
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
```
149 changes: 149 additions & 0 deletions .github/cloud-samples-tools/cmd/main.go
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() {
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
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.")
}
}
3 changes: 3 additions & 0 deletions .github/cloud-samples-tools/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module cloud-samples-tools

go 1.22.0
53 changes: 53 additions & 0 deletions .github/cloud-samples-tools/pkg/utils/affected.go
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) {
changed := Changed(config, diffs)
if slices.Contains(changed, ".") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow is this new fancy slices packages nice. Back in my day ... ;D.

[No action required]

return FindAllPackages(".", config)
}
return changed, nil
}

func Changed(config Config, diffs []string) []string {
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
}
Loading