name: CI (On Pull-Request) run-name: >- ${{ github.event_name }} / PR #${{ github.event.pull_request.number }} / ${{ github.event.action }} / ${{ github.event.pull_request.head.label }} on: pull_request: types: - opened - synchronize - reopened pull_request_target: types: - opened - synchronize - reopened - ready_for_review concurrency: # Keep only the newest run per PR and event type. # This avoids pull_request and pull_request_target cancelling each other. group: pr-ci-${{ github.repository }}-${{ github.event_name }}-pr-${{ github.event.pull_request.number }} cancel-in-progress: true permissions: actions: read contents: read packages: write security-events: write jobs: detect-pr-scope: name: 🔎 Detect PR scope if: ${{ github.event_name == 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository }} runs-on: ubuntu-latest outputs: scope: ${{ steps.resolve.outputs.scope }} run_ci_orchestrator: ${{ steps.resolve.outputs.run_ci_orchestrator }} steps: - name: Checkout uses: actions/checkout@v6 - name: Resolve PR scope id: resolve env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPOSITORY: ${{ github.repository }} PR_NUMBER: ${{ github.event.pull_request.number }} run: ./scripts/meta/resolve/pr/scope.sh validate-pr-branch-prefix: name: 🧭 Validate PR branch prefix needs: detect-pr-scope if: ${{ github.event_name == 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 - name: Validate branch prefix for detected scope env: PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} PR_SCOPE: ${{ needs.detect-pr-scope.outputs.scope }} run: ./scripts/meta/resolve/pr/branch_prefix.sh pr-scope-gate: name: 🚦 Gate PR scope needs: - detect-pr-scope - validate-pr-branch-prefix if: ${{ needs.detect-pr-scope.outputs.run_ci_orchestrator == 'false' }} runs-on: ubuntu-latest steps: - name: Confirm lightweight PR scope shell: bash run: | set -euo pipefail echo "Lightweight PR scope '${{ needs.detect-pr-scope.outputs.scope }}' passed." ci-orchestrator: needs: - detect-pr-scope - validate-pr-branch-prefix if: ${{ github.event_name == 'pull_request' && needs.detect-pr-scope.outputs.run_ci_orchestrator == 'true' }} uses: ./.github/workflows/ci-orchestrator.yml with: distros: "arch debian ubuntu fedora centos" prepare-fork-merge-ref: needs: - detect-pr-scope - validate-pr-branch-prefix if: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository && needs.detect-pr-scope.outputs.run_ci_orchestrator == 'true' }} runs-on: ubuntu-latest outputs: checkout_ref: ${{ steps.out.outputs.checkout_ref }} image_tag: ${{ steps.out.outputs.image_tag }} steps: - name: Checkout uses: actions/checkout@v6 - name: Resolve merge ref and image tag id: out env: PR_NUMBER: ${{ github.event.pull_request.number }} PR_MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha || '' }} run: ./scripts/meta/resolve/pr/merge_ref.sh build-ci-images-fork: needs: prepare-fork-merge-ref uses: ./.github/workflows/build-ci-images.yml with: distros: "arch debian ubuntu fedora centos" checkout_ref: ${{ needs.prepare-fork-merge-ref.outputs.checkout_ref }} image_tag: ${{ needs.prepare-fork-merge-ref.outputs.image_tag }} concurrency_channel: pr-target-build-producer secrets: inherit images-mirror-missing-fork: needs: prepare-fork-merge-ref uses: ./.github/workflows/images-mirror-missing.yml with: repo_root: _pr_source source_repository: ${{ github.repository }} source_ref: ${{ needs.prepare-fork-merge-ref.outputs.checkout_ref }} source_path: _pr_source concurrency_channel: pr-target-mirror-producer concurrency_key: pr-${{ github.event.pull_request.number }} secrets: inherit