fix: allow anonymous access to /invite/:token accept page #21521
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Test Workflow | |
| # Top-level PR / merge-queue gate. Detects which paths changed and dispatches | |
| # to the dedicated reusable workflows under .github/workflows/. Each child | |
| # workflow keeps its own setup/teardown so this file stays a routing layer. | |
| # | |
| # The final `all-checks-passed` job is the single status check that branch | |
| # protection should require — it succeeds only if every required upstream | |
| # job either succeeded or was legitimately skipped by its path filter. | |
| on: | |
| pull_request: | |
| branches: ["main"] | |
| merge_group: | |
| branches: ["main"] | |
| workflow_dispatch: | |
| # cancel in-progress jobs if a new job is triggered | |
| # This is useful to avoid running multiple builds for the same branch if a new commit is pushed | |
| # or a pull request is updated. | |
| # It helps to save resources and time by ensuring that only the latest commit is built and tested | |
| # This is particularly useful for long-running jobs that may take a while to complete. | |
| # The `group` is set to a combination of the workflow name, event name, and branch name. | |
| # This ensures that jobs are grouped by the workflow and branch, allowing for cancellation of | |
| # in-progress jobs when a new commit is pushed to the same branch or a new pull request is opened. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref_name || github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| files-changed: | |
| name: detect what files changed | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 3 | |
| outputs: | |
| build: ${{ steps.changes.outputs.build }} | |
| backend: ${{ steps.changes.outputs.backend }} | |
| project: ${{ steps.changes.outputs.project }} | |
| openapi: ${{ steps.changes.outputs.openapi }} | |
| frontend: ${{ steps.changes.outputs.frontend }} | |
| docker-base: ${{ steps.changes.outputs.docker-base }} | |
| dockerfiles: ${{ steps.changes.outputs.dockerfiles }} | |
| tauri: ${{ steps.changes.outputs.tauri }} | |
| engine: ${{ steps.changes.outputs.engine }} | |
| generated-models: ${{ steps.changes.outputs.generated-models }} | |
| proprietary: ${{ steps.changes.outputs.proprietary }} | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1 | |
| with: | |
| egress-policy: audit | |
| - name: Checkout repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Check for file changes | |
| uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3 | |
| id: changes | |
| with: | |
| filters: .github/config/.files.yaml | |
| gradle-cache-prime: | |
| needs: [files-changed] | |
| uses: ./.github/workflows/gradle-cache-prime.yml | |
| secrets: inherit | |
| build: | |
| if: needs.files-changed.outputs.backend == 'true' | |
| needs: [files-changed, gradle-cache-prime] | |
| permissions: | |
| actions: read | |
| contents: read | |
| security-events: write | |
| pull-requests: write | |
| uses: ./.github/workflows/backend-build.yml | |
| secrets: inherit | |
| db-migration-test: | |
| # Boots the current bootJar against H2 fixtures captured from past | |
| # releases (v2.0.0 / v2.5.0 / v2.10.0) and verifies admin login still | |
| # works after Hibernate's ddl-auto=update migrates the schema. Gated on | |
| # the `project` filter so doc-only PRs skip this ~5-minute job. | |
| if: needs.files-changed.outputs.project == 'true' | |
| needs: [files-changed, gradle-cache-prime] | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/db-migration-test.yml | |
| secrets: inherit | |
| check-generateOpenApiDocs: | |
| if: needs.files-changed.outputs.openapi == 'true' | |
| needs: [files-changed, gradle-cache-prime] | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/check-openapi.yml | |
| secrets: inherit | |
| frontend-validation: | |
| if: needs.files-changed.outputs.frontend == 'true' | |
| needs: [files-changed] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| uses: ./.github/workflows/frontend-validation.yml | |
| secrets: inherit | |
| # Required (in all-checks-passed). Scans the stories a branch touches in both | |
| # light and dark; an axe violation in either theme blocks the merge. The | |
| # whole-suite sweep (nightly.yml) still covers stories a change affects without | |
| # touching them directly. | |
| frontend-a11y: | |
| if: needs.files-changed.outputs.frontend == 'true' | |
| needs: [files-changed] | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/frontend-a11y.yml | |
| secrets: inherit | |
| playwright-e2e: | |
| if: needs.files-changed.outputs.frontend == 'true' | |
| needs: [files-changed] | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/e2e-stubbed.yml | |
| secrets: inherit | |
| playwright-e2e-live: | |
| if: needs.files-changed.outputs.frontend == 'true' | |
| needs: [files-changed, gradle-cache-prime] | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/e2e-live.yml | |
| secrets: inherit | |
| playwright-e2e-enterprise: | |
| if: needs.files-changed.outputs.proprietary == 'true' | |
| needs: [files-changed, gradle-cache-prime] | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/build-enterprise.yml | |
| secrets: inherit | |
| with: | |
| use_shared_cache: true | |
| check-licence: | |
| if: needs.files-changed.outputs.build == 'true' | |
| needs: [files-changed, gradle-cache-prime] | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/check-licence.yml | |
| secrets: inherit | |
| docker-compose-tests: | |
| if: needs.files-changed.outputs.project == 'true' | |
| needs: [files-changed, gradle-cache-prime] | |
| permissions: | |
| actions: write | |
| contents: read | |
| checks: write | |
| uses: ./.github/workflows/docker-compose-tests.yml | |
| secrets: inherit | |
| with: | |
| docker-base-changed: ${{ needs.files-changed.outputs.docker-base }} | |
| test-build-docker-images: | |
| if: | | |
| always() && | |
| github.event_name == 'pull_request' && | |
| needs.files-changed.outputs.project == 'true' && | |
| contains(fromJSON('["success", "skipped"]'), needs.gradle-cache-prime.result) && | |
| contains(fromJSON('["success", "skipped"]'), needs.build.result) && | |
| contains(fromJSON('["success", "skipped"]'), needs.check-generateOpenApiDocs.result) && | |
| contains(fromJSON('["success", "skipped"]'), needs.check-licence.result) | |
| needs: | |
| [ | |
| files-changed, | |
| build, | |
| check-generateOpenApiDocs, | |
| check-licence, | |
| gradle-cache-prime, | |
| ] | |
| permissions: | |
| contents: read | |
| packages: read | |
| uses: ./.github/workflows/test-build-docker.yml | |
| secrets: inherit | |
| with: | |
| docker-base-changed: ${{ needs.files-changed.outputs.docker-base }} | |
| dockerfiles-changed: ${{ needs.files-changed.outputs.dockerfiles }} | |
| tauri-build: | |
| if: needs.files-changed.outputs.tauri == 'true' | |
| needs: [files-changed, gradle-cache-prime] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| uses: ./.github/workflows/tauri-build.yml | |
| secrets: inherit | |
| # PR smoke build: macOS + Windows (the platforms our developers use). | |
| # sign: true only reaches macOS - tauri-build's per-platform gate keeps | |
| # Windows/Linux signing on main, and an unsigned .dmg cannot be opened. | |
| # The full signed multi-OS matrix runs on release; | |
| # nightly still warms the Rust cache with all-OS defaults. | |
| with: | |
| platform: windows-macos | |
| sign: true | |
| use_shared_cache: true | |
| ai-engine: | |
| if: needs.files-changed.outputs.engine == 'true' | |
| needs: [files-changed] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| uses: ./.github/workflows/ai-engine.yml | |
| secrets: inherit | |
| # The generated frontend types and engine tool models are both derived from | |
| # the Java OpenAPI spec. This job regenerates and diffs them; it boots the | |
| # backend, so it is gated on the narrow generated-models filter (spec source, | |
| # generators, generated files, generation tasks) rather than the broad | |
| # frontend filter, so a CSS-only PR does not pay for a backend build. | |
| generated-models: | |
| if: needs.files-changed.outputs.generated-models == 'true' | |
| needs: [files-changed, gradle-cache-prime] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| uses: ./.github/workflows/check-generated-models.yml | |
| secrets: inherit | |
| with: | |
| use_shared_cache: true | |
| pre-commit: | |
| needs: [files-changed] | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/pre_commit.yml | |
| secrets: inherit | |
| dependency-review: | |
| needs: [files-changed] | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/dependency-review.yml | |
| secrets: inherit | |
| # Coverage aggregate: merges the JUnit + e2e:live + cucumber .exec | |
| # artifacts produced by the jobs above into one report, plus pulls | |
| # in vitest + Playwright frontend coverage for the per-area matrix. | |
| # `if: always()` so a producer failing partway still gets credit | |
| # for whatever did record. Advisory only - intentionally NOT in | |
| # all-checks-passed, so a flaky aggregate run never blocks merging. | |
| coverage-aggregate: | |
| if: always() | |
| needs: | |
| - build | |
| - playwright-e2e-live | |
| - docker-compose-tests | |
| - frontend-validation | |
| permissions: | |
| contents: read | |
| uses: ./.github/workflows/coverage-aggregate.yml | |
| secrets: inherit | |
| with: | |
| frontend-validation-result: ${{ needs.frontend-validation.result }} | |
| playwright-e2e-live-result: ${{ needs.playwright-e2e-live.result }} | |
| # Single status check that branch protection should mark as required. | |
| # Succeeds when every upstream job is either `success` or `skipped` (path- | |
| # gated jobs that didn't apply this run). Any `failure` or `cancelled` | |
| # result fails the gate. `if: always()` ensures the gate evaluates even | |
| # when an upstream job fails. | |
| all-checks-passed: | |
| name: All checks passed | |
| if: always() | |
| needs: | |
| - files-changed | |
| - gradle-cache-prime | |
| - build | |
| - db-migration-test | |
| - check-generateOpenApiDocs | |
| - frontend-validation | |
| - frontend-a11y | |
| - playwright-e2e | |
| - playwright-e2e-live | |
| - playwright-e2e-enterprise | |
| - check-licence | |
| - docker-compose-tests | |
| - test-build-docker-images | |
| - tauri-build | |
| - ai-engine | |
| - generated-models | |
| - pre-commit | |
| - dependency-review | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1 | |
| with: | |
| egress-policy: audit | |
| - name: Verify every required job passed (or was legitimately skipped) | |
| env: | |
| RESULTS: | | |
| files-changed=${{ needs.files-changed.result }} | |
| gradle-cache-prime=${{ needs.gradle-cache-prime.result }} | |
| build=${{ needs.build.result }} | |
| db-migration-test=${{ needs.db-migration-test.result }} | |
| check-generateOpenApiDocs=${{ needs.check-generateOpenApiDocs.result }} | |
| frontend-validation=${{ needs.frontend-validation.result }} | |
| frontend-a11y=${{ needs.frontend-a11y.result }} | |
| playwright-e2e=${{ needs.playwright-e2e.result }} | |
| playwright-e2e-live=${{ needs.playwright-e2e-live.result }} | |
| playwright-e2e-enterprise=${{ needs.playwright-e2e-enterprise.result }} | |
| check-licence=${{ needs.check-licence.result }} | |
| docker-compose-tests=${{ needs.docker-compose-tests.result }} | |
| test-build-docker-images=${{ needs.test-build-docker-images.result }} | |
| tauri-build=${{ needs.tauri-build.result }} | |
| ai-engine=${{ needs.ai-engine.result }} | |
| generated-models=${{ needs.generated-models.result }} | |
| pre-commit=${{ needs.pre-commit.result }} | |
| dependency-review=${{ needs.dependency-review.result }} | |
| run: | | |
| ok=true | |
| while IFS='=' read -r name result; do | |
| [ -z "$name" ] && continue | |
| case "$result" in | |
| success|skipped) printf ' %-30s %s\n' "$name" "$result" ;; | |
| *) printf '✗ %-30s %s\n' "$name" "$result"; ok=false ;; | |
| esac | |
| done <<< "$RESULTS" | |
| if [ "$ok" != "true" ]; then | |
| echo "" | |
| echo "One or more required checks failed or were cancelled." | |
| exit 1 | |
| fi | |
| echo "" | |
| echo "All required checks passed." |