From e18b1fd99d6e359d74e4fcd1984ddd2f4cc91bd7 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 9 Mar 2026 10:02:34 -0700 Subject: [PATCH] Chore: use unified "gates" for ci tests and docs checks (#12277) --- .github/workflows/ci-backend.yml | 86 +++++++++++++++++++++---- .github/workflows/ci-docs.yml | 88 +++++++++++++++++++++----- .github/workflows/ci-frontend.yml | 102 +++++++++++++++++++++++++++--- 3 files changed, 237 insertions(+), 39 deletions(-) diff --git a/.github/workflows/ci-backend.yml b/.github/workflows/ci-backend.yml index f8bcbe2f3..488445545 100644 --- a/.github/workflows/ci-backend.yml +++ b/.github/workflows/ci-backend.yml @@ -3,21 +3,9 @@ on: push: branches-ignore: - 'translations**' - paths: - - 'src/**' - - 'pyproject.toml' - - 'uv.lock' - - 'docker/compose/docker-compose.ci-test.yml' - - '.github/workflows/ci-backend.yml' pull_request: branches-ignore: - 'translations**' - paths: - - 'src/**' - - 'pyproject.toml' - - 'uv.lock' - - 'docker/compose/docker-compose.ci-test.yml' - - '.github/workflows/ci-backend.yml' workflow_dispatch: concurrency: group: backend-${{ github.event.pull_request.number || github.ref }} @@ -26,7 +14,55 @@ env: DEFAULT_UV_VERSION: "0.10.x" NLTK_DATA: "/usr/share/nltk_data" jobs: + changes: + name: Detect Backend Changes + runs-on: ubuntu-slim + outputs: + backend_changed: ${{ steps.force.outputs.run_all == 'true' || steps.filter.outputs.backend == 'true' }} + steps: + - name: Checkout + uses: actions/checkout@v6.0.2 + with: + fetch-depth: 0 + - name: Decide run mode + id: force + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + echo "run_all=true" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event_name }}" == "push" && ( "${{ github.ref_name }}" == "main" || "${{ github.ref_name }}" == "dev" ) ]]; then + echo "run_all=true" >> "$GITHUB_OUTPUT" + else + echo "run_all=false" >> "$GITHUB_OUTPUT" + fi + - name: Set diff range + id: range + if: steps.force.outputs.run_all != 'true' + run: | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + echo "base=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event.created }}" == "true" ]]; then + echo "base=origin/${{ github.event.repository.default_branch }}" >> "$GITHUB_OUTPUT" + else + echo "base=${{ github.event.before }}" >> "$GITHUB_OUTPUT" + fi + echo "ref=${{ github.sha }}" >> "$GITHUB_OUTPUT" + - name: Detect changes + id: filter + if: steps.force.outputs.run_all != 'true' + uses: dorny/paths-filter@v3.0.2 + with: + base: ${{ steps.range.outputs.base }} + ref: ${{ steps.range.outputs.ref }} + filters: | + backend: + - 'src/**' + - 'pyproject.toml' + - 'uv.lock' + - 'docker/compose/docker-compose.ci-test.yml' + - '.github/workflows/ci-backend.yml' test: + needs: changes + if: needs.changes.outputs.backend_changed == 'true' name: "Python ${{ matrix.python-version }}" runs-on: ubuntu-24.04 strategy: @@ -100,6 +136,8 @@ jobs: docker compose --file docker/compose/docker-compose.ci-test.yml logs docker compose --file docker/compose/docker-compose.ci-test.yml down typing: + needs: changes + if: needs.changes.outputs.backend_changed == 'true' name: Check project typing runs-on: ubuntu-24.04 env: @@ -150,3 +188,27 @@ jobs: --show-error-codes \ --warn-unused-configs \ src/ | uv run mypy-baseline filter + gate: + name: Backend CI Gate + needs: [changes, test, typing] + if: always() + runs-on: ubuntu-slim + steps: + - name: Check gate + run: | + if [[ "${{ needs.changes.outputs.backend_changed }}" != "true" ]]; then + echo "No backend-relevant changes detected." + exit 0 + fi + + if [[ "${{ needs.test.result }}" != "success" ]]; then + echo "::error::Backend test job result: ${{ needs.test.result }}" + exit 1 + fi + + if [[ "${{ needs.typing.result }}" != "success" ]]; then + echo "::error::Backend typing job result: ${{ needs.typing.result }}" + exit 1 + fi + + echo "Backend checks passed." diff --git a/.github/workflows/ci-docs.yml b/.github/workflows/ci-docs.yml index 721d7d2eb..e684e6f55 100644 --- a/.github/workflows/ci-docs.yml +++ b/.github/workflows/ci-docs.yml @@ -1,22 +1,9 @@ name: Documentation on: push: - branches: - - main - - dev - paths: - - 'docs/**' - - 'zensical.toml' - - 'pyproject.toml' - - 'uv.lock' - - '.github/workflows/ci-docs.yml' + branches-ignore: + - 'translations**' pull_request: - paths: - - 'docs/**' - - 'zensical.toml' - - 'pyproject.toml' - - 'uv.lock' - - '.github/workflows/ci-docs.yml' workflow_dispatch: concurrency: group: docs-${{ github.event.pull_request.number || github.ref }} @@ -29,7 +16,55 @@ env: DEFAULT_UV_VERSION: "0.10.x" DEFAULT_PYTHON_VERSION: "3.12" jobs: + changes: + name: Detect Docs Changes + runs-on: ubuntu-slim + outputs: + docs_changed: ${{ steps.force.outputs.run_all == 'true' || steps.filter.outputs.docs == 'true' }} + steps: + - name: Checkout + uses: actions/checkout@v6.0.2 + with: + fetch-depth: 0 + - name: Decide run mode + id: force + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + echo "run_all=true" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event_name }}" == "push" && ( "${{ github.ref_name }}" == "main" || "${{ github.ref_name }}" == "dev" ) ]]; then + echo "run_all=true" >> "$GITHUB_OUTPUT" + else + echo "run_all=false" >> "$GITHUB_OUTPUT" + fi + - name: Set diff range + id: range + if: steps.force.outputs.run_all != 'true' + run: | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + echo "base=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event.created }}" == "true" ]]; then + echo "base=origin/${{ github.event.repository.default_branch }}" >> "$GITHUB_OUTPUT" + else + echo "base=${{ github.event.before }}" >> "$GITHUB_OUTPUT" + fi + echo "ref=${{ github.sha }}" >> "$GITHUB_OUTPUT" + - name: Detect changes + id: filter + if: steps.force.outputs.run_all != 'true' + uses: dorny/paths-filter@v3.0.2 + with: + base: ${{ steps.range.outputs.base }} + ref: ${{ steps.range.outputs.ref }} + filters: | + docs: + - 'docs/**' + - 'zensical.toml' + - 'pyproject.toml' + - 'uv.lock' + - '.github/workflows/ci-docs.yml' build: + needs: changes + if: needs.changes.outputs.docs_changed == 'true' name: Build Documentation runs-on: ubuntu-24.04 steps: @@ -64,8 +99,8 @@ jobs: name: github-pages-${{ github.run_id }}-${{ github.run_attempt }} deploy: name: Deploy Documentation - needs: build - if: github.event_name == 'push' && github.ref == 'refs/heads/main' + needs: [changes, build] + if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.changes.outputs.docs_changed == 'true' runs-on: ubuntu-24.04 environment: name: github-pages @@ -76,3 +111,22 @@ jobs: id: deployment with: artifact_name: github-pages-${{ github.run_id }}-${{ github.run_attempt }} + gate: + name: Docs CI Gate + needs: [changes, build] + if: always() + runs-on: ubuntu-slim + steps: + - name: Check gate + run: | + if [[ "${{ needs.changes.outputs.docs_changed }}" != "true" ]]; then + echo "No docs-relevant changes detected." + exit 0 + fi + + if [[ "${{ needs.build.result }}" != "success" ]]; then + echo "::error::Docs build job result: ${{ needs.build.result }}" + exit 1 + fi + + echo "Docs checks passed." diff --git a/.github/workflows/ci-frontend.yml b/.github/workflows/ci-frontend.yml index 6a5b88f9f..625b14a23 100644 --- a/.github/workflows/ci-frontend.yml +++ b/.github/workflows/ci-frontend.yml @@ -3,21 +3,60 @@ on: push: branches-ignore: - 'translations**' - paths: - - 'src-ui/**' - - '.github/workflows/ci-frontend.yml' pull_request: branches-ignore: - 'translations**' - paths: - - 'src-ui/**' - - '.github/workflows/ci-frontend.yml' workflow_dispatch: concurrency: group: frontend-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: + changes: + name: Detect Frontend Changes + runs-on: ubuntu-slim + outputs: + frontend_changed: ${{ steps.force.outputs.run_all == 'true' || steps.filter.outputs.frontend == 'true' }} + steps: + - name: Checkout + uses: actions/checkout@v6.0.2 + with: + fetch-depth: 0 + - name: Decide run mode + id: force + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + echo "run_all=true" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event_name }}" == "push" && ( "${{ github.ref_name }}" == "main" || "${{ github.ref_name }}" == "dev" ) ]]; then + echo "run_all=true" >> "$GITHUB_OUTPUT" + else + echo "run_all=false" >> "$GITHUB_OUTPUT" + fi + - name: Set diff range + id: range + if: steps.force.outputs.run_all != 'true' + run: | + if [[ "${{ github.event_name }}" == "pull_request" ]]; then + echo "base=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event.created }}" == "true" ]]; then + echo "base=origin/${{ github.event.repository.default_branch }}" >> "$GITHUB_OUTPUT" + else + echo "base=${{ github.event.before }}" >> "$GITHUB_OUTPUT" + fi + echo "ref=${{ github.sha }}" >> "$GITHUB_OUTPUT" + - name: Detect changes + id: filter + if: steps.force.outputs.run_all != 'true' + uses: dorny/paths-filter@v3.0.2 + with: + base: ${{ steps.range.outputs.base }} + ref: ${{ steps.range.outputs.ref }} + filters: | + frontend: + - 'src-ui/**' + - '.github/workflows/ci-frontend.yml' install-dependencies: + needs: changes + if: needs.changes.outputs.frontend_changed == 'true' name: Install Dependencies runs-on: ubuntu-24.04 steps: @@ -45,7 +84,8 @@ jobs: run: cd src-ui && pnpm install lint: name: Lint - needs: install-dependencies + needs: [changes, install-dependencies] + if: needs.changes.outputs.frontend_changed == 'true' runs-on: ubuntu-24.04 steps: - name: Checkout @@ -73,7 +113,8 @@ jobs: run: cd src-ui && pnpm run lint unit-tests: name: "Unit Tests (${{ matrix.shard-index }}/${{ matrix.shard-count }})" - needs: install-dependencies + needs: [changes, install-dependencies] + if: needs.changes.outputs.frontend_changed == 'true' runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -119,7 +160,8 @@ jobs: directory: src-ui/coverage/ e2e-tests: name: "E2E Tests (${{ matrix.shard-index }}/${{ matrix.shard-count }})" - needs: install-dependencies + needs: [changes, install-dependencies] + if: needs.changes.outputs.frontend_changed == 'true' runs-on: ubuntu-24.04 container: mcr.microsoft.com/playwright:v1.58.2-noble env: @@ -159,7 +201,8 @@ jobs: run: cd src-ui && pnpm exec playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }} bundle-analysis: name: Bundle Analysis - needs: [unit-tests, e2e-tests] + needs: [changes, unit-tests, e2e-tests] + if: needs.changes.outputs.frontend_changed == 'true' runs-on: ubuntu-24.04 steps: - name: Checkout @@ -189,3 +232,42 @@ jobs: env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} run: cd src-ui && pnpm run build --configuration=production + gate: + name: Frontend CI Gate + needs: [changes, install-dependencies, lint, unit-tests, e2e-tests, bundle-analysis] + if: always() + runs-on: ubuntu-slim + steps: + - name: Check gate + run: | + if [[ "${{ needs.changes.outputs.frontend_changed }}" != "true" ]]; then + echo "No frontend-relevant changes detected." + exit 0 + fi + + if [[ "${{ needs['install-dependencies'].result }}" != "success" ]]; then + echo "::error::Frontend install job result: ${{ needs['install-dependencies'].result }}" + exit 1 + fi + + if [[ "${{ needs.lint.result }}" != "success" ]]; then + echo "::error::Frontend lint job result: ${{ needs.lint.result }}" + exit 1 + fi + + if [[ "${{ needs['unit-tests'].result }}" != "success" ]]; then + echo "::error::Frontend unit-tests job result: ${{ needs['unit-tests'].result }}" + exit 1 + fi + + if [[ "${{ needs['e2e-tests'].result }}" != "success" ]]; then + echo "::error::Frontend e2e-tests job result: ${{ needs['e2e-tests'].result }}" + exit 1 + fi + + if [[ "${{ needs['bundle-analysis'].result }}" != "success" ]]; then + echo "::error::Frontend bundle-analysis job result: ${{ needs['bundle-analysis'].result }}" + exit 1 + fi + + echo "Frontend checks passed."