name: Nix CI on: push: branches: [ main, master ] pull_request: branches: [ main, master ] workflow_dispatch: jobs: # Detect which workspaces have changed to save CI minutes filter: runs-on: ubuntu-latest outputs: workspaces: ${{ steps.detect.outputs.workspaces }} build_targets: ${{ steps.detect.outputs.build_targets }} any_changed: ${{ steps.detect.outputs.any_changed }} build_changed: ${{ steps.detect.outputs.build_changed }} global_changed: ${{ steps.detect.outputs.global_changed }} shared_crates_changed: ${{ steps.detect.outputs.shared_crates_changed }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Collect changed files env: EVENT_NAME: ${{ github.event_name }} BASE_REF: ${{ github.base_ref }} BEFORE_SHA: ${{ github.event.before }} HEAD_SHA: ${{ github.sha }} run: | set -euo pipefail if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then printf 'flake.nix\n' > changed-files.txt elif [[ "$EVENT_NAME" == "pull_request" ]]; then git fetch --no-tags --depth=1 origin "$BASE_REF" git diff --name-only "origin/$BASE_REF...$HEAD_SHA" > changed-files.txt elif [[ "$BEFORE_SHA" == "0000000000000000000000000000000000000000" ]]; then git diff-tree --no-commit-id --name-only -r "$HEAD_SHA" > changed-files.txt else git diff --name-only "$BEFORE_SHA" "$HEAD_SHA" > changed-files.txt fi if [[ ! -f changed-files.txt ]]; then : > changed-files.txt fi sed -n '1,200p' changed-files.txt - name: Detect changed workspaces id: detect run: | python3 scripts/ci_changed_workspaces.py \ --config nix/ci/workspaces.json \ --changed-files-file changed-files.txt \ --github-output "$GITHUB_OUTPUT" # Run CI gates for changed workspaces # Uses the provider-agnostic 'photoncloud-gate' defined in nix/ci/flake.nix gate: needs: filter if: ${{ needs.filter.outputs.any_changed == 'true' }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: workspace: ${{ fromJSON(needs.filter.outputs.workspaces) }} name: gate (${{ matrix.workspace }}) steps: - uses: actions/checkout@v4 - uses: DeterminateSystems/nix-installer-action@v11 - uses: DeterminateSystems/magic-nix-cache-action@v8 - name: Run PhotonCloud Gate run: | nix run ./nix/ci#gate-ci -- --workspace ${{ matrix.workspace }} --tier 0 --no-logs shared-crates-gate: needs: filter if: ${{ needs.filter.outputs.shared_crates_changed == 'true' }} runs-on: ubuntu-latest name: gate (shared crates) steps: - uses: actions/checkout@v4 - uses: DeterminateSystems/nix-installer-action@v11 - uses: DeterminateSystems/magic-nix-cache-action@v8 - name: Run Shared Crates Gate run: | nix run ./nix/ci#gate-ci -- --shared-crates --tier 0 --no-logs # Build server packages (tier 1+) build: needs: [filter, gate] if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') && needs.filter.outputs.build_changed == 'true' }} runs-on: ubuntu-latest strategy: matrix: target: ${{ fromJSON(needs.filter.outputs.build_targets) }} name: build (${{ matrix.target.package }}) steps: - uses: actions/checkout@v4 - uses: DeterminateSystems/nix-installer-action@v11 - uses: DeterminateSystems/magic-nix-cache-action@v8 - name: Build package run: | nix build .#${{ matrix.target.package }} --accept-flake-config # Summary job for PR status checks ci-status: needs: [filter, gate, shared-crates-gate] if: always() runs-on: ubuntu-latest steps: - name: Check CI Status run: | if [[ "${{ needs.gate.result }}" == "failure" ]]; then exit 1 fi if [[ "${{ needs.shared-crates-gate.result }}" == "failure" ]]; then exit 1 fi if [[ "${{ needs.filter.outputs.any_changed }}" == "true" || "${{ needs.filter.outputs.global_changed }}" == "true" ]]; then if [[ "${{ needs.gate.result }}" == "skipped" ]]; then echo "Gate was skipped despite changes. This is unexpected." exit 1 fi fi if [[ "${{ needs.filter.outputs.shared_crates_changed }}" == "true" ]]; then if [[ "${{ needs.shared-crates-gate.result }}" == "skipped" ]]; then echo "Shared crates gate was skipped despite crates/** changes. This is unexpected." exit 1 fi fi echo "CI passed or was correctly skipped."