From 4b9e6a9a166a09670270d3d520bc25da41799e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 14:31:45 -0400 Subject: [PATCH 01/10] ci: replace upstream workflows with fork CI - ci.yml: lint, test, api-tests jobs; actions pinned by SHA; read-only token - drop leg100 release/charts jobs and docs deploy - dependabot: weekly github-actions updates Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/dependabot.yml | 12 +++ .github/workflows/build.yml | 154 ------------------------------------ .github/workflows/ci.yml | 91 +++++++++++++++++++++ .github/workflows/docs.yml | 31 -------- 4 files changed, 103 insertions(+), 185 deletions(-) create mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/docs.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..6f0c4f881 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + commit-message: + prefix: "chore(ci)" + groups: + github-actions: + patterns: + - "*" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 51da5e535..000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,154 +0,0 @@ -name: build -on: - push: - branches: - - master - tags: - - "v*.*.*" - pull_request: - branches: - - "*" -jobs: - build: - # You must use a Linux environment when using service containers or container jobs - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v6 - - name: Set up Go - uses: actions/setup-go@v6 - with: - go-version-file: "go.mod" - - name: Check no diff - run: make check-no-diff - - name: Lint check - run: | - make lint - make helm-lint - - name: Vet check - run: make vet - - name: Install e2e dependencies - run: make install-playwright-ubuntu - - name: Install tofu for provider mirror setup - uses: opentofu/setup-opentofu@v1 - - name: Install terraform for provider mirror setup - uses: hashicorp/setup-terraform@v3 - with: - terraform_wrapper: false - - name: Add hosts to /etc/hosts - run: | - # API tests create webhooks on github.com, and github.com mandates - # that the webhook endpoint cannot be 'localhost', so we create a host - # entry to dupe github - sudo echo "127.0.0.1 otf.local" | sudo tee -a /etc/hosts - - name: API tests - run: make go-tfe-tests - env: - # go-tfe tests require a valid github oauth token be set with which - # to create a webhook on a github repo - OAUTH_CLIENT_GITHUB_TOKEN: ${{ secrets.GO_TFE_OAUTH_CLIENT_GITHUB_TOKEN }} - GITHUB_POLICY_SET_IDENTIFIER: leg100/go-tfe-webhooks - - name: Setup provider mirror for integration tests - run: ./hack/setup_mirror.sh - - name: Create kind cluster for integration tests - uses: helm/kind-action@v1.13.0 - with: - cluster_name: kind - - name: Tests - env: - OTF_TEST_KUBE: true - run: make test - - name: Archive browser traces - if: always() - uses: actions/upload-artifact@v4 - with: - name: e2e-browser-traces - path: internal/integration/traces - release-please: - runs-on: ubuntu-latest - if: github.ref == 'refs/heads/master' - outputs: - release_created: ${{ steps.release-please.outputs.release_created }} - tag_name: ${{ steps.release-please.outputs.tag_name }} # e.g. v1.0.0 - version: ${{ steps.release-please.outputs.version }} # e.g. 1.0.0 - steps: - # Won't upgrade to v4 until they fix this bug: - # https://github.com/googleapis/release-please-action/issues/912 - - uses: google-github-actions/release-please-action@v3 - id: release-please - with: - release-type: go - command: manifest - release: - runs-on: ubuntu-latest - needs: [build, release-please] - if: needs.release-please.outputs.release_created - steps: - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - run: git fetch --force --tags - - uses: docker/login-action@v3 - with: - username: leg100 - password: ${{ secrets.DOCKERHUB_TOKEN }} - - uses: actions/setup-go@v6 - with: - go-version-file: "go.mod" - - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - uses: goreleaser/goreleaser-action@v6 - with: - args: release --clean --skip=sign,validate - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - charts: - # only upgrade charts for new releases - needs: [release-please, release] - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v6 - - name: Bump version - run: | - # set app version on all charts - yq -i ".appVersion = \"${{ needs.release-please.outputs.version }}\"" ./charts/otfd/Chart.yaml - yq -i ".appVersion = \"${{ needs.release-please.outputs.version }}\"" ./charts/otf-agent/Chart.yaml - # bump patch in chart version - CHART=otfd make bump-chart-version - CHART=otf-agent make bump-chart-version - # re-generate README.md to reflect updated version - eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" - brew install norwoodj/tap/helm-docs - make helm-docs - - name: Lint check - run: | - make helm-lint - - name: Commit new helm chart versions - run: | - # stage changes and commit - git config --global user.email "chart-bumper@otf.ninja" - git config --global user.name "Chart bumper" - git add -A - git commit -m "chore: bump helm charts with app version ${{ needs.release-please.outputs.tag_name }}" - git push origin master - - name: Checkout charts repo - uses: actions/checkout@v6 - with: - path: otf-charts - token: ${{ secrets.OTF_CHARTS_TOKEN }} - repository: leg100/otf-charts - - name: Copy charts to charts repo - run: | - cp -R ./charts ./otf-charts/ - - name: Commit changes to otf-charts repo - run: | - # switch to checkout of otf-charts repo - cd ./otf-charts - # stage changes and commit - git config --global user.email "chart-bumper@otf.ninja" - git config --global user.name "Chart bumper" - git add -A - git commit -m "New otf version ${{ needs.release-please.outputs.tag_name }}" - git push origin master diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..32a083552 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,91 @@ +name: ci +on: + push: + branches: + - master + pull_request: + branches: + - master +permissions: + contents: read +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} +jobs: + lint: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - name: Checkout + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 + with: + persist-credentials: false + - name: Set up Go + uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 + with: + go-version-file: "go.mod" + - name: Check no diff + run: make check-no-diff + - name: Lint check + run: | + make lint + make helm-lint + - name: Vet check + run: make vet + test: + # You must use a Linux environment when using service containers or container jobs + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - name: Checkout + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 + with: + persist-credentials: false + - name: Set up Go + uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 + with: + go-version-file: "go.mod" + - name: Install e2e dependencies + run: make install-playwright-ubuntu + - name: Install tofu for provider mirror setup + uses: opentofu/setup-opentofu@9d84900f3238fab8cd84ce47d658d25dd008be2f # v1.0.8 + - name: Install terraform for provider mirror setup + uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 + with: + terraform_wrapper: false + - name: Setup provider mirror for integration tests + run: ./hack/setup_mirror.sh + - name: Create kind cluster for integration tests + uses: helm/kind-action@92086f6be054225fa813e0a4b13787fc9088faab # v1.13.0 + with: + cluster_name: kind + - name: Tests + env: + OTF_TEST_KUBE: true + run: make test + - name: Archive browser traces + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: e2e-browser-traces + path: internal/integration/traces + api-tests: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 + with: + persist-credentials: false + - name: Set up Go + uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 + with: + go-version-file: "go.mod" + - name: Add hosts to /etc/hosts + run: | + # otfd is configured with hostname otf.local + echo "127.0.0.1 otf.local" | sudo tee -a /etc/hosts + - name: API tests + # VCS tests are skipped: they need a github oauth token to create a + # webhook on a real github repo. + run: make go-tfe-tests diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index c5ee745e3..000000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: docs -on: - push: - branches: - - master -defaults: - run: - working-directory: ./docs -permissions: - contents: write -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Configure Git Credentials - run: | - git config user.name github-actions[bot] - git config user.email 41898282+github-actions[bot]@users.noreply.github.com - - uses: actions/setup-python@v5 - with: - python-version: 3.x - - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV - - uses: actions/cache@v4 - with: - key: mkdocs-material-${{ env.cache_id }} - path: .cache - restore-keys: | - mkdocs-material- - - run: pip install -r requirements.txt - - run: mkdocs gh-deploy --force From 2daaf0e356386789ee2657f5918e4cf7a69d4030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 14:33:00 -0400 Subject: [PATCH 02/10] ci: install tofu and kind from release binaries Their setup actions are not on the org allowed actions list. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/ci.yml | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 32a083552..7fe0346fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,8 +47,16 @@ jobs: go-version-file: "go.mod" - name: Install e2e dependencies run: make install-playwright-ubuntu + # tofu and kind are installed from release binaries: their setup actions + # are not on the org's allowed actions list. - name: Install tofu for provider mirror setup - uses: opentofu/setup-opentofu@9d84900f3238fab8cd84ce47d658d25dd008be2f # v1.0.8 + env: + TOFU_VERSION: 1.13.1 + TOFU_SHA256: 8ccbc6f8ee21d2827715f3c6e08a9b3e0209b1e62057c05067ef117e047c1a80 + run: | + curl -fsSLo /tmp/tofu.zip "https://github.com/opentofu/opentofu/releases/download/v${TOFU_VERSION}/tofu_${TOFU_VERSION}_linux_amd64.zip" + echo "${TOFU_SHA256} /tmp/tofu.zip" | sha256sum -c - + sudo unzip -o /tmp/tofu.zip tofu -d /usr/local/bin - name: Install terraform for provider mirror setup uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 with: @@ -56,9 +64,14 @@ jobs: - name: Setup provider mirror for integration tests run: ./hack/setup_mirror.sh - name: Create kind cluster for integration tests - uses: helm/kind-action@92086f6be054225fa813e0a4b13787fc9088faab # v1.13.0 - with: - cluster_name: kind + env: + KIND_VERSION: 0.33.0 + KIND_SHA256: aee6151561422756b764a4ae28e7f44cda5af5a9eead3cc9985112b1de8d8e0d + run: | + curl -fsSLo /tmp/kind "https://github.com/kubernetes-sigs/kind/releases/download/v${KIND_VERSION}/kind-linux-amd64" + echo "${KIND_SHA256} /tmp/kind" | sha256sum -c - + sudo install -m 0755 /tmp/kind /usr/local/bin/kind + kind create cluster --name kind --wait 5m - name: Tests env: OTF_TEST_KUBE: true From bc90cbac29ed87303e5aa500338fe304f6e4e64e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 14:37:57 -0400 Subject: [PATCH 03/10] ci: add caches, run on ubuntu-26.04, rename workflow - per-job Go module/build caches; saved on master only - cache playwright browsers and provider mirror - use preinstalled kind Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/ci.yml | 101 +++++++++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7fe0346fa..33c557175 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: ci +name: Continuous Integration on: push: branches: @@ -11,9 +11,13 @@ permissions: concurrency: group: ci-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} +# Go caches (modules + build) are per job, since each job builds different +# packages. They are restored on every run but saved only on master pushes: +# PRs read master's caches, and PR branches don't fill the repo cache quota. +# The run ID in the key saves a fresh build cache on each master push. jobs: lint: - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 timeout-minutes: 20 steps: - name: Checkout @@ -24,6 +28,18 @@ jobs: uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 with: go-version-file: "go.mod" + cache: false + - name: Restore Go cache + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + ~/.cache/staticcheck + key: go-lint-${{ runner.os }}-${{ hashFiles('go.sum') }}-${{ github.run_id }} + restore-keys: | + go-lint-${{ runner.os }}-${{ hashFiles('go.sum') }}- + go-lint-${{ runner.os }}- - name: Check no diff run: make check-no-diff - name: Lint check @@ -32,9 +48,18 @@ jobs: make helm-lint - name: Vet check run: make vet + - name: Save Go cache + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + ~/.cache/staticcheck + key: go-lint-${{ runner.os }}-${{ hashFiles('go.sum') }}-${{ github.run_id }} test: # You must use a Linux environment when using service containers or container jobs - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 timeout-minutes: 60 steps: - name: Checkout @@ -45,11 +70,35 @@ jobs: uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 with: go-version-file: "go.mod" + cache: false + - name: Restore Go cache + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: go-test-${{ runner.os }}-${{ hashFiles('go.sum') }}-${{ github.run_id }} + restore-keys: | + go-test-${{ runner.os }}-${{ hashFiles('go.sum') }}- + go-test-${{ runner.os }}- + # The playwright version is pinned in go.mod. + - name: Cache playwright browsers + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ~/.cache/ms-playwright + key: playwright-${{ runner.os }}-${{ hashFiles('go.sum') }} - name: Install e2e dependencies run: make install-playwright-ubuntu - # tofu and kind are installed from release binaries: their setup actions - # are not on the org's allowed actions list. + - name: Cache provider mirror + id: mirror-cache + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: mirror/registry.* + key: mirror-${{ hashFiles('mirror/providers.tf') }} + # tofu is installed from a release binary: its setup action + # is not on the org's allowed actions list. - name: Install tofu for provider mirror setup + if: steps.mirror-cache.outputs.cache-hit != 'true' env: TOFU_VERSION: 1.13.1 TOFU_SHA256: 8ccbc6f8ee21d2827715f3c6e08a9b3e0209b1e62057c05067ef117e047c1a80 @@ -58,20 +107,16 @@ jobs: echo "${TOFU_SHA256} /tmp/tofu.zip" | sha256sum -c - sudo unzip -o /tmp/tofu.zip tofu -d /usr/local/bin - name: Install terraform for provider mirror setup + if: steps.mirror-cache.outputs.cache-hit != 'true' uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 with: terraform_wrapper: false - name: Setup provider mirror for integration tests + if: steps.mirror-cache.outputs.cache-hit != 'true' run: ./hack/setup_mirror.sh + # kind is preinstalled on the runner image. - name: Create kind cluster for integration tests - env: - KIND_VERSION: 0.33.0 - KIND_SHA256: aee6151561422756b764a4ae28e7f44cda5af5a9eead3cc9985112b1de8d8e0d - run: | - curl -fsSLo /tmp/kind "https://github.com/kubernetes-sigs/kind/releases/download/v${KIND_VERSION}/kind-linux-amd64" - echo "${KIND_SHA256} /tmp/kind" | sha256sum -c - - sudo install -m 0755 /tmp/kind /usr/local/bin/kind - kind create cluster --name kind --wait 5m + run: kind create cluster --name kind --wait 5m - name: Tests env: OTF_TEST_KUBE: true @@ -82,8 +127,16 @@ jobs: with: name: e2e-browser-traces path: internal/integration/traces + - name: Save Go cache + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: go-test-${{ runner.os }}-${{ hashFiles('go.sum') }}-${{ github.run_id }} api-tests: - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 timeout-minutes: 30 steps: - name: Checkout @@ -94,6 +147,18 @@ jobs: uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 with: go-version-file: "go.mod" + cache: false + # Also holds the go-tfe module that the API tests download. + - name: Restore Go cache + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: go-api-${{ runner.os }}-${{ hashFiles('go.sum') }}-${{ github.run_id }} + restore-keys: | + go-api-${{ runner.os }}-${{ hashFiles('go.sum') }}- + go-api-${{ runner.os }}- - name: Add hosts to /etc/hosts run: | # otfd is configured with hostname otf.local @@ -102,3 +167,11 @@ jobs: # VCS tests are skipped: they need a github oauth token to create a # webhook on a real github repo. run: make go-tfe-tests + - name: Save Go cache + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: go-api-${{ runner.os }}-${{ hashFiles('go.sum') }}-${{ github.run_id }} From 804585a774f27cb00a63821e06074d7bebf052be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 14:49:36 -0400 Subject: [PATCH 04/10] fix(hack): print otfd logs when go-tfe tests fail; drop -v set -e exited before the log step, and docker compose ran from the go-tfe module dir with no compose file. Non-verbose output matches the test job: failing tests' output only. Co-Authored-By: Claude Opus 5.5 (1M context) --- hack/go-tfe-tests.bash | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/hack/go-tfe-tests.bash b/hack/go-tfe-tests.bash index f43ab22eb..5bb93afb2 100755 --- a/hack/go-tfe-tests.bash +++ b/hack/go-tfe-tests.bash @@ -122,17 +122,24 @@ echo "downloaded go-tfe module to $dest_dir" # some tests generate a tarball and save locally and need write perms chmod -R +w $dest_dir +compose_file=$PWD/docker-compose.testing.yml + cd $dest_dir +# capture failures rather than exit on them (set -e), so that otfd logs can be +# printed below +status=0 + # run beta tests unless user specifies tests (there is currently no way in this # script to specify individual *beta* tests to run) if [[ "$#" -eq 0 ]]; then - ENABLE_BETA=1 go test -v -run $allBetaTests -timeout 600s + ENABLE_BETA=1 go test -run $allBetaTests -timeout 600s || status=$? fi # run tests -go test -v -run ${@:-$all} -timeout 600s -skip $skipTests +go test -run ${@:-$all} -timeout 600s -skip $skipTests || status=$? # if tests fail then spit out otfd logs -if [[ $? -ne 0 ]]; then - docker compose logs otfd +if [[ $status -ne 0 ]]; then + docker compose -f $compose_file logs otfd fi +exit $status From 481e66ba32548d35276370cffcc1026af62fad92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 14:50:56 -0400 Subject: [PATCH 05/10] ci: always cancel in-progress runs of the same PR Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33c557175..5bd643b47 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,9 +8,11 @@ on: - master permissions: contents: read +# A new push to a PR cancels the PR's running CI. Master pushes get a group +# per commit, so each one runs to the end and saves caches. concurrency: - group: ci-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} + group: ci-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true # Go caches (modules + build) are per job, since each job builds different # packages. They are restored on every run but saved only on master pushes: # PRs read master's caches, and PR branches don't fill the repo cache quota. From 129b9751367ffe22d52f209a6f0fc29a95b33035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 15:02:06 -0400 Subject: [PATCH 06/10] fix(hack): match go test output of the test job in go-tfe tests Co-Authored-By: Claude Opus 5.5 (1M context) --- hack/go-tfe-tests.bash | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hack/go-tfe-tests.bash b/hack/go-tfe-tests.bash index 5bb93afb2..705d413eb 100755 --- a/hack/go-tfe-tests.bash +++ b/hack/go-tfe-tests.bash @@ -130,13 +130,16 @@ cd $dest_dir # printed below status=0 +# the explicit package (.) selects package list mode, which prints only an +# `ok ` line on success, like `go test ./...` in the test job + # run beta tests unless user specifies tests (there is currently no way in this # script to specify individual *beta* tests to run) if [[ "$#" -eq 0 ]]; then - ENABLE_BETA=1 go test -run $allBetaTests -timeout 600s || status=$? + ENABLE_BETA=1 go test . -run $allBetaTests -timeout 600s || status=$? fi # run tests -go test -run ${@:-$all} -timeout 600s -skip $skipTests || status=$? +go test . -run ${@:-$all} -timeout 600s -skip $skipTests || status=$? # if tests fail then spit out otfd logs if [[ $status -ne 0 ]]; then From ebb4009e35fc7e65ed9e5ba993e69c8de0604c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 14:58:02 -0400 Subject: [PATCH 07/10] ci: use setup-opentofu and kind-action (org allowlisted pins) Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/ci.yml | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bd643b47..57373c777 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,17 +97,9 @@ jobs: with: path: mirror/registry.* key: mirror-${{ hashFiles('mirror/providers.tf') }} - # tofu is installed from a release binary: its setup action - # is not on the org's allowed actions list. - name: Install tofu for provider mirror setup if: steps.mirror-cache.outputs.cache-hit != 'true' - env: - TOFU_VERSION: 1.13.1 - TOFU_SHA256: 8ccbc6f8ee21d2827715f3c6e08a9b3e0209b1e62057c05067ef117e047c1a80 - run: | - curl -fsSLo /tmp/tofu.zip "https://github.com/opentofu/opentofu/releases/download/v${TOFU_VERSION}/tofu_${TOFU_VERSION}_linux_amd64.zip" - echo "${TOFU_SHA256} /tmp/tofu.zip" | sha256sum -c - - sudo unzip -o /tmp/tofu.zip tofu -d /usr/local/bin + uses: opentofu/setup-opentofu@a1320f892987e89d278cc92dc5adc984fb93aca4 # v2.0.2 - name: Install terraform for provider mirror setup if: steps.mirror-cache.outputs.cache-hit != 'true' uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2 @@ -116,9 +108,10 @@ jobs: - name: Setup provider mirror for integration tests if: steps.mirror-cache.outputs.cache-hit != 'true' run: ./hack/setup_mirror.sh - # kind is preinstalled on the runner image. - name: Create kind cluster for integration tests - run: kind create cluster --name kind --wait 5m + uses: helm/kind-action@1544676c07bb3570fcb70166beaa07c4528fd4aa # v1.15.1 + with: + cluster_name: kind - name: Tests env: OTF_TEST_KUBE: true From 14d581cee726b3da796d05cb4181f23117d9c74b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 15:14:00 -0400 Subject: [PATCH 08/10] test: make e2e browser tracing opt-in; drop CI trace upload OTF_E2E_TRACE=true turns tracing on. Off by default: recording screenshots and snapshots slows down tests. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/ci.yml | 6 ------ docs/docs/testing.md | 10 ++++++++++ internal/testbrowser/pool.go | 38 +++++++++++++++++++++++++----------- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 57373c777..4e5c17a10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,12 +116,6 @@ jobs: env: OTF_TEST_KUBE: true run: make test - - name: Archive browser traces - if: always() - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: e2e-browser-traces - path: internal/integration/traces - name: Save Go cache if: github.event_name == 'push' && github.ref == 'refs/heads/master' uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 diff --git a/docs/docs/testing.md b/docs/docs/testing.md index e6bab1cdd..0d4f90a1b 100644 --- a/docs/docs/testing.md +++ b/docs/docs/testing.md @@ -43,6 +43,16 @@ export OTF_E2E_HEADLESS=false
Integration tests with headless mode disabled
+#### Record browser traces + +Browser-based tests can record a [playwright trace](https://playwright.dev/docs/trace-viewer) of each browser session, with screenshots and DOM snapshots. Tracing is off by default because it slows down the tests. To turn it on: + +``` +export OTF_E2E_TRACE=true +``` + +Each trace is written to `internal/integration/traces/_/trace.zip`. + #### More verbose logging By default, the integration tests don't print the logs from the OTF daemons they spawn. To enable logging with a verbosity of 1, set the following environment variable: diff --git a/internal/testbrowser/pool.go b/internal/testbrowser/pool.go index ced28fe20..0b34d0984 100644 --- a/internal/testbrowser/pool.go +++ b/internal/testbrowser/pool.go @@ -20,6 +20,7 @@ import ( const ( headlessEnvVar = "OTF_E2E_HEADLESS" + traceEnvVar = "OTF_E2E_TRACE" tracesDir = "traces" ) @@ -35,6 +36,8 @@ type Pool struct { tokens *tokens.Service // keep a record of tests using this pool tests map[*testing.T]int + // record a playwright trace of each browser context + trace bool } func NewPool(secret []byte) (*Pool, func(), error) { @@ -54,6 +57,16 @@ func NewPool(secret []byte) (*Pool, func(), error) { } } + // Tracing is opt-in: recording screenshots and snapshots slows down tests. + var trace bool + if v, ok := os.LookupEnv(traceEnvVar); ok { + var err error + trace, err = strconv.ParseBool(v) + if err != nil { + return nil, nil, fmt.Errorf("parsing %s: %w", traceEnvVar, err) + } + } + // Remove previous traces os.RemoveAll(tracesDir) @@ -73,6 +86,7 @@ func NewPool(secret []byte) (*Pool, func(), error) { tokens: tokensService, browser: browser, tests: make(map[*testing.T]int), + trace: trace, } for range poolSize { p.pool <- nil @@ -113,17 +127,19 @@ func (p *Pool) New(t *testing.T, user context.Context, fn func(playwright.Page)) defer browserCtx.Close() // Setup tracing for debugging purposes. - browserCtx.Tracing().Start(playwright.TracingStartOptions{ - Screenshots: new(true), - Snapshots: new(true), - }) - defer func() { - // Save trace to a unique path for each call of this func - dir := fmt.Sprintf("%s_%d", t.Name(), p.tests[t]) - p.tests[t]++ - path := filepath.Join(tracesDir, dir, "trace.zip") - browserCtx.Tracing().Stop(path) - }() + if p.trace { + browserCtx.Tracing().Start(playwright.TracingStartOptions{ + Screenshots: new(true), + Snapshots: new(true), + }) + defer func() { + // Save trace to a unique path for each call of this func + dir := fmt.Sprintf("%s_%d", t.Name(), p.tests[t]) + p.tests[t]++ + path := filepath.Join(tracesDir, dir, "trace.zip") + browserCtx.Tracing().Stop(path) + }() + } err = browserCtx.GrantPermissions([]string{ "clipboard-read", From 12c24397dc70652568f9604490d83d87cc5a86b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 15:14:14 -0400 Subject: [PATCH 09/10] test: keep e2e browser tracing as upstream Only the CI trace upload is dropped. Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/docs/testing.md | 10 ---------- internal/testbrowser/pool.go | 38 +++++++++++------------------------- 2 files changed, 11 insertions(+), 37 deletions(-) diff --git a/docs/docs/testing.md b/docs/docs/testing.md index 0d4f90a1b..e6bab1cdd 100644 --- a/docs/docs/testing.md +++ b/docs/docs/testing.md @@ -43,16 +43,6 @@ export OTF_E2E_HEADLESS=false
Integration tests with headless mode disabled
-#### Record browser traces - -Browser-based tests can record a [playwright trace](https://playwright.dev/docs/trace-viewer) of each browser session, with screenshots and DOM snapshots. Tracing is off by default because it slows down the tests. To turn it on: - -``` -export OTF_E2E_TRACE=true -``` - -Each trace is written to `internal/integration/traces/_/trace.zip`. - #### More verbose logging By default, the integration tests don't print the logs from the OTF daemons they spawn. To enable logging with a verbosity of 1, set the following environment variable: diff --git a/internal/testbrowser/pool.go b/internal/testbrowser/pool.go index 0b34d0984..ced28fe20 100644 --- a/internal/testbrowser/pool.go +++ b/internal/testbrowser/pool.go @@ -20,7 +20,6 @@ import ( const ( headlessEnvVar = "OTF_E2E_HEADLESS" - traceEnvVar = "OTF_E2E_TRACE" tracesDir = "traces" ) @@ -36,8 +35,6 @@ type Pool struct { tokens *tokens.Service // keep a record of tests using this pool tests map[*testing.T]int - // record a playwright trace of each browser context - trace bool } func NewPool(secret []byte) (*Pool, func(), error) { @@ -57,16 +54,6 @@ func NewPool(secret []byte) (*Pool, func(), error) { } } - // Tracing is opt-in: recording screenshots and snapshots slows down tests. - var trace bool - if v, ok := os.LookupEnv(traceEnvVar); ok { - var err error - trace, err = strconv.ParseBool(v) - if err != nil { - return nil, nil, fmt.Errorf("parsing %s: %w", traceEnvVar, err) - } - } - // Remove previous traces os.RemoveAll(tracesDir) @@ -86,7 +73,6 @@ func NewPool(secret []byte) (*Pool, func(), error) { tokens: tokensService, browser: browser, tests: make(map[*testing.T]int), - trace: trace, } for range poolSize { p.pool <- nil @@ -127,19 +113,17 @@ func (p *Pool) New(t *testing.T, user context.Context, fn func(playwright.Page)) defer browserCtx.Close() // Setup tracing for debugging purposes. - if p.trace { - browserCtx.Tracing().Start(playwright.TracingStartOptions{ - Screenshots: new(true), - Snapshots: new(true), - }) - defer func() { - // Save trace to a unique path for each call of this func - dir := fmt.Sprintf("%s_%d", t.Name(), p.tests[t]) - p.tests[t]++ - path := filepath.Join(tracesDir, dir, "trace.zip") - browserCtx.Tracing().Stop(path) - }() - } + browserCtx.Tracing().Start(playwright.TracingStartOptions{ + Screenshots: new(true), + Snapshots: new(true), + }) + defer func() { + // Save trace to a unique path for each call of this func + dir := fmt.Sprintf("%s_%d", t.Name(), p.tests[t]) + p.tests[t]++ + path := filepath.Join(tracesDir, dir, "trace.zip") + browserCtx.Tracing().Stop(path) + }() err = browserCtx.GrantPermissions([]string{ "clipboard-read", From 0c85c1503dcc39a48abe3a00f62d3aa621f71271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Beauch=C3=A9?= Date: Tue, 13 Oct 2026 15:34:05 -0400 Subject: [PATCH 10/10] ci: address review: no go-tfe result cache, master-only cache saves - go-tfe tests: -count=1; package list mode cached results while otfd changed - playwright + provider mirror caches: restore always, save on master only - setup_mirror.sh: fail on error so a partial mirror is never cached Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/ci.yml | 28 +++++++++++++++++++--------- hack/go-tfe-tests.bash | 8 +++++--- hack/setup_mirror.sh | 2 ++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e5c17a10..4d27b9a30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,8 @@ permissions: concurrency: group: ci-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true -# Go caches (modules + build) are per job, since each job builds different -# packages. They are restored on every run but saved only on master pushes: -# PRs read master's caches, and PR branches don't fill the repo cache quota. -# The run ID in the key saves a fresh build cache on each master push. +# Caches are restored on every run and saved on master pushes only. The run ID +# in the Go cache keys makes each master push save a fresh build cache. jobs: lint: runs-on: ubuntu-26.04 @@ -60,7 +58,6 @@ jobs: ~/.cache/staticcheck key: go-lint-${{ runner.os }}-${{ hashFiles('go.sum') }}-${{ github.run_id }} test: - # You must use a Linux environment when using service containers or container jobs runs-on: ubuntu-26.04 timeout-minutes: 60 steps: @@ -84,16 +81,23 @@ jobs: go-test-${{ runner.os }}-${{ hashFiles('go.sum') }}- go-test-${{ runner.os }}- # The playwright version is pinned in go.mod. - - name: Cache playwright browsers - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + - name: Restore playwright browsers + id: playwright-cache + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ~/.cache/ms-playwright key: playwright-${{ runner.os }}-${{ hashFiles('go.sum') }} - name: Install e2e dependencies run: make install-playwright-ubuntu - - name: Cache provider mirror + - name: Save playwright browsers + if: github.event_name == 'push' && github.ref == 'refs/heads/master' && steps.playwright-cache.outputs.cache-hit != 'true' + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ~/.cache/ms-playwright + key: playwright-${{ runner.os }}-${{ hashFiles('go.sum') }} + - name: Restore provider mirror id: mirror-cache - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: mirror/registry.* key: mirror-${{ hashFiles('mirror/providers.tf') }} @@ -108,6 +112,12 @@ jobs: - name: Setup provider mirror for integration tests if: steps.mirror-cache.outputs.cache-hit != 'true' run: ./hack/setup_mirror.sh + - name: Save provider mirror + if: github.event_name == 'push' && github.ref == 'refs/heads/master' && steps.mirror-cache.outputs.cache-hit != 'true' + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: mirror/registry.* + key: mirror-${{ hashFiles('mirror/providers.tf') }} - name: Create kind cluster for integration tests uses: helm/kind-action@1544676c07bb3570fcb70166beaa07c4528fd4aa # v1.15.1 with: diff --git a/hack/go-tfe-tests.bash b/hack/go-tfe-tests.bash index 705d413eb..2145bca4a 100755 --- a/hack/go-tfe-tests.bash +++ b/hack/go-tfe-tests.bash @@ -131,15 +131,17 @@ cd $dest_dir status=0 # the explicit package (.) selects package list mode, which prints only an -# `ok ` line on success, like `go test ./...` in the test job +# `ok ` line on success, like `go test ./...` in the test job. That mode +# also caches results, but these tests depend on otfd, which the cache cannot +# see: -count=1 disables the cache. # run beta tests unless user specifies tests (there is currently no way in this # script to specify individual *beta* tests to run) if [[ "$#" -eq 0 ]]; then - ENABLE_BETA=1 go test . -run $allBetaTests -timeout 600s || status=$? + ENABLE_BETA=1 go test . -count=1 -run $allBetaTests -timeout 600s || status=$? fi # run tests -go test . -run ${@:-$all} -timeout 600s -skip $skipTests || status=$? +go test . -count=1 -run ${@:-$all} -timeout 600s -skip $skipTests || status=$? # if tests fail then spit out otfd logs if [[ $status -ne 0 ]]; then diff --git a/hack/setup_mirror.sh b/hack/setup_mirror.sh index ca067f868..b6acd7be1 100755 --- a/hack/setup_mirror.sh +++ b/hack/setup_mirror.sh @@ -1,5 +1,7 @@ +#!/usr/bin/env bash # Setup filesystem mirror for both terraform and tofu. This speeds up the # integration tests massively. +set -euo pipefail cd mirror/ terraform providers mirror . tofu providers mirror .