Skip to content

Commit 81fcafa

Browse files
author
David Cavazos
committed
find setup files on separate command
1 parent 5ec99cd commit 81fcafa

File tree

7 files changed

+95
-83
lines changed

7 files changed

+95
-83
lines changed

.github/cloud-samples-tools/cmd/main.go

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ var usage = `usage: tools <command> ...
3030
3131
commands:
3232
affected path/to/config.jsonc path/to/diffs.txt
33-
run-all path/to/config.jsonc path/to/script.sh
33+
setups path/to/config.jsonc path/to/affected-paths.txt
3434
`
3535

3636
// Entry point to validate command line arguments.
@@ -54,15 +54,17 @@ func main() {
5454
log.Fatalln("❌ no diffs file specified\n", usage)
5555
}
5656

57-
affectedCmd(configFile, diffsFile)
57+
outputFile := flag.Arg(3)
58+
59+
affectedCmd(configFile, diffsFile, outputFile)
5860

5961
default:
6062
log.Fatalln("❌ unknown command: ", command, "\n", usage)
6163
}
6264
}
6365

6466
// affected command entry point to validate inputs.
65-
func affectedCmd(configFile string, diffsFile string) {
67+
func affectedCmd(configFile string, diffsFile string, outputFile string) {
6668
config, err := c.LoadConfig(configFile)
6769
if err != nil {
6870
log.Fatalln("❌ error loading the config file: ", configFile, "\n", err)
@@ -76,23 +78,32 @@ func affectedCmd(configFile string, diffsFile string) {
7678
diffs := strings.Split(strings.TrimSpace(string(diffsBytes)), "\n")
7779

7880
// Log to stderr since GitHub Actions expects the output on stdout.
79-
packages, err := config.Affected(os.Stderr, diffs)
81+
paths, err := config.Affected(os.Stderr, diffs)
8082
if err != nil {
8183
log.Fatalln("❌ error finding the affected packages.\n", err)
8284
}
83-
if len(packages) > 256 {
85+
if len(paths) > 256 {
8486
log.Fatalln(
8587
"❌ Error: GitHub Actions only supports up to 256 packages, got ",
86-
len(packages),
88+
len(paths),
8789
" packages, for more details see:\n",
8890
"https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow",
8991
)
9092
}
9193

92-
packagesJson, err := json.Marshal(packages)
94+
if outputFile != "" {
95+
file, err := os.Create(outputFile)
96+
if err != nil {
97+
log.Fatalln("❌ eror creating output file.\n", err)
98+
}
99+
for _, path := range paths {
100+
fmt.Fprintf(file, "%v\n", path)
101+
}
102+
}
103+
104+
output, err := json.Marshal(paths)
93105
if err != nil {
94106
log.Fatalln("❌ error marshaling packages to JSON.\n", err)
95107
}
96-
97-
fmt.Println(string(packagesJson))
108+
fmt.Println(string(output))
98109
}

.github/cloud-samples-tools/pkg/config/config.go

Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,9 @@ type Config struct {
3232
// Filename to look for the root of a package.
3333
PackageFile []string `json:"package-file"`
3434

35-
// Setup file, must be located in the same directory as the package file.
36-
Setup struct {
37-
FileName string `json:"filename"`
38-
Defaults map[string]any `json:"defaults"`
39-
} `json:"setup"`
35+
// CI setup file, must be located in the same directory as the package file.
36+
CISetupFileName string `json:"ci-setup-filename"`
37+
CISetupDefaults *CISetup `json:"ci-setup-defaults"`
4038

4139
// Pattern to match filenames or directories.
4240
Match []string `json:"match"`
@@ -48,13 +46,7 @@ type Config struct {
4846
ExcludePackages []string `json:"exclude-packages"`
4947
}
5048

51-
type Package struct {
52-
// Package directory path.
53-
Path string `json:"path"`
54-
55-
// Package setup configurations.
56-
Setup *map[string]any `json:"setup"`
57-
}
49+
type CISetup = map[string]any
5850

5951
// Saves the config to the given file.
6052
func (c *Config) Save(file *os.File) error {
@@ -73,7 +65,7 @@ func (c *Config) Save(file *os.File) error {
7365
func LoadConfig(path string) (*Config, error) {
7466
// Read the config file.
7567
var config Config
76-
err := ReadJsonc(path, &config)
68+
err := readJsonc(path, &config)
7769
if err != nil {
7870
return nil, err
7971
}
@@ -85,6 +77,9 @@ func LoadConfig(path string) (*Config, error) {
8577
if config.Match == nil {
8678
config.Match = []string{"*"}
8779
}
80+
if config.CISetupFileName == "" {
81+
config.CISetupFileName = "ci-setup.json"
82+
}
8883

8984
return &config, nil
9085
}
@@ -111,15 +106,14 @@ func (c *Config) Matches(path string) bool {
111106
// IsPackageDir returns true if the path is a package directory.
112107
func (c *Config) IsPackageDir(dir string) bool {
113108
for _, filename := range c.PackageFile {
114-
packageFile := filepath.Join(dir, filename)
115-
if fileExists(packageFile) {
109+
if fileExists(filepath.Join(dir, filename)) {
116110
return true
117111
}
118112
}
119113
return false
120114
}
121115

122-
// FindPackage returns the package name for the given path.
116+
// FindPackage returns the most specific package path for the given filename.
123117
func (c *Config) FindPackage(path string) string {
124118
dir := filepath.Dir(path)
125119
if dir == "." || c.IsPackageDir(dir) {
@@ -128,9 +122,9 @@ func (c *Config) FindPackage(path string) string {
128122
return c.FindPackage(dir)
129123
}
130124

131-
// FindAllPackages finds all the packages in the given root directory.
125+
// FindAllPackages finds all the package paths in the given root directory.
132126
func (c *Config) FindAllPackages(root string) ([]string, error) {
133-
var packages []string
127+
var paths []string
134128
err := fs.WalkDir(os.DirFS(root), ".",
135129
func(path string, d os.DirEntry, err error) error {
136130
if err != nil {
@@ -143,45 +137,15 @@ func (c *Config) FindAllPackages(root string) ([]string, error) {
143137
return nil
144138
}
145139
if d.IsDir() && c.Matches(path) && c.IsPackageDir(path) {
146-
packages = append(packages, path)
140+
paths = append(paths, path)
147141
return nil
148142
}
149143
return nil
150144
})
151145
if err != nil {
152146
return []string{}, err
153147
}
154-
return packages, nil
155-
}
156-
157-
// Affected returns the packages that have been affected from diffs.
158-
// If there are diffs on at leat one global file affecting all packages,
159-
// then this returns all packages matched by the config.
160-
func (c *Config) Affected(log io.Writer, diffs []string) ([]Package, error) {
161-
changed := c.Changed(log, diffs)
162-
if slices.Contains(changed, ".") {
163-
allPackages, err := c.FindAllPackages(".")
164-
if err != nil {
165-
return nil, err
166-
}
167-
changed = allPackages
168-
}
169-
170-
packages := make([]Package, 0, len(changed))
171-
for _, path := range changed {
172-
pkg := Package{Path: path, Setup: &c.Setup.Defaults}
173-
if c.Setup.FileName != "" {
174-
setup_file := filepath.Join(path, c.Setup.FileName)
175-
if fileExists(setup_file) {
176-
err := ReadJsonc(setup_file, pkg.Setup)
177-
if err != nil {
178-
return nil, err
179-
}
180-
}
181-
}
182-
packages = append(packages, pkg)
183-
}
184-
return packages, nil
148+
return paths, nil
185149
}
186150

187151
// Changed returns the packages that have changed.
@@ -193,17 +157,54 @@ func (c *Config) Changed(log io.Writer, diffs []string) []string {
193157
if !c.Matches(diff) {
194158
continue
195159
}
196-
pkg := c.FindPackage(diff)
197-
changedUnique[pkg] = true
160+
path := c.FindPackage(diff)
161+
if path == "." {
162+
fmt.Fprintf(log, "ℹ️ Global file changed: %q\n", diff)
163+
}
164+
changedUnique[path] = true
198165
}
199166

200167
changed := make([]string, 0, len(changedUnique))
201-
for pkg := range changedUnique {
202-
if slices.Contains(c.ExcludePackages, pkg) {
203-
fmt.Fprintf(log, "ℹ️ Excluded package %q, skipping.\n", pkg)
168+
for path := range changedUnique {
169+
if slices.Contains(c.ExcludePackages, path) {
170+
fmt.Fprintf(log, "ℹ️ Excluded package %q, skipping.\n", path)
204171
continue
205172
}
206-
changed = append(changed, pkg)
173+
changed = append(changed, path)
207174
}
208175
return changed
209176
}
177+
178+
// Affected returns the packages that have been affected from diffs.
179+
// If there are diffs on at leat one global file affecting all packages,
180+
// then this returns all packages matched by the config.
181+
func (c *Config) Affected(log io.Writer, diffs []string) ([]string, error) {
182+
paths := c.Changed(log, diffs)
183+
if slices.Contains(paths, ".") {
184+
fmt.Fprintf(log, "One or more global files were affected, all packages marked as affected.")
185+
allPackages, err := c.FindAllPackages(".")
186+
if err != nil {
187+
return nil, err
188+
}
189+
paths = allPackages
190+
}
191+
return paths, nil
192+
}
193+
194+
func (c *Config) FindSetupFiles(paths []string) (*map[string]CISetup, error) {
195+
setups := make(map[string]CISetup, len(paths))
196+
for _, path := range paths {
197+
setup := *c.CISetupDefaults
198+
setupFile := filepath.Join(path, c.CISetupFileName)
199+
if fileExists(setupFile) {
200+
// This mutates `setup` so there's no need to reassign it.
201+
// It keeps the default values if they're not in the JSON file.
202+
err := readJsonc(setupFile, &setup)
203+
if err != nil {
204+
return nil, err
205+
}
206+
}
207+
setups[path] = setup
208+
}
209+
return &setups, nil
210+
}

.github/cloud-samples-tools/pkg/config/utils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
var multiLineCommentsRegex = regexp.MustCompile(`(?s)\s*/\*.*?\*/`)
2727
var singleLineCommentsRegex = regexp.MustCompile(`\s*//.*\s*`)
2828

29-
func ReadJsonc[a any](path string, ref *a) error {
29+
func readJsonc[a any](path string, ref *a) error {
3030
// Read the JSONC file.
3131
sourceJsonc, err := os.ReadFile(path)
3232
if err != nil {

.github/config/nodejs-dev.jsonc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,9 @@
1616

1717
{
1818
"package-file": [ "package.json" ],
19-
"setup": {
20-
"filename": "setup.json",
21-
"defaults": {
22-
"nodejs_version": 20,
23-
"secrets": null
24-
}
19+
"ci-setup-defaults": {
20+
"node-version": 20,
21+
"secrets": null
2522
},
2623
"ignore": [
2724
".eslintignore",

.github/config/nodejs-prod.jsonc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
{
1818
"package-file": [ "package.json" ],
19-
"setup-file": "setup.json",
2019
"ignore": [
2120
".eslintignore",
2221
".eslintrc.json",

.github/workflows/ci-dev.yaml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ jobs:
3131
runs-on: ubuntu-latest
3232
timeout-minutes: 2
3333
outputs:
34-
nodejs: ${{ steps.nodejs.outputs.packages }}
34+
nodejs-paths: ${{ steps.nodejs.outputs.paths }}
35+
nodejs-setups: ${{ steps.nodejs.outputs.setups }}
3536
steps:
3637
- uses: actions/checkout@v4
3738
with:
@@ -45,37 +46,40 @@ jobs:
4546
run: git --no-pager diff --name-only HEAD origin/main | tee diffs.txt
4647
- name: Find Node.js affected packages
4748
id: nodejs
48-
run: echo "packages=$(./tools affected .github/config/nodejs-dev.jsonc diffs.txt)" | tee -a $GITHUB_OUTPUT
49+
run: |
50+
echo "paths=$(./tools affected .github/config/nodejs-dev.jsonc diffs.txt paths.txt)" >> $GITHUB_OUTPUT
51+
cat paths.txt
52+
echo "setups=$(./tools setups .github/config/nodejs-dev.jsonc paths.txt)" >> $GITHUB_OUTPUT
4953
5054
nodejs-test:
51-
name: Node.js ${{ matrix.package.setup.nodejs_version }} test
55+
name: Node.js test
5256
needs: affected
5357
runs-on: ubuntu-latest
5458
permissions:
5559
id-token: write # needed for google-github-actions/auth
5660
strategy:
5761
fail-fast: false
5862
matrix:
59-
package: ${{ fromJson(github.event_name == 'pull_request' && needs.affected.outputs.nodejs || '[]') }}
63+
path: ${{ fromJson(github.event_name == 'pull_request' && needs.affected.outputs.nodejs-paths || '[]') }}
6064
steps:
6165
- uses: actions/checkout@v4
6266
with:
6367
ref: ${{ github.event.pull_request.head.sha }}
6468
- uses: actions/setup-node@v4
6569
with:
66-
node-version: ${{ matrix.package.setup.nodejs_version }}
70+
node-version: ${{ needs.affected.outputs.nodejs-setups[matrix.path].node-version }}
6771
- uses: google-github-actions/auth@v2
6872
with:
6973
project_id: long-door-651
7074
workload_identity_provider: projects/1046198160504/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider
7175
service_account: [email protected]
7276
access_token_lifetime: 600s # 10 minutes
73-
- if: matrix.package.secrets != '[]'
77+
- if: needs.affected.outputs.nodejs-setups[matrix.path].secrets != null
7478
uses: google-github-actions/get-secretmanager-secrets@v2
7579
with:
76-
secrets: ${{ join(matrix.package.secrets) }}
80+
secrets: ${{ join(needs.affected.outputs.nodejs-setups[matrix.path].secrets) }}
7781
export_to_environment: true
78-
- name: Test ${{ matrix.package.path }}
79-
run: make test dir=${{ matrix.package.path }}
82+
- name: 🛠️ Test ${{ matrix.path }}
83+
run: make test dir=${{ matrix.path }}
8084
env:
8185
GOOGLE_SAMPLES_PROJECT: long-door-651
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"nodejs_version": 18,
2+
"node-version": 18,
33
"secrets": [
44
"CAIP_PROJECT_ID:nodejs-docs-samples-tests/nodejs-docs-samples-ai-platform-caip-project-id",
55
"LOCATION:nodejs-docs-samples-tests/nodejs-docs-samples-ai-platform-location",

0 commit comments

Comments
 (0)