From 67645456cd7b3c142d80352c2048364415c87a07 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Tue, 4 Mar 2025 14:31:24 -0800 Subject: [PATCH 01/17] custard integration --- .github/config/golang-dev.jsonc | 57 +++++++ .github/custard-setup/action.yaml | 70 ++++++++ .github/scripts/cmd/vars.js | 41 +++++ .github/scripts/package.json | 14 ++ .github/scripts/setup-vars.js | 84 ++++++++++ .github/scripts/setup-vars.test.js | 202 ++++++++++++++++++++++++ .github/workflows/custard-affected.yaml | 65 ++++++++ .github/workflows/custard-ci-dev.yaml | 55 +++++++ 8 files changed, 588 insertions(+) create mode 100644 .github/config/golang-dev.jsonc create mode 100644 .github/custard-setup/action.yaml create mode 100644 .github/scripts/cmd/vars.js create mode 100644 .github/scripts/package.json create mode 100644 .github/scripts/setup-vars.js create mode 100644 .github/scripts/setup-vars.test.js create mode 100644 .github/workflows/custard-affected.yaml create mode 100644 .github/workflows/custard-ci-dev.yaml diff --git a/.github/config/golang-dev.jsonc b/.github/config/golang-dev.jsonc new file mode 100644 index 0000000000..9f9e4d00eb --- /dev/null +++ b/.github/config/golang-dev.jsonc @@ -0,0 +1,57 @@ +/* + Copyright 2025 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-file": [ "go.mod" ], + "ci-setup-filename": "ci-setup.json", + + // If these change, please update the .github/config/README.md too! + "ci-setup-defaults": { + "env": { }, + "secrets": { }, + "go-version-earliest": 1.23, + "go-version-latest": 1.24, + "timeout-minutes": 10 + }, + + "ignore": [ + ".github/blunderbuss.yaml", + ".github/CODEOWNERS", + // TODO: do not ignore .github/config once everything is in prod + ".github/config/", // prevent changes to exclusions from running all tests + ".github/flakybot.yaml", + ".github/header-checker-lint.yaml", + ".github/ISSUE_TEMPLATE/", + ".github/PULL_REQUEST_TEMPLATE.md", + ".github/renovate.json", + ".github/scripts/", + ".github/snippet-bot.yml", + ".gitignore", + "badfiles_test.go", + "cloud-samples-tools", // checked out by GH action in ci-*.yml + "CODE_OF_CONDUCT.md", + "CONTRIBUTING.md", + "LICENSE", + "Makefile", + "README.md", + "regiontag_test.go", + "SECURITY.md", + "Taskfile.yaml" + ], + + "exclude-packages": [ + ] +} diff --git a/.github/custard-setup/action.yaml b/.github/custard-setup/action.yaml new file mode 100644 index 0000000000..34648bc631 --- /dev/null +++ b/.github/custard-setup/action.yaml @@ -0,0 +1,70 @@ +# 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 +# +# http://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. + +name: Custard setup +description: Sets up the testing environment. + +inputs: + path: + description: Path of the package to run. + required: true + affected: + description: The job for affected packages. + required: true + project_id: + description: The Google Cloud project ID. + required: true + workload_identity_provider: + description: The Google Cloud workload identity provider. + required: true + service_account: + description: The Google Cloud service account to use for credentials. + required: true + +outputs: + ci-setup: + description: The CI setup configuration for the given path. + value: ${{ inputs.affected.outputs.ci-setups[inputs.path] }} + +runs: + using: composite + steps: + - uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2 + id: auth + with: + project_id: ${{ inputs.project_id }} + workload_identity_provider: ${{ inputs.workload_identity_provider }} + service_account: ${{ inputs.service_account }} + access_token_lifetime: 600s # 10 minutes + token_format: id_token + id_token_audience: https://action.test/ # service must have this custom audience + id_token_include_email: true + - name: Export environment variables + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7 + id: vars + with: + script: | + const { default: setupVars } = await import('${{ github.workspace }}/.github/scripts/setup-vars.js'); + return await setupVars({ + core, + projectId: '${{ inputs.project_id }}', + setup: ${{ toJson(inputs.affected.outputs.ci-setups[inputs.path]) }}, + serviceAccount: '${{ inputs.service_account }}', + idToken: '${{ steps.auth.outputs.id_token }}', + }) + - uses: google-github-actions/get-secretmanager-secrets@e5bb06c2ca53b244f978d33348d18317a7f263ce # v2 + if: ${{ fromJson(steps.vars.outputs.result).secrets }} + with: + secrets: ${{ fromJson(steps.vars.outputs.result).secrets }} + export_to_environment: true diff --git a/.github/scripts/cmd/vars.js b/.github/scripts/cmd/vars.js new file mode 100644 index 0000000000..28bdf2bbd4 --- /dev/null +++ b/.github/scripts/cmd/vars.js @@ -0,0 +1,41 @@ +/* + Copyright 2025 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. + */ + +import fs from "node:fs"; +import path from "node:path"; +import setupVars from "../setup-vars.js"; + +const project_id = process.env.PROJECT_ID; +if (!project_id) { + console.error( + "Please set the PROJECT_ID environment variable to your Google Cloud project." + ); + process.exit(1); +} + +const core = { + exportVariable: (_key, _value) => null, +}; + +const setupFile = process.argv[2]; +if (!setupFile) { + console.error("Please provide the path to a setup file."); + process.exit(1); +} +const data = fs.readFileSync(path.join("..", "..", setupFile), "utf8"); +const setup = JSON.parse(data); + +setupVars({ project_id, core, setup }); diff --git a/.github/scripts/package.json b/.github/scripts/package.json new file mode 100644 index 0000000000..b90f45fda5 --- /dev/null +++ b/.github/scripts/package.json @@ -0,0 +1,14 @@ +{ + "name": "custard", + "version": "1.0.0", + "type": "module", + "license": "Apache-2.0", + "private": true, + "scripts": { + "vars": "node cmd/vars.js", + "test": "mocha -p -j 2 **/*.test.js" + }, + "devDependencies": { + "mocha": "^11.1.0" + } +} diff --git a/.github/scripts/setup-vars.js b/.github/scripts/setup-vars.js new file mode 100644 index 0000000000..faa06e0e98 --- /dev/null +++ b/.github/scripts/setup-vars.js @@ -0,0 +1,84 @@ +/* + Copyright 2025 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. + */ + +export default function setupVars( + { projectId, core, setup, serviceAccount, idToken }, + runId = null +) { + // Define automatic variables plus custom variables. + const vars = { + PROJECT_ID: projectId, + RUN_ID: runId || uniqueId(), + SERVICE_ACCOUNT: serviceAccount, + ...(setup.env || {}), + }; + + // Apply variable interpolation. + const env = Object.fromEntries( + Object.keys(vars).map((key) => [key, substituteVars(vars[key], vars)]) + ); + + // Export environment variables. + console.log("env:"); + for (const key in env) { + const value = env[key]; + console.log(` ${key}: ${value}`); + core.exportVariable(key, value); + } + + // Show exported secrets, for logging purposes. + // TODO: We might want to fetch the secrets here and export them directly. + // https://cloud.google.com/secret-manager/docs/create-secret-quickstart#secretmanager-quickstart-nodejs + console.log("secrets:"); + for (const key in setup.secrets || {}) { + // This is the Google Cloud Secret Manager secret ID. + // NOT the secret value, so it's ok to show. + console.log(` ${key}: ${setup.secrets[key]}`); + } + + // Set global secret for the Service Account identity token + // Use in place of 'gcloud auth print-identity-token' or auth.getIdTokenClient + // usage: curl -H 'Bearer: $ID_TOKEN' https:// + core.exportVariable("ID_TOKEN", idToken); + core.setSecret(idToken); + // For logging, show the source of the ID_TOKEN + console.log(` ID_TOKEN: steps.auth.outputs.id_token (from GitHub Action)`); + + // Return env and secrets to use for further steps. + return { + env: env, + // Transform secrets into the format needed for the GHA secret manager step. + secrets: Object.keys(setup.secrets || {}) + .map((key) => `${key}:${setup.secrets[key]}`) + .join("\n"), + }; +} + +export function substituteVars(value, env) { + for (const key in env) { + let re = new RegExp(`\\$(${key}\\b|\\{\\s*${key}\\s*\\})`, "g"); + value = value.replaceAll(re, env[key]); + } + return value; +} + +export function uniqueId(length = 6) { + const min = 2 ** 32; + const max = 2 ** 64; + return Math.floor(Math.random() * max + min) + .toString(36) + .slice(0, length); +} diff --git a/.github/scripts/setup-vars.test.js b/.github/scripts/setup-vars.test.js new file mode 100644 index 0000000000..e3417d5005 --- /dev/null +++ b/.github/scripts/setup-vars.test.js @@ -0,0 +1,202 @@ +/* + Copyright 2025 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. + */ + +import { deepStrictEqual } from "assert"; +import setupVars from "./setup-vars.js"; +import { substituteVars, uniqueId } from "./setup-vars.js"; + +const projectId = "my-test-project"; +const serviceAccount = "my-sa@my-project.iam.gserviceaccount.com"; +const core = { + exportVariable: (_key, _value) => null, + setSecret: (_key) => null, +}; + +const autovars = { + PROJECT_ID: projectId, + RUN_ID: "run-id", + SERVICE_ACCOUNT: serviceAccount, +}; + +describe("setupVars", () => { + describe("env", () => { + it("empty", () => { + const setup = {}; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = autovars; + deepStrictEqual(vars.env, expected); + }); + + it("zero vars", () => { + const setup = { env: {} }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = autovars; + deepStrictEqual(vars.env, expected); + }); + + it("one var", () => { + const setup = { env: { A: "x" } }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = { ...autovars, A: "x" }; + deepStrictEqual(vars.env, expected); + }); + + it("three vars", () => { + const setup = { env: { A: "x", B: "y", C: "z" } }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = { ...autovars, A: "x", B: "y", C: "z" }; + deepStrictEqual(vars.env, expected); + }); + + it("should override automatic variables", () => { + const setup = { + env: { PROJECT_ID: "custom-value", SERVICE_ACCOUNT: "baz@foo.com" }, + }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = { + PROJECT_ID: "custom-value", + RUN_ID: "run-id", + SERVICE_ACCOUNT: "baz@foo.com", + }; + deepStrictEqual(vars.env, expected); + }); + + it("should interpolate variables", () => { + const setup = { env: { A: "x", B: "y", C: "$A/${B}" } }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = { ...autovars, A: "x", B: "y", C: "x/y" }; + deepStrictEqual(vars.env, expected); + }); + + it("should not interpolate secrets", () => { + const setup = { + env: { C: "$x/$y" }, + secrets: { A: "x", B: "y" }, + }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = { ...autovars, C: "$x/$y" }; + deepStrictEqual(vars.env, expected); + }); + }); + + describe("secrets", () => { + it("zero secrets", () => { + const setup = { secrets: {} }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + deepStrictEqual(vars.secrets, ""); + }); + + it("one secret", () => { + const setup = { secrets: { A: "x" } }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = "A:x"; + deepStrictEqual(vars.secrets, expected); + }); + + it("three secrets", () => { + const setup = { secrets: { A: "x", B: "y", C: "z" } }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = "A:x\nB:y\nC:z"; + deepStrictEqual(vars.secrets, expected); + }); + + it("should not interpolate variables", () => { + const setup = { + env: { A: "x", B: "y" }, + secrets: { C: "$A/$B" }, + }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = "C:$A/$B"; + deepStrictEqual(vars.secrets, expected); + }); + + it("should not interpolate secrets", () => { + const setup = { secrets: { A: "x", B: "y", C: "$A/$B" } }; + const vars = setupVars( + { projectId, core, setup, serviceAccount }, + "run-id" + ); + const expected = "A:x\nB:y\nC:$A/$B"; + deepStrictEqual(vars.secrets, expected); + }); + }); +}); + +describe("substituteVars", () => { + it("should interpolate $VAR", () => { + const got = substituteVars("$A-$B", { A: "x", B: "y" }); + const expected = "x-y"; + deepStrictEqual(got, expected); + }); + + it("should interpolate ${VAR}", () => { + const got = substituteVars("${A}-${B}", { A: "x", B: "y" }); + const expected = "x-y"; + deepStrictEqual(got, expected); + }); + + it("should interpolate ${ VAR }", () => { + const got = substituteVars("${ A }-${ \tB\t }", { A: "x", B: "y" }); + const expected = "x-y"; + deepStrictEqual(got, expected); + }); + + it("should not interpolate on non-word boundary", () => { + const got = substituteVars("$Ab", { A: "x" }); + const expected = "$Ab"; + deepStrictEqual(got, expected); + }); +}); + +describe("uniqueId", () => { + it("should match length", () => { + const n = 6; + deepStrictEqual(uniqueId(n).length, n); + }); +}); diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml new file mode 100644 index 0000000000..4dff23a9c7 --- /dev/null +++ b/.github/workflows/custard-affected.yaml @@ -0,0 +1,65 @@ +# 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 +# +# http://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. + +on: + workflow_call: + inputs: + go-version: + description: Go version to use to build the custard tools. + default: ^1.22.0 + type: string + timeout-minutes: + description: Timeout to find affected packages. + default: 2 + type: number + outputs: + paths: + description: The affected paths as a JSON list. + value: ${{ jobs.affected.outputs.paths }} + ci-setups: + description: The CI setup configurations for the affected packages. + value: ${{ jobs.affected.outputs.ci-setups }} + +jobs: + affected: + name: Finding affected tests + runs-on: ubuntu-latest + timeout-minutes: ${{ inputs.timeout-minutes }} + outputs: + paths: ${{ fromJson(steps.custard.outputs.paths) }} + ci-setups: ${{ fromJson(steps.custard.outputs.ci-setups) }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 # fetch the entire branch history to find diffs + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + repository: GoogleCloudPlatform/cloud-samples-tools + ref: v0.2.1 + path: cloud-samples-tools + - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5 + with: + go-version: ${{ inputs.go-version }} + - name: Build Custard (from cloud-samples-tools) + run: go build -o ${{ github.workspace }} -v ./... + working-directory: cloud-samples-tools/custard + - name: Get diffs + run: git --no-pager diff --name-only HEAD origin/main | tee diffs.txt + - name: Find affected packages + id: custard + run: | + set -e + echo "paths=$(./cloud-samples-tools/bin/custard affected .github/config/nodejs-dev.jsonc diffs.txt paths.txt)" >> $GITHUB_OUTPUT + cat paths.txt # show the affected paths in the logs + echo "ci-setups=$(./cloud-samples-tools/bin/custard setup-files .github/config/nodejs-dev.jsonc paths.txt)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/custard-ci-dev.yaml b/.github/workflows/custard-ci-dev.yaml new file mode 100644 index 0000000000..5779ad61a1 --- /dev/null +++ b/.github/workflows/custard-ci-dev.yaml @@ -0,0 +1,55 @@ +# 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 +# +# http://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. + +name: custard CI (dev) +on: + push: + branches: + - main + pull_request: + +jobs: + affected: + uses: ./.github/workflows/custard-affected.yaml + + test-latest: + name: Test latest + needs: affected + runs-on: ubuntu-latest + timeout-minutes: 120 # 2 hours hard limit + permissions: + id-token: write # needed for google-github-actions/auth + strategy: + fail-fast: false + matrix: + path: ${{ needs.affected.outputs.paths }} + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - id: custard + uses: ./.github/custard-setup + with: + path: ${{ matrix.path }} + affected: ${{ needs.affected }} + project_id: golang-samples-tests + workload_identity_provider: TODO + service_account: kokoro-golang-samples-tests@golang-samples-tests.iam.gserviceaccount.com + - uses: actions/setup-go@v5 + with: + go-version: ${{ steps.custard.outputs.ci-setup.go-version-latest }} + - name: Run tests for ${{ matrix.path }} + run: | + timeout ${{ steps.custard.outputs.ci-setup.timeout-minutes }}m \ + make test dir=${{ matrix.path }} From 05205936870712d372932ba50128b7cddaa23162 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Tue, 4 Mar 2025 14:39:12 -0800 Subject: [PATCH 02/17] add debugging info --- .github/workflows/custard-affected.yaml | 17 +++++++++++------ .github/workflows/custard-ci-dev.yaml | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index 4dff23a9c7..ccf3d1ee55 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -40,19 +40,24 @@ jobs: paths: ${{ fromJson(steps.custard.outputs.paths) }} ci-setups: ${{ fromJson(steps.custard.outputs.ci-setups) }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: fetch-depth: 0 # fetch the entire branch history to find diffs - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - name: Setup Go + uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5 + with: + go-version: ${{ inputs.go-version }} + - name: Fetch Custard + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: repository: GoogleCloudPlatform/cloud-samples-tools ref: v0.2.1 path: cloud-samples-tools - - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5 - with: - go-version: ${{ inputs.go-version }} - name: Build Custard (from cloud-samples-tools) - run: go build -o ${{ github.workspace }} -v ./... + run: | + ls + go build -o ${{ github.workspace }} -v ./... working-directory: cloud-samples-tools/custard - name: Get diffs run: git --no-pager diff --name-only HEAD origin/main | tee diffs.txt diff --git a/.github/workflows/custard-ci-dev.yaml b/.github/workflows/custard-ci-dev.yaml index 5779ad61a1..523ec1f02a 100644 --- a/.github/workflows/custard-ci-dev.yaml +++ b/.github/workflows/custard-ci-dev.yaml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -name: custard CI (dev) +name: Custard CI (dev) on: push: branches: From fe159ab673c64868cf16f73b0d9d2f6d16017b2c Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Tue, 4 Mar 2025 14:49:17 -0800 Subject: [PATCH 03/17] fix build command --- .github/workflows/custard-affected.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index ccf3d1ee55..84533a42c2 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -55,9 +55,7 @@ jobs: ref: v0.2.1 path: cloud-samples-tools - name: Build Custard (from cloud-samples-tools) - run: | - ls - go build -o ${{ github.workspace }} -v ./... + run: go build -o ${{ github.workspace }}/custard -v ./cmd/custard working-directory: cloud-samples-tools/custard - name: Get diffs run: git --no-pager diff --name-only HEAD origin/main | tee diffs.txt From d3143929ee098cb1817c7f716c16845716dfbaf1 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Tue, 4 Mar 2025 15:12:31 -0800 Subject: [PATCH 04/17] install custard directly --- .github/workflows/custard-affected.yaml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index 84533a42c2..4b6442f612 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -48,15 +48,8 @@ jobs: uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5 with: go-version: ${{ inputs.go-version }} - - name: Fetch Custard - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - repository: GoogleCloudPlatform/cloud-samples-tools - ref: v0.2.1 - path: cloud-samples-tools - - name: Build Custard (from cloud-samples-tools) - run: go build -o ${{ github.workspace }}/custard -v ./cmd/custard - working-directory: cloud-samples-tools/custard + - name: Install Custard from cloud-samples-tools + run: go install github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard@v0.2.1 - name: Get diffs run: git --no-pager diff --name-only HEAD origin/main | tee diffs.txt - name: Find affected packages From 72c56a5b1806869bf58e0f15491ab8af742d5fdc Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Tue, 4 Mar 2025 15:13:56 -0800 Subject: [PATCH 05/17] remove version tag --- .github/workflows/custard-affected.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index 4b6442f612..fbf43b99f2 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -49,7 +49,7 @@ jobs: with: go-version: ${{ inputs.go-version }} - name: Install Custard from cloud-samples-tools - run: go install github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard@v0.2.1 + run: go install github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard - name: Get diffs run: git --no-pager diff --name-only HEAD origin/main | tee diffs.txt - name: Find affected packages From bf4f62419284ba683ed3c9942a16100b5364e542 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Tue, 4 Mar 2025 15:17:00 -0800 Subject: [PATCH 06/17] pass specific path --- .github/workflows/custard-affected.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index fbf43b99f2..911c6ecab1 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -49,7 +49,7 @@ jobs: with: go-version: ${{ inputs.go-version }} - name: Install Custard from cloud-samples-tools - run: go install github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard + run: go install github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard/cmd/custard - name: Get diffs run: git --no-pager diff --name-only HEAD origin/main | tee diffs.txt - name: Find affected packages From 6c09ffba2c1dbcdf215a9b47ee2f758c67ede9cf Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Tue, 4 Mar 2025 15:17:59 -0800 Subject: [PATCH 07/17] go get first --- .github/workflows/custard-affected.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index 911c6ecab1..a14dfd1180 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -49,7 +49,9 @@ jobs: with: go-version: ${{ inputs.go-version }} - name: Install Custard from cloud-samples-tools - run: go install github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard/cmd/custard + run: | + go get github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard/cmd/custard + go install github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard/cmd/custard - name: Get diffs run: git --no-pager diff --name-only HEAD origin/main | tee diffs.txt - name: Find affected packages From 7c652a8b88f25e1ffa4ce8cbb04afb98d61bd002 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 10:45:14 -0800 Subject: [PATCH 08/17] build custard on separate directory --- .github/workflows/custard-affected.yaml | 28 +++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index a14dfd1180..e73dbe9ad2 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -40,24 +40,30 @@ jobs: paths: ${{ fromJson(steps.custard.outputs.paths) }} ci-setups: ${{ fromJson(steps.custard.outputs.ci-setups) }} steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 # fetch the entire branch history to find diffs - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5 with: go-version: ${{ inputs.go-version }} - - name: Install Custard from cloud-samples-tools - run: | - go get github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard/cmd/custard - go install github.com/GoogleCloudPlatform/golang-samples/cloud-samples-tools/custard/cmd/custard - - name: Get diffs + - name: Fetch Custard from cloud-samples-tools + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + repository: GoogleCloudPlatform/cloud-samples-tools + ref: v0.2.1 + path: ../cloud-samples-tools + - name: Install Custard + run: go install ./cmd/custard + working-directory: ../cloud-samples-tools/custard + - name: Checkout the commit history + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + fetch-depth: 0 # fetch the entire branch history to find diffs + - name: Get diffs from main and the PR run: git --no-pager diff --name-only HEAD origin/main | tee diffs.txt - name: Find affected packages id: custard run: | set -e - echo "paths=$(./cloud-samples-tools/bin/custard affected .github/config/nodejs-dev.jsonc diffs.txt paths.txt)" >> $GITHUB_OUTPUT + echo "paths=$(custard this is a test that should fail)" >> $GITHUB_OUTPUT + echo "paths=$(custard affected .github/config/nodejs-dev.jsonc diffs.txt paths.txt)" >> $GITHUB_OUTPUT cat paths.txt # show the affected paths in the logs - echo "ci-setups=$(./cloud-samples-tools/bin/custard setup-files .github/config/nodejs-dev.jsonc paths.txt)" >> $GITHUB_OUTPUT + echo "ci-setups=$(custard setup-files .github/config/nodejs-dev.jsonc paths.txt)" >> $GITHUB_OUTPUT From b0b807a41c7898a0a9401a53b0232af59008d6ab Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 11:08:47 -0800 Subject: [PATCH 09/17] build custard, clean, then get diffs --- .github/workflows/custard-affected.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index e73dbe9ad2..be8669986f 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -49,10 +49,12 @@ jobs: with: repository: GoogleCloudPlatform/cloud-samples-tools ref: v0.2.1 - path: ../cloud-samples-tools + path: cloud-samples-tools - name: Install Custard run: go install ./cmd/custard - working-directory: ../cloud-samples-tools/custard + working-directory: cloud-samples-tools/custard + - name: Clean up the workspace + run: rm -rf cloud-samples-tools - name: Checkout the commit history uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: From 10f734b1513ca99d13221151cef97e1bca742c70 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 11:10:59 -0800 Subject: [PATCH 10/17] test without -e --- .github/workflows/custard-affected.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index be8669986f..8b1ba184fe 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -40,6 +40,7 @@ jobs: paths: ${{ fromJson(steps.custard.outputs.paths) }} ci-setups: ${{ fromJson(steps.custard.outputs.ci-setups) }} steps: + # Install the Custard tools. - name: Setup Go uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5 with: @@ -55,6 +56,8 @@ jobs: working-directory: cloud-samples-tools/custard - name: Clean up the workspace run: rm -rf cloud-samples-tools + + # Find the affected packages. - name: Checkout the commit history uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: @@ -64,7 +67,6 @@ jobs: - name: Find affected packages id: custard run: | - set -e echo "paths=$(custard this is a test that should fail)" >> $GITHUB_OUTPUT echo "paths=$(custard affected .github/config/nodejs-dev.jsonc diffs.txt paths.txt)" >> $GITHUB_OUTPUT cat paths.txt # show the affected paths in the logs From 70b62341028b2c5eefc4b45a6f48e703c68acad6 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 11:12:04 -0800 Subject: [PATCH 11/17] fix affected --- .github/workflows/custard-affected.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index 8b1ba184fe..2adc60d4b9 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -67,7 +67,6 @@ jobs: - name: Find affected packages id: custard run: | - echo "paths=$(custard this is a test that should fail)" >> $GITHUB_OUTPUT echo "paths=$(custard affected .github/config/nodejs-dev.jsonc diffs.txt paths.txt)" >> $GITHUB_OUTPUT - cat paths.txt # show the affected paths in the logs + cat paths.txt echo "ci-setups=$(custard setup-files .github/config/nodejs-dev.jsonc paths.txt)" >> $GITHUB_OUTPUT From 6279cee4275f1541bd38733394464df1ae28f08e Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 11:15:39 -0800 Subject: [PATCH 12/17] pass the config file as input --- .github/workflows/custard-affected.yaml | 8 ++++++-- .github/workflows/custard-ci-dev.yaml | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index 2adc60d4b9..574d5b1179 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -15,6 +15,10 @@ on: workflow_call: inputs: + config-file: + description: Path to the 🍮 custard config file. + required: true + type: string go-version: description: Go version to use to build the custard tools. default: ^1.22.0 @@ -67,6 +71,6 @@ jobs: - name: Find affected packages id: custard run: | - echo "paths=$(custard affected .github/config/nodejs-dev.jsonc diffs.txt paths.txt)" >> $GITHUB_OUTPUT + echo "paths=$(custard affected ${{ inputs.config-file }} diffs.txt paths.txt)" >> $GITHUB_OUTPUT cat paths.txt - echo "ci-setups=$(custard setup-files .github/config/nodejs-dev.jsonc paths.txt)" >> $GITHUB_OUTPUT + echo "ci-setups=$(custard setup-files ${{ inputs.config-file }} paths.txt)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/custard-ci-dev.yaml b/.github/workflows/custard-ci-dev.yaml index 523ec1f02a..d126fb5631 100644 --- a/.github/workflows/custard-ci-dev.yaml +++ b/.github/workflows/custard-ci-dev.yaml @@ -22,6 +22,8 @@ on: jobs: affected: uses: ./.github/workflows/custard-affected.yaml + with: + config-file: .github/config/golang-dev.jsonc test-latest: name: Test latest From e14bddabbc19f32f6553f3d5245b99450562fc55 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 11:17:06 -0800 Subject: [PATCH 13/17] better step names --- .github/workflows/custard-ci-dev.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/custard-ci-dev.yaml b/.github/workflows/custard-ci-dev.yaml index d126fb5631..701a0cefc5 100644 --- a/.github/workflows/custard-ci-dev.yaml +++ b/.github/workflows/custard-ci-dev.yaml @@ -37,10 +37,12 @@ jobs: matrix: path: ${{ needs.affected.outputs.paths }} steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: ref: ${{ github.event.pull_request.head.sha }} - - id: custard + - name: Setup Custard testing environment + id: custard uses: ./.github/custard-setup with: path: ${{ matrix.path }} @@ -48,7 +50,8 @@ jobs: project_id: golang-samples-tests workload_identity_provider: TODO service_account: kokoro-golang-samples-tests@golang-samples-tests.iam.gserviceaccount.com - - uses: actions/setup-go@v5 + - name: Setup Go + uses: actions/setup-go@v5 with: go-version: ${{ steps.custard.outputs.ci-setup.go-version-latest }} - name: Run tests for ${{ matrix.path }} From 890c8c16842848edfc39d4c89324a27e061628d4 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 11:22:58 -0800 Subject: [PATCH 14/17] do not deserialize on reusable output --- .github/workflows/custard-affected.yaml | 5 +++-- .github/workflows/custard-ci-dev.yaml | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/custard-affected.yaml b/.github/workflows/custard-affected.yaml index 574d5b1179..e1c898e806 100644 --- a/.github/workflows/custard-affected.yaml +++ b/.github/workflows/custard-affected.yaml @@ -27,6 +27,7 @@ on: description: Timeout to find affected packages. default: 2 type: number + outputs: paths: description: The affected paths as a JSON list. @@ -41,8 +42,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: ${{ inputs.timeout-minutes }} outputs: - paths: ${{ fromJson(steps.custard.outputs.paths) }} - ci-setups: ${{ fromJson(steps.custard.outputs.ci-setups) }} + paths: ${{ steps.custard.outputs.paths }} + ci-setups: ${{ steps.custard.outputs.ci-setups }} steps: # Install the Custard tools. - name: Setup Go diff --git a/.github/workflows/custard-ci-dev.yaml b/.github/workflows/custard-ci-dev.yaml index 701a0cefc5..f2b2477791 100644 --- a/.github/workflows/custard-ci-dev.yaml +++ b/.github/workflows/custard-ci-dev.yaml @@ -53,8 +53,8 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: ${{ steps.custard.outputs.ci-setup.go-version-latest }} + go-version: ${{ fromJson(steps.custard.outputs.ci-setup).go-version-latest }} - name: Run tests for ${{ matrix.path }} run: | - timeout ${{ steps.custard.outputs.ci-setup.timeout-minutes }}m \ + timeout ${{ fromJson(steps.custard.outputs.ci-setup).timeout-minutes }}m \ make test dir=${{ matrix.path }} From 29ff4cb7148a78f50df8f837810350fc94ad5ab7 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 11:26:48 -0800 Subject: [PATCH 15/17] fix more serialization stuff --- .github/custard-setup/action.yaml | 4 ++-- .github/workflows/custard-ci-dev.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/custard-setup/action.yaml b/.github/custard-setup/action.yaml index 34648bc631..661771219f 100644 --- a/.github/custard-setup/action.yaml +++ b/.github/custard-setup/action.yaml @@ -35,7 +35,7 @@ inputs: outputs: ci-setup: description: The CI setup configuration for the given path. - value: ${{ inputs.affected.outputs.ci-setups[inputs.path] }} + value: ${{ fromJson(inputs.affected).outputs.ci-setups[inputs.path] }} runs: using: composite @@ -59,7 +59,7 @@ runs: return await setupVars({ core, projectId: '${{ inputs.project_id }}', - setup: ${{ toJson(inputs.affected.outputs.ci-setups[inputs.path]) }}, + setup: ${{ toJson(fromJson(inputs.affected).outputs.ci-setups[inputs.path]) }}, serviceAccount: '${{ inputs.service_account }}', idToken: '${{ steps.auth.outputs.id_token }}', }) diff --git a/.github/workflows/custard-ci-dev.yaml b/.github/workflows/custard-ci-dev.yaml index f2b2477791..bed9e60327 100644 --- a/.github/workflows/custard-ci-dev.yaml +++ b/.github/workflows/custard-ci-dev.yaml @@ -35,7 +35,7 @@ jobs: strategy: fail-fast: false matrix: - path: ${{ needs.affected.outputs.paths }} + path: ${{ fromJson(needs.affected.outputs.paths) }} steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -53,8 +53,8 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: ${{ fromJson(steps.custard.outputs.ci-setup).go-version-latest }} + go-version: ${{ steps.custard.outputs.ci-setup.go-version-latest }} - name: Run tests for ${{ matrix.path }} run: | - timeout ${{ fromJson(steps.custard.outputs.ci-setup).timeout-minutes }}m \ + timeout ${{ steps.custard.outputs.ci-setup.timeout-minutes }}m \ make test dir=${{ matrix.path }} From 46283f355e5a8170c3deb848ac423d5be232b102 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 11:31:28 -0800 Subject: [PATCH 16/17] more serialization fixes --- .github/custard-setup/action.yaml | 8 ++++---- .github/workflows/custard-ci-dev.yaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/custard-setup/action.yaml b/.github/custard-setup/action.yaml index 661771219f..797abb7cec 100644 --- a/.github/custard-setup/action.yaml +++ b/.github/custard-setup/action.yaml @@ -19,8 +19,8 @@ inputs: path: description: Path of the package to run. required: true - affected: - description: The job for affected packages. + ci-setups: + description: The CI setups for the affected packages in JSON. required: true project_id: description: The Google Cloud project ID. @@ -35,7 +35,7 @@ inputs: outputs: ci-setup: description: The CI setup configuration for the given path. - value: ${{ fromJson(inputs.affected).outputs.ci-setups[inputs.path] }} + value: ${{ fromJson(inputs.ci-setups)[inputs.path] }} runs: using: composite @@ -59,7 +59,7 @@ runs: return await setupVars({ core, projectId: '${{ inputs.project_id }}', - setup: ${{ toJson(fromJson(inputs.affected).outputs.ci-setups[inputs.path]) }}, + setup: ${{ toJson(fromJson(inputs.ci-setups)[inputs.path]) }}, serviceAccount: '${{ inputs.service_account }}', idToken: '${{ steps.auth.outputs.id_token }}', }) diff --git a/.github/workflows/custard-ci-dev.yaml b/.github/workflows/custard-ci-dev.yaml index bed9e60327..ab91c696b5 100644 --- a/.github/workflows/custard-ci-dev.yaml +++ b/.github/workflows/custard-ci-dev.yaml @@ -46,7 +46,7 @@ jobs: uses: ./.github/custard-setup with: path: ${{ matrix.path }} - affected: ${{ needs.affected }} + ci-setups: ${{ toJson(needs.affected.outputs.ci-setups) }} project_id: golang-samples-tests workload_identity_provider: TODO service_account: kokoro-golang-samples-tests@golang-samples-tests.iam.gserviceaccount.com From fd8abcb85146d51312d697e3fdc276cfa02b7216 Mon Sep 17 00:00:00 2001 From: David Cavazos Date: Wed, 5 Mar 2025 11:38:13 -0800 Subject: [PATCH 17/17] decrease serialization payloads --- .github/custard-setup/action.yaml | 11 +++-------- .github/workflows/custard-ci-dev.yaml | 6 +++--- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/.github/custard-setup/action.yaml b/.github/custard-setup/action.yaml index 797abb7cec..d5643b3490 100644 --- a/.github/custard-setup/action.yaml +++ b/.github/custard-setup/action.yaml @@ -19,8 +19,8 @@ inputs: path: description: Path of the package to run. required: true - ci-setups: - description: The CI setups for the affected packages in JSON. + ci-setup: + description: The CI setup for the package path. required: true project_id: description: The Google Cloud project ID. @@ -32,11 +32,6 @@ inputs: description: The Google Cloud service account to use for credentials. required: true -outputs: - ci-setup: - description: The CI setup configuration for the given path. - value: ${{ fromJson(inputs.ci-setups)[inputs.path] }} - runs: using: composite steps: @@ -59,7 +54,7 @@ runs: return await setupVars({ core, projectId: '${{ inputs.project_id }}', - setup: ${{ toJson(fromJson(inputs.ci-setups)[inputs.path]) }}, + setup: ${{ inputs.ci-setup }}, serviceAccount: '${{ inputs.service_account }}', idToken: '${{ steps.auth.outputs.id_token }}', }) diff --git a/.github/workflows/custard-ci-dev.yaml b/.github/workflows/custard-ci-dev.yaml index ab91c696b5..a8d6b722f9 100644 --- a/.github/workflows/custard-ci-dev.yaml +++ b/.github/workflows/custard-ci-dev.yaml @@ -46,15 +46,15 @@ jobs: uses: ./.github/custard-setup with: path: ${{ matrix.path }} - ci-setups: ${{ toJson(needs.affected.outputs.ci-setups) }} + ci-setup: ${{ toJson(fromJson(needs.affected.outputs.ci-setups)[matrix.path]) }} project_id: golang-samples-tests workload_identity_provider: TODO service_account: kokoro-golang-samples-tests@golang-samples-tests.iam.gserviceaccount.com - name: Setup Go uses: actions/setup-go@v5 with: - go-version: ${{ steps.custard.outputs.ci-setup.go-version-latest }} + go-version: ${{ fromJson(needs.affected.outputs.ci-setups)[matrix.path].go-version-latest }} - name: Run tests for ${{ matrix.path }} run: | - timeout ${{ steps.custard.outputs.ci-setup.timeout-minutes }}m \ + timeout ${{ fromJson(needs.affected.outputs.ci-setups)[matrix.path].timeout-minutes }}m \ make test dir=${{ matrix.path }}