From 4207ee2492c62dbde426fef13a6b719c023ceac3 Mon Sep 17 00:00:00 2001 From: AminDhouib Date: Tue, 15 Sep 2026 20:25:17 -0400 Subject: [PATCH] ci: gate per-package e2e jobs on changed paths and add missing job timeouts Two changes, both CI-only. 1. A `changes` gate job in ci.yml. Each of the nine e2e jobs runs `turbo run e2e --filter=`, so a commit that touches an unrelated package still pays for the whole matrix. A single dorny/paths-filter@v4 job now classifies the changed files and each e2e job carries `needs: changes` plus an `if:` on its own output. Filter keys use underscores because `needs.changes.outputs.e2e-core` would parse as a subtraction. Skipping is safe here: main is unprotected, so a skipped job cannot block a pull request. e2e-core if: needs.changes.outputs.e2e_core == 'true' e2e-core-oidc if: needs.changes.outputs.e2e_core_oidc == 'true' e2e-core-tokenless if: needs.changes.outputs.e2e_core_tokenless == 'true' e2e-cypress if: needs.changes.outputs.e2e_cypress == 'true' e2e-playwright if: needs.changes.outputs.e2e_playwright == 'true' e2e-puppeteer if: needs.changes.outputs.e2e_puppeteer == 'true' e2e-storybook if: needs.changes.outputs.e2e_storybook == 'true' e2e-vitest if: needs.changes.outputs.e2e_vitest == 'true' e2e-webdriverio if: needs.changes.outputs.e2e_webdriverio == 'true' Every filter includes .github/workflows/ci.yml, so a change to the workflow itself still runs all nine. The gate job gets timeout-minutes: 5, matching the other jobs in this workflow, and pull-requests: read for the filter step. 2. timeout-minutes on the three jobs that had none. Every job in ci.yml already declared one. The rule is 3 x the observed p90 duration rounded up to the nearest 5 minutes; none of these three had a usable sample in 72 h of run history, so each takes its class default. pr.yml check-commits 30 class default (other) publish-sdk.yml publish 60 class default (release) release.yml release 30 class default (build) No concurrency edit was planned for this repository. --- .github/workflows/ci.yml | 131 ++++++++++++++++++++++++++++++ .github/workflows/pr.yml | 1 + .github/workflows/publish-sdk.yml | 1 + .github/workflows/release.yml | 1 + 4 files changed, 134 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 74dd3349..1a3e5d4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,119 @@ env: TURBO_TEAM: ${{ vars.TURBO_TEAM }} jobs: + # Classify the changed files once, so the nine per-package e2e jobs below can + # skip themselves when their package was not touched. Filter keys use + # underscores: `needs.changes.outputs.e2e-core` would parse as a subtraction. + changes: + timeout-minutes: 5 + runs-on: ubuntu-latest + + permissions: + contents: read + pull-requests: read + + outputs: + e2e_core: ${{ steps.filter.outputs.e2e_core }} + e2e_core_oidc: ${{ steps.filter.outputs.e2e_core_oidc }} + e2e_core_tokenless: ${{ steps.filter.outputs.e2e_core_tokenless }} + e2e_cypress: ${{ steps.filter.outputs.e2e_cypress }} + e2e_playwright: ${{ steps.filter.outputs.e2e_playwright }} + e2e_puppeteer: ${{ steps.filter.outputs.e2e_puppeteer }} + e2e_storybook: ${{ steps.filter.outputs.e2e_storybook }} + e2e_vitest: ${{ steps.filter.outputs.e2e_vitest }} + e2e_webdriverio: ${{ steps.filter.outputs.e2e_webdriverio }} + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Classify changed files + id: filter + uses: dorny/paths-filter@v4 + with: + filters: | + e2e_core: + - ".github/workflows/ci.yml" + - "package-lock.json" + - "package.json" + - "packages/api-client/**" + - "packages/cli/**" + - "packages/core/**" + - "packages/util/**" + - "turbo.json" + e2e_core_oidc: + - ".github/workflows/ci.yml" + - "package-lock.json" + - "package.json" + - "packages/api-client/**" + - "packages/cli/**" + - "packages/core/**" + - "packages/util/**" + - "turbo.json" + e2e_core_tokenless: + - ".github/workflows/ci.yml" + - "package-lock.json" + - "package.json" + - "packages/api-client/**" + - "packages/cli/**" + - "packages/core/**" + - "packages/util/**" + - "turbo.json" + e2e_cypress: + - ".github/workflows/ci.yml" + - "package-lock.json" + - "package.json" + - "packages/api-client/**" + - "packages/core/**" + - "packages/cypress/**" + - "packages/util/**" + - "turbo.json" + e2e_playwright: + - ".github/workflows/ci.yml" + - "package-lock.json" + - "package.json" + - "packages/api-client/**" + - "packages/core/**" + - "packages/playwright/**" + - "packages/util/**" + - "turbo.json" + e2e_puppeteer: + - ".github/workflows/ci.yml" + - "package-lock.json" + - "package.json" + - "packages/api-client/**" + - "packages/core/**" + - "packages/puppeteer/**" + - "packages/util/**" + - "turbo.json" + e2e_storybook: + - ".github/workflows/ci.yml" + - "package-lock.json" + - "package.json" + - "packages/api-client/**" + - "packages/core/**" + - "packages/storybook/**" + - "packages/util/**" + - "turbo.json" + e2e_vitest: + - ".github/workflows/ci.yml" + - "package-lock.json" + - "package.json" + - "packages/api-client/**" + - "packages/core/**" + - "packages/util/**" + - "packages/vitest/**" + - "turbo.json" + e2e_webdriverio: + - ".github/workflows/ci.yml" + - "package-lock.json" + - "package.json" + - "packages/api-client/**" + - "packages/core/**" + - "packages/util/**" + - "packages/webdriverio/**" + - "turbo.json" + lint: timeout-minutes: 5 runs-on: ubuntu-latest @@ -72,6 +185,8 @@ jobs: run: npm run test e2e-core: + needs: changes + if: needs.changes.outputs.e2e_core == 'true' timeout-minutes: 5 env: ARGOS_API_BASE_URL: https://api.snapvisor.io/v2/ @@ -105,6 +220,8 @@ jobs: OS: ${{ matrix.os }} e2e-core-oidc: + needs: changes + if: needs.changes.outputs.e2e_core_oidc == 'true' timeout-minutes: 5 runs-on: ubuntu-latest @@ -129,6 +246,8 @@ jobs: OS: ubuntu-latest e2e-core-tokenless: + needs: changes + if: needs.changes.outputs.e2e_core_tokenless == 'true' timeout-minutes: 5 runs-on: ubuntu-latest @@ -149,6 +268,8 @@ jobs: OS: ubuntu-latest e2e-cypress: + needs: changes + if: needs.changes.outputs.e2e_cypress == 'true' timeout-minutes: 5 env: ARGOS_API_BASE_URL: https://api.snapvisor.io/v2/ @@ -177,6 +298,8 @@ jobs: OS: ${{ matrix.os }} e2e-playwright: + needs: changes + if: needs.changes.outputs.e2e_playwright == 'true' timeout-minutes: 5 env: ARGOS_API_BASE_URL: https://api.snapvisor.io/v2/ @@ -205,6 +328,8 @@ jobs: OS: ${{ matrix.os }} e2e-puppeteer: + needs: changes + if: needs.changes.outputs.e2e_puppeteer == 'true' timeout-minutes: 5 env: ARGOS_API_BASE_URL: https://api.snapvisor.io/v2/ @@ -233,6 +358,8 @@ jobs: OS: ${{ matrix.os }} e2e-webdriverio: + needs: changes + if: needs.changes.outputs.e2e_webdriverio == 'true' timeout-minutes: 5 env: ARGOS_API_BASE_URL: https://api.snapvisor.io/v2/ @@ -261,6 +388,8 @@ jobs: OS: ${{ matrix.os }} e2e-storybook: + needs: changes + if: needs.changes.outputs.e2e_storybook == 'true' timeout-minutes: 5 env: ARGOS_API_BASE_URL: https://api.snapvisor.io/v2/ @@ -289,6 +418,8 @@ jobs: OS: ${{ matrix.os }} e2e-vitest: + needs: changes + if: needs.changes.outputs.e2e_vitest == 'true' timeout-minutes: 5 env: ARGOS_API_BASE_URL: https://api.snapvisor.io/v2/ diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index ba41ce1d..fc07d395 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -8,6 +8,7 @@ jobs: check-commits: name: Check Commits runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v6 diff --git a/.github/workflows/publish-sdk.yml b/.github/workflows/publish-sdk.yml index e4f14e18..c77114ab 100644 --- a/.github/workflows/publish-sdk.yml +++ b/.github/workflows/publish-sdk.yml @@ -9,6 +9,7 @@ on: jobs: publish: runs-on: ubuntu-latest + timeout-minutes: 60 defaults: run: working-directory: sdk diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9121ab2f..03b2cca2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,6 +24,7 @@ env: jobs: release: runs-on: ubuntu-latest + timeout-minutes: 30 steps: - name: Checkout