Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/close-empty-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ name: Close Empty PR

on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]
types: [opened, synchronize, reopened, ready_for_review, closed]

concurrency:
group: close-empty-pr-${{ github.event.pull_request.base.repo.full_name || github.repository }}-${{ github.event.pull_request.number }}
Expand All @@ -21,7 +21,14 @@ permissions:
contents: read

jobs:
cancel-closed-pr-runs:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- run: echo "PR closed; this run only cancels older runs through workflow concurrency."

close-empty:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
steps:
- name: Close PR when it has no net changes
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/codeql-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ name: CodeQL PR

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, closed]
branches: [main, master, develop]

concurrency:
Expand All @@ -17,8 +18,15 @@ permissions:
contents: read

jobs:
cancel-closed-pr-runs:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- run: echo "PR closed; this run only cancels older runs through workflow concurrency."

detect-languages:
name: Detect CodeQL languages
if: github.event.action != 'closed'
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.detect.outputs.matrix }}
Expand Down Expand Up @@ -92,7 +100,7 @@ jobs:
analyze-merge:
name: CodeQL merge preview (${{ matrix.language }})
needs: detect-languages
if: github.event.pull_request.merge_commit_sha != ''
if: github.event.action != 'closed' && github.event.pull_request.merge_commit_sha != ''
runs-on: ubuntu-latest
permissions:
actions: read
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/noema-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Required Noema Review

on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]
types: [opened, synchronize, reopened, ready_for_review, closed]
workflow_run:
workflows: ["Required OpenCode Review", "Strix Security Scan"]
types: [completed]
Expand Down Expand Up @@ -39,6 +39,12 @@ permissions:
id-token: write

jobs:
cancel-closed-pr-runs:
if: github.event_name == 'pull_request_target' && github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- run: echo "PR closed; this run only cancels older runs through workflow concurrency."

noema-review:
name: noema-review
runs-on: ubuntu-latest
Expand All @@ -50,6 +56,7 @@ jobs:
)
|| (
github.event_name == 'pull_request_target'
&& github.event.action != 'closed'
&& github.event.pull_request.head.repo.full_name == github.repository
)
env:
Expand Down
19 changes: 17 additions & 2 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Required OpenCode Review

on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]
types: [opened, synchronize, reopened, ready_for_review, closed]
workflow_dispatch:
inputs:
pr_number:
Expand Down Expand Up @@ -45,12 +45,19 @@ permissions:
contents: read

jobs:
cancel-closed-pr-runs:
if: github.event_name == 'pull_request_target' && github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- run: echo "PR closed; this run only cancels older runs through workflow concurrency."

coverage-evidence:
name: coverage-evidence
if: >-
github.event_name == 'workflow_dispatch'
|| (
github.event_name == 'pull_request_target'
&& github.event.action != 'closed'
&& github.event.pull_request.head.repo.full_name == github.repository
)
runs-on: ubuntu-latest
Expand Down Expand Up @@ -825,7 +832,15 @@ jobs:
opencode-review-target:
name: opencode-review
needs: [coverage-evidence]
if: always() && (github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request_target')
if: >-
always()
&& (
github.event_name == 'workflow_dispatch'
|| (
github.event_name == 'pull_request_target'
&& github.event.action != 'closed'
)
)
runs-on: ubuntu-latest
timeout-minutes: 360
permissions:
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/osv-scanner-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ name: OSV-Scanner PR

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, closed]
branches: [main, master, develop]

concurrency:
Expand All @@ -19,7 +20,14 @@ permissions:
security-events: write

jobs:
cancel-closed-pr-runs:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- run: echo "PR closed; this run only cancels older runs through workflow concurrency."

osv-scan:
if: github.event.action != 'closed'
# ponytail: use upstream reusable PR workflow, don't hand-roll the diff scan
uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@9a498708959aeaef5ef730655706c5a1df1edbc2 # v2.3.8
permissions:
Expand Down
20 changes: 16 additions & 4 deletions .github/workflows/pr-review-merge-scheduler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [main, develop, master]
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review, auto_merge_enabled]
types: [opened, synchronize, reopened, ready_for_review, auto_merge_enabled, closed]
workflow_run:
workflows: ["Required OpenCode Review", "Strix Security Scan"]
types: [completed]
Expand Down Expand Up @@ -128,14 +128,26 @@ concurrency:
cancel-in-progress: true

jobs:
cancel-closed-pr-runs:
if: github.event_name == 'pull_request_target' && github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- run: echo "PR closed; this run only cancels older runs through workflow concurrency."

scan-pr-queue:
# workflow_dispatch review runs do not reliably carry pull_requests metadata.
# Without this guard, one completed central review can wake a repo-wide scan.
if: >-
github.event_name != 'workflow_run' ||
(
github.event.workflow_run.conclusion != 'cancelled' &&
github.event.workflow_run.pull_requests[0].number
github.event_name != 'pull_request_target' ||
github.event.action != 'closed'
) &&
(
github.event_name != 'workflow_run' ||
(
github.event.workflow_run.conclusion != 'cancelled' &&
github.event.workflow_run.pull_requests[0].number
)
)
runs-on: ubuntu-latest
permissions:
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/scorecard-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ name: Scorecard PR

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, closed]
branches: [main, master, develop]

concurrency:
Expand All @@ -23,8 +24,15 @@ permissions:
contents: read

jobs:
cancel-closed-pr-runs:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- run: echo "PR closed; this run only cancels older runs through workflow concurrency."

analysis:
name: Scorecard
if: github.event.action != 'closed'
runs-on: ubuntu-latest
permissions:
security-events: write
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ name: Security Scan

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review, closed]
branches: [main, master, develop]

concurrency:
Expand All @@ -40,7 +41,14 @@ permissions:
security-events: write

jobs:
cancel-closed-pr-runs:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- run: echo "PR closed; this run only cancels older runs through workflow concurrency."

osv-scan:
if: github.event.action != 'closed'
# ponytail: reuse upstream diff-scoped PR scanner instead of hand-rolling it
uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@9a498708959aeaef5ef730655706c5a1df1edbc2 # v2.3.8
permissions:
Expand All @@ -51,6 +59,7 @@ jobs:
fail-on-vuln: true

dependency-review:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down Expand Up @@ -103,6 +112,7 @@ jobs:
comment-summary-in-pr: on-failure

trivy-fs:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down Expand Up @@ -132,6 +142,7 @@ jobs:
category: trivy-fs

scorecard:
if: github.event.action != 'closed'
runs-on: ubuntu-latest
# SOFT: posture findings are unrelated to the PR diff, so never block merge.
continue-on-error: true
Expand Down
16 changes: 12 additions & 4 deletions .github/workflows/strix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches: [main, develop, master]
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review, closed]
schedule:
# Weekly scan on protected branches (Mondays at 03:00 UTC).
- cron: '0 3 * * 1'
Expand Down Expand Up @@ -39,10 +40,10 @@ concurrency:
github.event.inputs.pr_number != '' && github.event.inputs.pr_head_sha != '' &&
format('pr-{0}-{1}', github.event.inputs.pr_number, github.event.inputs.pr_head_sha) ||
github.event.inputs.pr_number != '' && format('pr-{0}', github.event.inputs.pr_number) || github.ref }}
# cancel-in-progress deliberately disabled: an attacker could force-push
# a benign commit to cancel an in-progress scan of a malicious commit. The
# head SHA in PR groups prevents stale scans from serializing newer evidence.
cancel-in-progress: false
# cancel-in-progress stays disabled for normal PR updates: an attacker could
# force-push a benign commit to cancel an in-progress scan of a malicious
# commit. Closed PR events only cancel older runs for the same PR/head group.
cancel-in-progress: ${{ github.event_name == 'pull_request_target' && github.event.action == 'closed' }}

permissions:
actions: read
Expand All @@ -52,7 +53,14 @@ permissions:
statuses: write

jobs:
cancel-closed-pr-runs:
if: github.event_name == 'pull_request_target' && github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- run: echo "PR closed; this run only cancels older runs through workflow concurrency."

strix:
if: github.event_name != 'pull_request_target' || github.event.action != 'closed'
timeout-minutes: 120
runs-on: ubuntu-latest
env:
Expand Down
32 changes: 32 additions & 0 deletions tests/test_required_workflow_queue_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,38 @@ def test_required_pull_request_workflows_cancel_superseded_runs() -> None:
assert "cancel-in-progress: true" in workflow


def test_pull_request_close_events_cancel_superseded_runs_without_heavy_jobs() -> None:
workflows = (
"close-empty-pr.yml",
"codeql-pr.yml",
"noema-review.yml",
"opencode-review.yml",
"osv-scanner-pr.yml",
"pr-review-merge-scheduler.yml",
"scorecard-pr.yml",
"security-scan.yml",
"strix.yml",
)

for filename in workflows:
workflow = workflow_text(filename)

assert "closed" in workflow
assert "cancel-closed-pr-runs:" in workflow
assert (
'PR closed; this run only cancels older runs through workflow concurrency.'
in workflow
)
assert "github.event.action != 'closed'" in workflow

strix = workflow_text("strix.yml")

assert (
"cancel-in-progress: ${{ github.event_name == 'pull_request_target' && "
"github.event.action == 'closed' }}"
) in strix


def test_cancelled_review_workflow_runs_do_not_spawn_more_queue_work() -> None:
for filename in ("noema-review.yml", "pr-review-merge-scheduler.yml"):
workflow = workflow_text(filename)
Expand Down
Loading