From 837ba17bd364513bbf0c7fe0ea77da9376ddaffe Mon Sep 17 00:00:00 2001 From: frostebite Date: Mon, 31 Aug 2026 21:52:44 +0100 Subject: [PATCH] Add job timeouts and split cache save/restore in CI workflows Add timeout-minutes to every job in checks.yml, firebase-hosting-merge.yml, firebase-hosting-pull-request.yml, cats.yml, and search-trigger.yml so a hung job fails fast instead of blocking the runner queue indefinitely. Also split actions/cache@v4 usage in checks.yml and both firebase-hosting workflows into the explicit restore + save pattern, moving the save to the end of each job with continue-on-error and its own timeout, to avoid the known post-run cache-save hang. --- .github/workflows/cats.yml | 1 + .github/workflows/checks.yml | 80 +++++++++++++++++-- .github/workflows/firebase-hosting-merge.yml | 16 +++- .../firebase-hosting-pull-request.yml | 16 +++- .github/workflows/search-trigger.yml | 1 + 5 files changed, 107 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cats.yml b/.github/workflows/cats.yml index ef94df5c..4b653d61 100644 --- a/.github/workflows/cats.yml +++ b/.github/workflows/cats.yml @@ -10,6 +10,7 @@ jobs: aCatForCreatingThePullRequest: name: A cat for your effort! runs-on: ubuntu-latest + timeout-minutes: 5 steps: - name: Action Cats uses: ruairidhwm/action-cats@1.0.2 diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 74715cd1..41e0cea5 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -8,6 +8,7 @@ jobs: codeFormatting: name: Code formatting runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v4 - name: Read Node version from mise.toml @@ -25,7 +26,7 @@ jobs: id: yarn-config run: echo "cacheFolder=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT" - name: Restore yarn install cache (node_modules + cacheFolder + install-state) - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -42,10 +43,24 @@ jobs: run: | case "$(yarn --version)" in 1.*) echo 'expected up-to-date yarn version'; exit 1 ;; esac yarn install --immutable + - name: Save yarn install cache (node_modules + cacheFolder + install-state) + if: always() + uses: actions/cache/save@v4 + with: + path: | + node_modules + ${{ steps.yarn-config.outputs.cacheFolder }} + .yarn/install-state.gz + key: + yarn-${{ runner.os }}-node${{ steps.node.outputs.version }}-${{ hashFiles('yarn.lock') + }} + timeout-minutes: 5 + continue-on-error: true - run: yarn format:check codeStyles: name: Code styles runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v4 - name: Read Node version from mise.toml @@ -63,7 +78,7 @@ jobs: id: yarn-config run: echo "cacheFolder=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT" - name: Restore yarn install cache (node_modules + cacheFolder + install-state) - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -80,10 +95,24 @@ jobs: run: | case "$(yarn --version)" in 1.*) echo 'expected up-to-date yarn version'; exit 1 ;; esac yarn install --immutable + - name: Save yarn install cache (node_modules + cacheFolder + install-state) + if: always() + uses: actions/cache/save@v4 + with: + path: | + node_modules + ${{ steps.yarn-config.outputs.cacheFolder }} + .yarn/install-state.gz + key: + yarn-${{ runner.os }}-node${{ steps.node.outputs.version }}-${{ hashFiles('yarn.lock') + }} + timeout-minutes: 5 + continue-on-error: true - run: yarn lint types: name: Types check runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v4 - name: Read Node version from mise.toml @@ -101,7 +130,7 @@ jobs: id: yarn-config run: echo "cacheFolder=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT" - name: Restore yarn install cache (node_modules + cacheFolder + install-state) - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -118,10 +147,24 @@ jobs: run: | case "$(yarn --version)" in 1.*) echo 'expected up-to-date yarn version'; exit 1 ;; esac yarn install --immutable + - name: Save yarn install cache (node_modules + cacheFolder + install-state) + if: always() + uses: actions/cache/save@v4 + with: + path: | + node_modules + ${{ steps.yarn-config.outputs.cacheFolder }} + .yarn/install-state.gz + key: + yarn-${{ runner.os }}-node${{ steps.node.outputs.version }}-${{ hashFiles('yarn.lock') + }} + timeout-minutes: 5 + continue-on-error: true - run: yarn typecheck tests: name: Tests runs-on: ubuntu-latest + timeout-minutes: 15 steps: - uses: actions/checkout@v4 - name: Read Node version from mise.toml @@ -139,7 +182,7 @@ jobs: id: yarn-config run: echo "cacheFolder=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT" - name: Restore yarn install cache (node_modules + cacheFolder + install-state) - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -156,6 +199,19 @@ jobs: run: | case "$(yarn --version)" in 1.*) echo 'expected up-to-date yarn version'; exit 1 ;; esac yarn install --immutable + - name: Save yarn install cache (node_modules + cacheFolder + install-state) + if: always() + uses: actions/cache/save@v4 + with: + path: | + node_modules + ${{ steps.yarn-config.outputs.cacheFolder }} + .yarn/install-state.gz + key: + yarn-${{ runner.os }}-node${{ steps.node.outputs.version }}-${{ hashFiles('yarn.lock') + }} + timeout-minutes: 5 + continue-on-error: true - run: yarn test --coverage - run: bash <(curl -s https://codecov.io/bash) env: @@ -163,6 +219,7 @@ jobs: e2e: name: E2E tests runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v4 - name: Read Node version from mise.toml @@ -180,7 +237,7 @@ jobs: id: yarn-config run: echo "cacheFolder=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT" - name: Restore yarn install cache (node_modules + cacheFolder + install-state) - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -197,6 +254,19 @@ jobs: run: | case "$(yarn --version)" in 1.*) echo 'expected up-to-date yarn version'; exit 1 ;; esac yarn install --immutable + - name: Save yarn install cache (node_modules + cacheFolder + install-state) + if: always() + uses: actions/cache/save@v4 + with: + path: | + node_modules + ${{ steps.yarn-config.outputs.cacheFolder }} + .yarn/install-state.gz + key: + yarn-${{ runner.os }}-node${{ steps.node.outputs.version }}-${{ hashFiles('yarn.lock') + }} + timeout-minutes: 5 + continue-on-error: true - run: yarn build - run: npx playwright install --with-deps chromium - run: yarn test:e2e diff --git a/.github/workflows/firebase-hosting-merge.yml b/.github/workflows/firebase-hosting-merge.yml index bb97d812..3e15c753 100644 --- a/.github/workflows/firebase-hosting-merge.yml +++ b/.github/workflows/firebase-hosting-merge.yml @@ -9,6 +9,7 @@ name: Deploy Live jobs: build_and_deploy: runs-on: ubuntu-latest + timeout-minutes: 20 steps: # Checkout - uses: actions/checkout@v4 @@ -29,7 +30,7 @@ jobs: id: yarn-config run: echo "cacheFolder=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT" - name: Restore yarn install cache (node_modules + cacheFolder + install-state) - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -46,6 +47,19 @@ jobs: run: | case "$(yarn --version)" in 1.*) echo 'expected up-to-date yarn version'; exit 1 ;; esac yarn install --immutable + - name: Save yarn install cache (node_modules + cacheFolder + install-state) + if: always() + uses: actions/cache/save@v4 + with: + path: | + node_modules + ${{ steps.yarn-config.outputs.cacheFolder }} + .yarn/install-state.gz + key: + yarn-${{ runner.os }}-node${{ steps.node.outputs.version }}-${{ hashFiles('yarn.lock') + }} + timeout-minutes: 5 + continue-on-error: true - name: Build website run: yarn build diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml index 1e214c85..c67b947a 100644 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ b/.github/workflows/firebase-hosting-pull-request.yml @@ -7,6 +7,7 @@ jobs: build_and_preview: if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}' runs-on: ubuntu-latest + timeout-minutes: 20 steps: # Checkout - uses: actions/checkout@v4 @@ -27,7 +28,7 @@ jobs: id: yarn-config run: echo "cacheFolder=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT" - name: Restore yarn install cache (node_modules + cacheFolder + install-state) - uses: actions/cache@v4 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -44,6 +45,19 @@ jobs: run: | case "$(yarn --version)" in 1.*) echo 'expected up-to-date yarn version'; exit 1 ;; esac yarn install --immutable + - name: Save yarn install cache (node_modules + cacheFolder + install-state) + if: always() + uses: actions/cache/save@v4 + with: + path: | + node_modules + ${{ steps.yarn-config.outputs.cacheFolder }} + .yarn/install-state.gz + key: + yarn-${{ runner.os }}-node${{ steps.node.outputs.version }}-${{ hashFiles('yarn.lock') + }} + timeout-minutes: 5 + continue-on-error: true - name: Build website run: yarn build diff --git a/.github/workflows/search-trigger.yml b/.github/workflows/search-trigger.yml index 615cd1ba..abcfd73d 100644 --- a/.github/workflows/search-trigger.yml +++ b/.github/workflows/search-trigger.yml @@ -5,6 +5,7 @@ jobs: updateSearchIndex: name: Update search index runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v4 - uses: darrenjennings/algolia-docsearch-action@da2ed379c147b356d60dbfec68bdcfacb2791a98