From 83e531966193cb9fbd820e668596eed8651d0fcb Mon Sep 17 00:00:00 2001 From: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:49:06 +0100 Subject: [PATCH] Reduce CI cost: disable Depot, gate arm64/Tauri PR builds, self-testing CI routing (#7028) ## What CI cost/routing cleanup. Four changes, each reversible with no code deleted. ### 1. Disable Depot repo-wide (reversible) Depot ran on trusted (non-fork) triggers via the `is_fork` output of `_runner-pick.yml`, driving both the `depot-*` runner selection and the Depot docker build actions. It's now disabled everywhere behind a single kill-switch: - `_runner-pick.yml` gains a dedicated `use_depot` output, forced `false` via `DEPOT_ENABLED=false`. `is_fork` stays truthful for trust gating (e.g. `build-enterprise` skipping on forks). - All `runs-on:` and `USE_DEPOT:` expressions now key off `use_depot`, so every job falls back to `ubuntu-latest` + buildx. - `settings.gradle` Depot remote build cache (`cache.depot.dev`) gated behind `depotCacheEnabled = false`. **Switch back on:** set `DEPOT_ENABLED=true` in `_runner-pick.yml` (and `depotCacheEnabled = true` in `settings.gradle`). Depot then reactivates on trusted triggers exactly as before. ### 2. arm64 PR docker build only on Dockerfile changes `test-build-docker.yml` was building `linux/amd64,linux/arm64/v8` on every PR matching the broad `project` filter. With Depot off, the arm64 leg runs under slow QEMU emulation on every code PR. New `dockerfiles` path filter (`docker/**/Dockerfile*`) gates the arm64 leg: normal code PRs build amd64 only; PRs that touch a Dockerfile still build amd64 + arm64. arm64 is still fully exercised on the base-image publish and on release. ### 3. Tauri PR build -> Linux only, unsigned, deb-only The PR path built the full 3-OS matrix (Windows + macOS-universal + Linux), plus the flaky Linux AppImage pass (#6127). PRs now build Linux only (fastest + cheapest to compile) via a new `minimal` input on `tauri-build.yml`: Linux deb only, no rpm, no AppImage. The full signed multi-OS matrix still runs on release, and nightly still warms the Rust cache with all-OS defaults (unchanged). Tradeoff: Windows/macOS desktop build breaks are caught by nightly (all-OS) rather than the introducing PR. ### 4. CI self-testing routing Editing `build.yml` only matched the `project` filter, so a change to how e2e / enterprise / tauri / engine jobs are dispatched didn't actually run those jobs. Added a `ci` anchor (`build.yml` + `.github/config/.files.yaml`) that every job-gating area filter now includes, so editing the router or the filter config runs every job. Also added the orphaned reusable workflows (`e2e-*`, `frontend-validation`, `docker-compose-tests`, `test-build-docker`, `check-openapi`, `check-licence`) to their area filters so editing a reusable workflow self-tests. ## Validation - All workflow YAML + `.files.yaml` parse; anchor resolution verified (every job-gating filter resolves to include the `ci` paths). - Gradle evaluates `settings.gradle` cleanly; `spotlessGradleCheck` passes. --- .github/config/.files.yaml | 32 +++++++++- .github/workflows/PR-Auto-Deploy-V2.yml | 8 +-- .../workflows/PR-Demo-Comment-with-react.yml | 8 +-- .github/workflows/_runner-pick.yml | 58 +++++++++++++------ .github/workflows/backend-build.yml | 2 +- .github/workflows/build-enterprise.yml | 2 +- .github/workflows/build.yml | 9 +++ .github/workflows/check-openapi.yml | 2 +- .github/workflows/coverage-aggregate.yml | 2 +- .github/workflows/db-migration-test.yml | 2 +- .github/workflows/deploy-on-v2-commit.yml | 4 +- .github/workflows/docker-compose-tests.yml | 2 +- .github/workflows/e2e-live.yml | 2 +- .github/workflows/e2e-stubbed.yml | 2 +- .../frontend-backend-licenses-update.yml | 6 +- .github/workflows/frontend-validation.yml | 2 +- .github/workflows/multiOSReleases.yml | 6 +- .github/workflows/nightly.yml | 2 +- .github/workflows/swagger.yml | 2 +- .github/workflows/tauri-build.yml | 29 +++++++--- .github/workflows/test-build-docker.yml | 24 ++++++-- .github/workflows/testdriver.yml | 10 ++-- settings.gradle | 10 ++-- 23 files changed, 156 insertions(+), 70 deletions(-) diff --git a/.github/config/.files.yaml b/.github/config/.files.yaml index 905f2feed9..2894464831 100644 --- a/.github/config/.files.yaml +++ b/.github/config/.files.yaml @@ -1,16 +1,34 @@ +# CI routing infra. Editing the top-level router (build.yml) or this filter +# config re-runs every area's jobs, so every job-gating filter below includes +# *ci. That makes a change to how jobs are dispatched actually exercise those +# jobs (self-testing), instead of a router edit only matching the project filter. +ci: &ci + - .github/workflows/build.yml + - .github/config/.files.yaml + build: &build + - *ci - build.gradle - app/(common|core|proprietary|saas)/build.gradle - Taskfile.yml - .taskfiles/backend.yml + - .github/workflows/check-licence.yml openapi: &openapi + - *ci - *build - app/(common|core|proprietary|saas)/src/main/java/** + - .github/workflows/check-openapi.yml docker-base: &docker-base - docker/base/Dockerfile +# Dockerfiles only (base + embedded + unoserver). Gates the slow multi-arch +# (arm64) leg of the PR docker test build: arm64 is only rebuilt when a +# Dockerfile itself changes, not on every code PR. +dockerfiles: &dockerfiles + - docker/**/Dockerfile* + docker: &docker - docker/embedded/Dockerfile - docker/embedded/Dockerfile.fat @@ -23,13 +41,11 @@ docker: &docker - *docker-base project: &project + - *ci - app/(common|core|proprietary|saas)/src/(main|test)/java/** - *build - "app/(common|core|proprietary|saas)/src/(main|test)/resources/**/!(messages_*.properties|*.md)*" - exampleYmlFiles/** - - gradle/** - - libs/** - - "testing/**/!(requirements*.txt|requirements*.in)*" - *docker - *docker-base - gradle.properties @@ -45,8 +61,11 @@ project: &project - .taskfiles/docker.yml - scripts/db-migration/** - .github/workflows/db-migration-test.yml + - .github/workflows/docker-compose-tests.yml + - .github/workflows/test-build-docker.yml frontend: &frontend + - *ci - frontend/** - .github/workflows/testdriver.yml - testing/** @@ -63,10 +82,14 @@ frontend: &frontend - Taskfile.yml - .taskfiles/frontend.yml - .taskfiles/e2e.yml + - .github/workflows/frontend-validation.yml + - .github/workflows/e2e-stubbed.yml + - .github/workflows/e2e-live.yml # Files that affect the Tauri desktop bundle. Gate the multi-OS Tauri build # job on changes to any of these. tauri: &tauri + - *ci - frontend/editor/src-tauri/** - frontend/editor/src/desktop/** - frontend/editor/tsconfig.desktop.vite.json @@ -81,6 +104,7 @@ tauri: &tauri # the engine validation job on changes to engine sources or to the Java # tool surfaces it generates models from. engine: &engine + - *ci - engine/** - app/(common|core|proprietary|saas)/src/main/java/** - .github/workflows/ai-engine.yml @@ -93,6 +117,7 @@ engine: &engine # tasks that drive generation. Deliberately excludes the broad frontend/docker/ # testing globs, so a CSS-only PR does not boot the backend to rebuild the spec. generated-models: &generated-models + - *ci - *openapi - frontend/editor/scripts/generate-tool-api-types.mts - frontend/editor/src/core/types/toolApiTypes.ts @@ -115,6 +140,7 @@ licenses-backend: &licenses-backend # Files that can affect premium / enterprise behaviour. Gate the enterprise # Playwright job on changes to any of these on PRs. proprietary: &proprietary + - *ci - app/proprietary/** - frontend/editor/src/proprietary/** - frontend/editor/src/core/tests/enterprise/** diff --git a/.github/workflows/PR-Auto-Deploy-V2.yml b/.github/workflows/PR-Auto-Deploy-V2.yml index 8f1aab7977..172d72ee5c 100644 --- a/.github/workflows/PR-Auto-Deploy-V2.yml +++ b/.github/workflows/PR-Auto-Deploy-V2.yml @@ -29,7 +29,7 @@ jobs: check-pr: if: (github.event_name == 'pull_request' && github.event.action != 'closed') || github.event_name == 'workflow_dispatch' needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} outputs: should_deploy: ${{ steps.decide.outputs.should_deploy }} is_fork: ${{ steps.resolve.outputs.is_fork }} @@ -102,7 +102,7 @@ jobs: deploy-v2-pr: needs: [pick, check-pr] - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} if: needs.check-pr.outputs.should_deploy == 'true' && (needs.check-pr.outputs.is_fork == 'false' || needs.check-pr.outputs.allow_fork == 'true') # Concurrency control - only one deployment per PR at a time concurrency: @@ -114,7 +114,7 @@ jobs: pull-requests: write id-token: write env: - USE_DEPOT: ${{ needs.pick.outputs.is_fork != 'true' }} + USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' }} DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} # Single source of truth for whether this preview embeds the admin portal: # drives the image build-arg and the deployment comment. @@ -475,7 +475,7 @@ jobs: cleanup-v2-deployment: if: github.event.action == 'closed' needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} permissions: contents: read issues: write diff --git a/.github/workflows/PR-Demo-Comment-with-react.yml b/.github/workflows/PR-Demo-Comment-with-react.yml index 5a4ea8deef..2a780e5d98 100644 --- a/.github/workflows/PR-Demo-Comment-with-react.yml +++ b/.github/workflows/PR-Demo-Comment-with-react.yml @@ -39,7 +39,7 @@ jobs: check-comment: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} permissions: issues: write if: | @@ -180,13 +180,13 @@ jobs: deploy-pr: needs: [pick, check-comment] - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} permissions: issues: write pull-requests: write id-token: write env: - USE_DEPOT: ${{ needs.pick.outputs.is_fork != 'true' }} + USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' }} DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} steps: @@ -511,7 +511,7 @@ jobs: handle-label-commands: if: ${{ github.event.issue.pull_request != null }} needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} steps: - name: Harden Runner uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 diff --git a/.github/workflows/_runner-pick.yml b/.github/workflows/_runner-pick.yml index 023325d383..09959f3353 100644 --- a/.github/workflows/_runner-pick.yml +++ b/.github/workflows/_runner-pick.yml @@ -5,6 +5,11 @@ name: _runner-pick # can pick a runner class without each one duplicating the 200-char gate # expression in their own `runs-on:`. # +# It also owns the single Depot kill-switch (use_depot). Depot is currently +# disabled repo-wide; downstream jobs gate their Depot runner/build usage on +# use_depot so nothing has to be deleted to turn Depot off. Flip DEPOT_ENABLED +# in the decide step to switch Depot back on. +# # Caller pattern: # # jobs: @@ -13,12 +18,15 @@ name: _runner-pick # # real-work: # needs: pick -# runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-8' }} +# runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-8' || 'ubuntu-latest' }} # steps: [...] # -# Output: -# is_fork: "true" when the trigger is a pull_request from a fork or an -# untrusted author_association, "false" otherwise. +# Outputs: +# is_fork: "true" when the trigger is a pull_request from a fork or an +# untrusted author_association, "false" otherwise. Use this for +# trust gating (skipping secret-dependent jobs on forks). +# use_depot: "true" when downstream jobs should use Depot runners/builders. +# Currently forced "false" (Depot disabled repo-wide). on: workflow_call: @@ -26,6 +34,9 @@ on: is_fork: description: '"true" if the trigger is an untrusted fork PR.' value: ${{ jobs.pick.outputs.is_fork }} + use_depot: + description: '"true" when downstream jobs should use Depot. Currently forced off.' + value: ${{ jobs.pick.outputs.use_depot }} permissions: contents: read @@ -36,6 +47,7 @@ jobs: timeout-minutes: 1 outputs: is_fork: ${{ steps.decide.outputs.is_fork }} + use_depot: ${{ steps.decide.outputs.use_depot }} steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 @@ -50,21 +62,33 @@ jobs: AUTHOR_ASSOC: ${{ github.event.pull_request.author_association }} run: | set -eu + + # Depot kill-switch. Depot is disabled repo-wide: no job uses Depot + # runners or the Depot build actions while this is false. All the + # Depot wiring is left in place - set DEPOT_ENABLED=true to switch it + # back on (it then activates on trusted, non-fork triggers as before). + DEPOT_ENABLED=false + if [ -z "${PR_NUMBER:-}" ]; then # Not a pull_request event at all (push, schedule, workflow_dispatch, # workflow_call from a non-PR trigger) -> trusted by default. - echo "is_fork=false" >> "$GITHUB_OUTPUT" - exit 0 + is_fork=false + elif [ "${HEAD_REPO_FORK}" = "true" ]; then + is_fork=true + else + case "${AUTHOR_ASSOC}" in + OWNER|MEMBER|COLLABORATOR) is_fork=false ;; + *) is_fork=true ;; + esac fi - if [ "${HEAD_REPO_FORK}" = "true" ]; then - echo "is_fork=true" >> "$GITHUB_OUTPUT" - exit 0 + + # Depot only ever ran on trusted triggers, so gate it on both the + # kill-switch and is_fork. + if [ "${DEPOT_ENABLED}" = "true" ] && [ "${is_fork}" = "false" ]; then + use_depot=true + else + use_depot=false fi - case "${AUTHOR_ASSOC}" in - OWNER|MEMBER|COLLABORATOR) - echo "is_fork=false" >> "$GITHUB_OUTPUT" - ;; - *) - echo "is_fork=true" >> "$GITHUB_OUTPUT" - ;; - esac + + echo "is_fork=${is_fork}" >> "$GITHUB_OUTPUT" + echo "use_depot=${use_depot}" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/backend-build.yml b/.github/workflows/backend-build.yml index ef0dd20aba..e8e68968f2 100644 --- a/.github/workflows/backend-build.yml +++ b/.github/workflows/backend-build.yml @@ -24,7 +24,7 @@ jobs: build: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-8' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-8' || 'ubuntu-latest' }} env: DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} strategy: diff --git a/.github/workflows/build-enterprise.yml b/.github/workflows/build-enterprise.yml index 9e1a4efb83..5aab6529b4 100644 --- a/.github/workflows/build-enterprise.yml +++ b/.github/workflows/build-enterprise.yml @@ -54,7 +54,7 @@ jobs: # (nor DEPOT_TOKEN), so the suite can't boot premium and would fail. See the # header comment. GitHub reports the skipped reusable workflow as success. if: needs.pick.outputs.is_fork != 'true' - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }} timeout-minutes: 45 env: PREMIUM_KEY: ${{ secrets.PREMIUM_KEY_ENTERPRISE }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8142c37fca..5689afe532 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,6 +41,7 @@ jobs: 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 }} @@ -153,6 +154,7 @@ jobs: 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' @@ -162,6 +164,13 @@ jobs: pull-requests: write uses: ./.github/workflows/tauri-build.yml secrets: inherit + # PR smoke build: Linux only (fastest + cheapest to compile), unsigned, + # deb-only, no AppImage. The full signed multi-OS matrix runs on release; + # nightly still warms the Rust cache with all-OS defaults. + with: + platform: linux + sign: false + minimal: true ai-engine: if: needs.files-changed.outputs.engine == 'true' diff --git a/.github/workflows/check-openapi.yml b/.github/workflows/check-openapi.yml index a27ea4ec02..bf51140181 100644 --- a/.github/workflows/check-openapi.yml +++ b/.github/workflows/check-openapi.yml @@ -15,7 +15,7 @@ jobs: check-generate-openapi-docs: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} env: DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} steps: diff --git a/.github/workflows/coverage-aggregate.yml b/.github/workflows/coverage-aggregate.yml index 18772fe819..277350da93 100644 --- a/.github/workflows/coverage-aggregate.yml +++ b/.github/workflows/coverage-aggregate.yml @@ -34,7 +34,7 @@ jobs: aggregate: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} timeout-minutes: 15 steps: - name: Harden Runner diff --git a/.github/workflows/db-migration-test.yml b/.github/workflows/db-migration-test.yml index 9e8eeb8c8c..f6c93db3d0 100644 --- a/.github/workflows/db-migration-test.yml +++ b/.github/workflows/db-migration-test.yml @@ -17,7 +17,7 @@ jobs: migration-test: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-8' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-8' || 'ubuntu-latest' }} timeout-minutes: 30 env: DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} diff --git a/.github/workflows/deploy-on-v2-commit.yml b/.github/workflows/deploy-on-v2-commit.yml index 0a4f502166..a932581840 100644 --- a/.github/workflows/deploy-on-v2-commit.yml +++ b/.github/workflows/deploy-on-v2-commit.yml @@ -15,7 +15,7 @@ jobs: deploy-v2-on-push: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} concurrency: group: deploy-v2-push-V2 cancel-in-progress: true @@ -23,7 +23,7 @@ jobs: contents: read id-token: write env: - USE_DEPOT: ${{ needs.pick.outputs.is_fork != 'true' }} + USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' }} DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} steps: diff --git a/.github/workflows/docker-compose-tests.yml b/.github/workflows/docker-compose-tests.yml index 945f4883cb..1a1c53bc25 100644 --- a/.github/workflows/docker-compose-tests.yml +++ b/.github/workflows/docker-compose-tests.yml @@ -26,7 +26,7 @@ jobs: docker-compose-tests: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '4') }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '4') || 'ubuntu-latest' }} permissions: actions: write contents: read diff --git a/.github/workflows/e2e-live.yml b/.github/workflows/e2e-live.yml index 57a4357dad..f2904220b9 100644 --- a/.github/workflows/e2e-live.yml +++ b/.github/workflows/e2e-live.yml @@ -21,7 +21,7 @@ jobs: playwright-e2e-live: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }} timeout-minutes: 30 steps: - name: Harden Runner diff --git a/.github/workflows/e2e-stubbed.yml b/.github/workflows/e2e-stubbed.yml index ccfdf0052f..b16e538114 100644 --- a/.github/workflows/e2e-stubbed.yml +++ b/.github/workflows/e2e-stubbed.yml @@ -21,7 +21,7 @@ jobs: playwright-e2e: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }} steps: - name: Harden Runner uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 diff --git a/.github/workflows/frontend-backend-licenses-update.yml b/.github/workflows/frontend-backend-licenses-update.yml index cc9aa023e3..2bc36fb0c9 100644 --- a/.github/workflows/frontend-backend-licenses-update.yml +++ b/.github/workflows/frontend-backend-licenses-update.yml @@ -25,7 +25,7 @@ jobs: files-changed: name: detect what files changed needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} timeout-minutes: 3 outputs: licenses-frontend: ${{ steps.changes.outputs.licenses-frontend }} @@ -49,7 +49,7 @@ jobs: if: needs.files-changed.outputs.licenses-frontend == 'true' name: Generate Frontend License Report needs: [pick, files-changed] - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} permissions: contents: write pull-requests: write @@ -320,7 +320,7 @@ jobs: if: needs.files-changed.outputs.licenses-backend == 'true' needs: [pick, files-changed] name: Generate Backend License Report - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} permissions: contents: write pull-requests: write diff --git a/.github/workflows/frontend-validation.yml b/.github/workflows/frontend-validation.yml index 70187df412..ad689149db 100644 --- a/.github/workflows/frontend-validation.yml +++ b/.github/workflows/frontend-validation.yml @@ -16,7 +16,7 @@ jobs: frontend-validation: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} steps: - name: Harden Runner uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 diff --git a/.github/workflows/multiOSReleases.yml b/.github/workflows/multiOSReleases.yml index 7df9a49b46..88e38c5c97 100644 --- a/.github/workflows/multiOSReleases.yml +++ b/.github/workflows/multiOSReleases.yml @@ -42,7 +42,7 @@ jobs: determine-matrix: if: ${{ vars.CI_PROFILE != 'lite' }} needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} version: ${{ steps.versionNumber.outputs.versionNumber }} @@ -113,7 +113,7 @@ jobs: build-jars: needs: [pick, determine-matrix] - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} env: DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} strategy: @@ -639,7 +639,7 @@ jobs: collect-and-release: needs: [pick, determine-matrix, build, build-jars] - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} permissions: contents: write steps: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1801876bcd..eca963c060 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -19,7 +19,7 @@ jobs: playwright-all-browsers: name: Playwright (chromium + firefox + webkit) needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 diff --git a/.github/workflows/swagger.yml b/.github/workflows/swagger.yml index 9696aa419c..d6d9640f06 100644 --- a/.github/workflows/swagger.yml +++ b/.github/workflows/swagger.yml @@ -28,7 +28,7 @@ jobs: push: if: ${{ vars.CI_PROFILE != 'lite' }} needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} env: DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} steps: diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index 0a017d6273..ca00af04bc 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -21,6 +21,11 @@ on: required: false type: boolean default: true + minimal: + description: "Fast smoke build: Linux deb only, skip rpm and the flaky AppImage pass. Used by PR builds." + required: false + type: boolean + default: false workflow_dispatch: inputs: platform: @@ -38,6 +43,11 @@ on: required: false default: true type: boolean + minimal: + description: "Fast smoke build: Linux deb only, skip rpm and the flaky AppImage pass." + required: false + default: false + type: boolean permissions: contents: read @@ -386,10 +396,10 @@ jobs: with: projectPath: ./frontend/editor tauriScript: npx tauri - # Linux: build deb+rpm only here. AppImage runs in its own - # continue-on-error step below so its persistent linuxdeploy - # failure (#6127 onwards) does not tank deb/rpm uploads. - args: ${{ matrix.platform == 'ubuntu-22.04' && '--bundles deb,rpm' || matrix.args }} + # Linux: build deb+rpm only here (deb-only on minimal smoke builds). + # AppImage runs in its own continue-on-error step below so its + # persistent linuxdeploy failure (#6127 onwards) does not tank uploads. + args: ${{ matrix.platform == 'ubuntu-22.04' && (inputs.minimal && '--bundles deb' || '--bundles deb,rpm') || matrix.args }} - name: Build Tauri app (unsigned) if: ${{ !inputs.sign }} @@ -406,15 +416,16 @@ jobs: with: projectPath: ./frontend/editor tauriScript: npx tauri - # Linux: build deb+rpm only here. AppImage runs in its own - # continue-on-error step below so its persistent linuxdeploy - # failure (#6127 onwards) does not tank deb/rpm uploads. - args: ${{ matrix.platform == 'ubuntu-22.04' && '--bundles deb,rpm' || matrix.args }} + # Linux: build deb+rpm only here (deb-only on minimal smoke builds). + # AppImage runs in its own continue-on-error step below so its + # persistent linuxdeploy failure (#6127 onwards) does not tank uploads. + args: ${{ matrix.platform == 'ubuntu-22.04' && (inputs.minimal && '--bundles deb' || '--bundles deb,rpm') || matrix.args }} # AppImage is decoupled so its linuxdeploy run gets a fresh process # (rpm scratch state torn down) and its failure can't tank deb/rpm. + # Skipped on minimal smoke builds (flaky + slow, deb is enough to verify). - name: Build Tauri app (Linux AppImage) - if: matrix.platform == 'ubuntu-22.04' + if: matrix.platform == 'ubuntu-22.04' && !inputs.minimal continue-on-error: true uses: tauri-apps/tauri-action@84b9d35b5fc46c1e45415bdb6144030364f7ebc5 # v0.6.2 env: diff --git a/.github/workflows/test-build-docker.yml b/.github/workflows/test-build-docker.yml index c91ea0435a..ff7ac0637b 100644 --- a/.github/workflows/test-build-docker.yml +++ b/.github/workflows/test-build-docker.yml @@ -12,6 +12,11 @@ on: required: false type: string default: "false" + dockerfiles-changed: + description: "Whether any Dockerfile changed (forwarded from files-changed). Gates the slow arm64 build leg." + required: false + type: string + default: "false" depot_cores: description: "Depot runner vCPU count (used in runs-on). Override for benchmarking." required: false @@ -41,12 +46,12 @@ jobs: # `task backend:build:ci` produce equivalent JARs (verify before wiring). test-build-docker-images: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }} permissions: contents: read id-token: write env: - USE_DEPOT: ${{ needs.pick.outputs.is_fork != 'true' && inputs.docker-base-changed != 'true' }} + USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' && inputs.docker-base-changed != 'true' }} DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} strategy: fail-fast: false @@ -146,13 +151,22 @@ jobs: # GITHUB_EVENT_NAME is already provided by the runner. env: DOCKER_BASE_CHANGED: ${{ inputs.docker-base-changed }} + DOCKERFILES_CHANGED: ${{ inputs.dockerfiles-changed }} run: | if [ "$GITHUB_EVENT_NAME" = "pull_request" ] && [ "$DOCKER_BASE_CHANGED" = "true" ]; then + # Base Dockerfile changed: build against the locally-built base, + # which only exists for amd64. echo "base_image=stirling-pdf-base:pr-test" >> "$GITHUB_OUTPUT" echo "platforms=linux/amd64" >> "$GITHUB_OUTPUT" - else + elif [ "$DOCKERFILES_CHANGED" = "true" ]; then + # A Dockerfile changed: also verify the arm64 build (slow QEMU leg). echo "base_image=stirlingtools/stirling-pdf-base:latest" >> "$GITHUB_OUTPUT" echo "platforms=linux/amd64,linux/arm64/v8" >> "$GITHUB_OUTPUT" + else + # No Dockerfile change: amd64 only. arm64 is exercised on the base + # image publish and on release, not on every code PR. + echo "base_image=stirlingtools/stirling-pdf-base:latest" >> "$GITHUB_OUTPUT" + echo "platforms=linux/amd64" >> "$GITHUB_OUTPUT" fi # Base-changed PRs build the embedded image with the local docker driver @@ -214,12 +228,12 @@ jobs: test-build-unoserver-image: needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && format('depot-ubuntu-24.04-{0}', inputs.depot_cores || '8') || 'ubuntu-latest' }} permissions: contents: read id-token: write env: - USE_DEPOT: ${{ needs.pick.outputs.is_fork != 'true' && inputs.docker-base-changed != 'true' }} + USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' && inputs.docker-base-changed != 'true' }} DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} steps: - name: Harden Runner diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml index ec9b658326..7e87fc6d92 100644 --- a/.github/workflows/testdriver.yml +++ b/.github/workflows/testdriver.yml @@ -26,12 +26,12 @@ jobs: deploy: if: ${{ vars.CI_PROFILE != 'lite' }} needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} permissions: contents: read id-token: write env: - USE_DEPOT: ${{ needs.pick.outputs.is_fork != 'true' }} + USE_DEPOT: ${{ needs.pick.outputs.use_depot == 'true' }} DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }} steps: - name: Harden Runner @@ -154,7 +154,7 @@ jobs: if: always() name: detect what files changed needs: pick - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} timeout-minutes: 3 outputs: frontend: ${{ steps.changes.outputs.frontend }} @@ -175,7 +175,7 @@ jobs: test: if: needs.files-changed.outputs.frontend == 'true' needs: [pick, deploy, files-changed] - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} steps: - name: Harden Runner uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3 @@ -209,7 +209,7 @@ jobs: cleanup: needs: [pick, deploy, test] - runs-on: ${{ needs.pick.outputs.is_fork == 'true' && 'ubuntu-latest' || 'depot-ubuntu-24.04-4' }} + runs-on: ${{ needs.pick.outputs.use_depot == 'true' && 'depot-ubuntu-24.04-4' || 'ubuntu-latest' }} if: always() steps: diff --git a/settings.gradle b/settings.gradle index c712f672a1..aa90b41375 100644 --- a/settings.gradle +++ b/settings.gradle @@ -23,15 +23,17 @@ plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0' } -// Depot remote build cache. Silently no-ops when DEPOT_TOKEN is absent -// (local dev without depot login, and fork PRs where GitHub hides secrets), -// so contributors without Depot access still build fine on local cache only. +// Depot remote build cache. Disabled repo-wide via depotCacheEnabled below; +// flip it back to true to re-enable. Even when enabled it silently no-ops +// without DEPOT_TOKEN (local dev without depot login, and fork PRs where +// GitHub hides secrets), so contributors build fine on local cache only. buildCache { + def depotCacheEnabled = false def depotToken = System.getenv('DEPOT_TOKEN') local { enabled = true } - if (depotToken) { + if (depotCacheEnabled && depotToken) { remote(HttpBuildCache) { url = 'https://cache.depot.dev' enabled = true