diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1281cef2..575dcfb9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,9 +20,22 @@ concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + lint-workflows: + name: Workflow Checks + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v7 + - name: Check workflow files + uses: docker://rhysd/actionlint:1.7.12 + with: + args: -color + check-frontend: name: Frontend Checks + needs: lint-workflows runs-on: windows-2025-vs2026 + timeout-minutes: 20 steps: - name: Checkout @@ -35,7 +48,9 @@ jobs: check-backend: name: Backend Checks + needs: lint-workflows runs-on: windows-2025-vs2026 + timeout-minutes: 20 env: CARGO_PROFILE_DEV_DEBUG: 0 CARGO_PROFILE_TEST_DEBUG: 0 @@ -62,6 +77,7 @@ jobs: test-e2e-desktop: name: Desktop E2E + needs: lint-workflows runs-on: windows-2025-vs2026 timeout-minutes: 20 env: @@ -110,7 +126,7 @@ jobs: ci-gate: name: CI Gate if: ${{ always() }} - needs: [check-frontend, check-backend, test-e2e-desktop] + needs: [lint-workflows, check-frontend, check-backend, test-e2e-desktop] runs-on: ubuntu-latest timeout-minutes: 5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 48597e1d..d7436f95 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,6 +16,7 @@ jobs: release-windows: name: Build Windows installers runs-on: windows-2025-vs2026 + timeout-minutes: 45 steps: - name: Checkout diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c2fa4384..91ce455b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -189,7 +189,9 @@ Frontend checks enforce a coverage floor. It is a ratchet set just below the mea CI and release jobs share [the setup action](./.github/actions/setup/action.yml), which uses `pnpm/setup` to install manifest-selected pnpm and Node.js, cache the package store, and require a frozen lockfile. Rust jobs provide a cache workspace mapping to also install the pinned toolchain and restore the appropriate target directory; CI saves Rust caches only on `main`. -The `CI Gate` job in [the CI workflow](./.github/workflows/ci.yml) waits for `Frontend Checks`, `Backend Checks`, and `Desktop E2E`. It runs even when a prerequisite fails or is skipped, and passes only when every prerequisite succeeds. +`Workflow Checks` runs pinned actionlint, including ShellCheck, before the application jobs. It checks all workflow files, including the release workflow. CI jobs have explicit time limits: five minutes for workflow linting and the gate, twenty minutes for each application job, and forty-five minutes for the release build. + +The `CI Gate` job in [the CI workflow](./.github/workflows/ci.yml) waits for `Workflow Checks`, `Frontend Checks`, `Backend Checks`, and `Desktop E2E`. It runs even when a prerequisite fails or is skipped, and passes only when every prerequisite succeeds. To change the required validation, update `ci-gate.needs` with the relevant job IDs. If a job becomes conditional, update the gate's result policy in the same pull request so intentional skips are explicit and unexpected skips still fail. Keep the `CI Gate` display name stable because GitHub branch protection uses it. When migrating branch protection, retain the existing required checks until the gate passes on a pull request and is merged, then require `CI Gate` from GitHub Actions.