From e4e64e8cb67da27e50be367e198b02577df252b9 Mon Sep 17 00:00:00 2001 From: abrichr Date: Tue, 20 Oct 2026 01:29:30 -0400 Subject: [PATCH] ci: run every required workflow on merge_group; review every PR base Adds merge_group to Python CI, Packages, Secret Scan, Dependency Review, CodeQL and Platform manifest, so each required check (gitleaks, dependency-review, Analyze (python), run-ci (ubuntu-latest, 3.12), packages-gate) reports for a merge queue group. - Packages and desktop-build scope a group like a push to main: they diff the group's head against merge_group.base_sha and run the full matrix for the packages it touches. The Desktop build classifier treats merge_group as push. - dependency-review compares the group's base and head explicitly, since a group has no pull request in its payload. - dependency-review and CodeQL drop `branches: [main]` on pull_request, so a stacked PR reaches main with both checks already reported (#1358). Co-Authored-By: Claude Opus 5.5 --- .github/workflows/codeql.yml | 3 ++- .github/workflows/dependency-review.yml | 15 ++++++++++++++- .github/workflows/desktop-build.yml | 9 ++++++++- .github/workflows/main.yml | 2 ++ .github/workflows/packages.yml | 10 ++++++++++ .github/workflows/platform-manifest.yml | 2 ++ .github/workflows/secret-scan.yml | 2 ++ .../desktop/scripts/classify_build_changes.py | 10 ++++++---- .../desktop/tests/test_build_change_classifier.py | 7 +++++++ 9 files changed, 53 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 09e5964a3..a6658fba2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -4,8 +4,9 @@ name: CodeQL on: push: branches: [main] + # Every pull request, whatever its base, plus each merge queue group. pull_request: - branches: [main] + merge_group: schedule: - cron: "23 5 * * 1" diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 2756e4bad..00e93c022 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -2,8 +2,11 @@ name: Dependency Review # SOC 2: dependency-review (OA-C-24). Flags vulnerable/denied deps on PRs. on: + # Every pull request, whatever its base, so a stacked PR reaches main with + # this required check already reported. pull_request: - branches: [main] + # The merge queue tests each group before it lands on main. + merge_group: permissions: contents: read @@ -22,6 +25,16 @@ jobs: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Dependency Review + if: github.event_name != 'merge_group' uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 with: fail-on-severity: high + # A queue group has no pull request in its payload: compare the group's + # head with the main commit it was built on. + - name: Dependency Review (merge queue group) + if: github.event_name == 'merge_group' + uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 + with: + fail-on-severity: high + base-ref: ${{ github.event.merge_group.base_sha }} + head-ref: ${{ github.event.merge_group.head_sha }} diff --git a/.github/workflows/desktop-build.yml b/.github/workflows/desktop-build.yml index 6d4e5b044..2be51da54 100644 --- a/.github/workflows/desktop-build.yml +++ b/.github/workflows/desktop-build.yml @@ -35,12 +35,19 @@ jobs: env: BEFORE_SHA: ${{ github.event.before }} EVENT_NAME: ${{ github.event_name }} + GROUP_BASE_SHA: ${{ github.event.merge_group.base_sha }} shell: bash run: | set -euo pipefail changed_paths="${RUNNER_TEMP}/openadapt-desktop-changed-paths.txt" : > "${changed_paths}" - if [ "${EVENT_NAME}" = "push" ]; then + if [ "${EVENT_NAME}" = "merge_group" ]; then + # A queue group is scoped like a push to main: diff the group's + # head against the main commit it was built on. + BEFORE_SHA="${GROUP_BASE_SHA}" + git fetch --no-tags --depth=1 origin "${GROUP_BASE_SHA}" || true + fi + if [ "${EVENT_NAME}" = "push" ] || [ "${EVENT_NAME}" = "merge_group" ]; then before="${BEFORE_SHA}" if [ -z "${before}" ] || [ "${before}" = "0000000000000000000000000000000000000000" ]; then before="$(git rev-parse HEAD^)" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0a82abe9d..b831e627b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,6 +4,8 @@ on: pull_request: branches: - '**' + # The merge queue tests each group before it lands on main. + merge_group: push: branches: - main diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 64c3da981..01a495042 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -41,6 +41,8 @@ name: Packages on: pull_request: + # The merge queue tests each group before it lands on main. + merge_group: push: branches: [main] workflow_dispatch: @@ -80,6 +82,7 @@ jobs: env: EVENT_NAME: ${{ github.event_name }} BEFORE_SHA: ${{ github.event.before }} + GROUP_BASE_SHA: ${{ github.event.merge_group.base_sha }} run: | set -euo pipefail all() { @@ -89,6 +92,13 @@ jobs: case "$EVENT_NAME" in workflow_dispatch) all ;; pull_request) base="HEAD^1" ;; # the PR merge commit's first parent is the base tip + # A queue group runs the full matrix (the PR tier ran one lane) + # for every package the group's PRs touch, measured from the main + # commit the group was built on. + merge_group) + base="$GROUP_BASE_SHA" + git cat-file -e "$base^{commit}" 2>/dev/null || all + ;; *) if [ -z "${BEFORE_SHA:-}" ] || [ "$BEFORE_SHA" = 0000000000000000000000000000000000000000 ] \ || ! git cat-file -e "$BEFORE_SHA^{commit}" 2>/dev/null; then diff --git a/.github/workflows/platform-manifest.yml b/.github/workflows/platform-manifest.yml index 0920b86ba..7fbacc084 100644 --- a/.github/workflows/platform-manifest.yml +++ b/.github/workflows/platform-manifest.yml @@ -8,6 +8,8 @@ on: pull_request: branches: - '**' + # The merge queue tests each group before it lands on main. + merge_group: push: branches: - main diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml index 2d5db93f0..02212b5f3 100644 --- a/.github/workflows/secret-scan.yml +++ b/.github/workflows/secret-scan.yml @@ -6,6 +6,8 @@ name: Secret Scan # invoke it directly and pin the version. Scans full git history on PRs + main. on: pull_request: + # The merge queue tests each group before it lands on main. + merge_group: push: branches: [main] diff --git a/packages/desktop/scripts/classify_build_changes.py b/packages/desktop/scripts/classify_build_changes.py index 2c41eb576..308d51518 100644 --- a/packages/desktop/scripts/classify_build_changes.py +++ b/packages/desktop/scripts/classify_build_changes.py @@ -4,9 +4,10 @@ request that changes the Tauri shell or its JavaScript locks also builds the Linux installer, so a native dependency bump compiles before it merges. Release candidates and explicit dispatches keep the complete platform matrix. A push -to protected ``main`` repeats the expensive matrix only when a dependency, -toolchain, packaging, or native-runtime input changed. The immutable native -release workflow always rebuilds every installer from its release tag. +to protected ``main``, and a merge queue group about to become ``main``, +repeats the expensive matrix only when a dependency, toolchain, packaging, or +native-runtime input changed. The immutable native release workflow always +rebuilds every installer from its release tag. """ from __future__ import annotations @@ -123,7 +124,8 @@ def classify_build_scope(event: str, changed_paths: Iterable[str]) -> BuildScope if native: return BuildScope(True, True, f"pull request changes the native shell: {native[0]}") return BuildScope(True, False, "representative pull-request sidecar") - if event != "push": + # A merge queue group is about to become main, so it gets main's scope. + if event not in ("push", "merge_group"): return BuildScope(True, True, f"unknown event {event!r}; fail toward full evidence") if not paths: diff --git a/packages/desktop/tests/test_build_change_classifier.py b/packages/desktop/tests/test_build_change_classifier.py index 8e87ddd4b..fb39a156a 100644 --- a/packages/desktop/tests/test_build_change_classifier.py +++ b/packages/desktop/tests/test_build_change_classifier.py @@ -85,3 +85,10 @@ def test_empty_push_fails_toward_the_complete_matrix() -> None: def test_absolute_or_parent_path_is_refused() -> None: with pytest.raises(ValueError, match="repository-relative"): classify_build_scope("push", ["../outside"]) + + +def test_merge_queue_group_is_scoped_like_main() -> None: + assert classify_build_scope("merge_group", ["src/App.tsx"]) == classify_build_scope( + "push", ["src/App.tsx"] + ) + assert classify_build_scope("merge_group", []).run_native is True