diff --git a/.gitea/workflows/qa-review.yml b/.gitea/workflows/qa-review.yml index 75c68351d..32c5325ab 100644 --- a/.gitea/workflows/qa-review.yml +++ b/.gitea/workflows/qa-review.yml @@ -10,19 +10,17 @@ # - `pull_request_target`: opened, synchronize, reopened # → initial status posts when PR opens / re-pushes # - `pull_request_review` types: [submitted] -# → re-evaluate when a team member submits an APPROVE review so -# the gate flips immediately (no wait for the next push or -# slash-command). Verified live: sop-tier-check.yml uses this -# same event and provably fires (produces -# `sop-tier-check / tier-check (pull_request_review)` contexts). -# The job-level `if:` guard checks -# `github.event.review.state == 'APPROVED' || 'approved'` so -# only APPROVE reviews run the evaluator; COMMENT and +# → defensive fallback. Empirical evidence (live status audit) +# `pull_request_review_approved` does not always fire on this +# Gitea instance, while `pull_request_review` does (verified +# by sop-tier-check live status context). The job guard checks +# both `github.event.review.type` and `github.event.review.state` +# so only APPROVE reviews run the evaluator; COMMENT and # REQUEST_CHANGES are skipped at the job level. -# Branch-protection requires the `(pull_request_target)` -# context variant, so the review-event path EXPLICITLY POSTS -# the required context via the API. Trust boundary preserved -# (BASE ref, no PR-head). +# - `pull_request_review_approved` +# → retained as a forward-compatible trigger in case a future +# Gitea version fires it reliably. The same job guard covers +# both events. # - comment refires are handled by `sop-checklist.yml` review-refire job # → `/qa-recheck` slash-command re-evaluates this gate. # Workflow name = `qa-review` ; job name = `approved`. @@ -99,6 +97,7 @@ on: types: [opened, synchronize, reopened] pull_request_review: types: [submitted] + pull_request_review_approved: permissions: contents: read @@ -115,8 +114,11 @@ jobs: # Comment-triggered refires live in sop-checklist.yml review-refire job. if: | github.event_name == 'pull_request_target' || + github.event_name == 'pull_request_review_approved' || (github.event_name == 'pull_request_review' && - (github.event.review.state == 'APPROVED' || github.event.review.state == 'approved')) + (github.event.review.type == 'pull_request_review_approved' || + github.event.review.state == 'APPROVED' || + github.event.review.state == 'approved')) runs-on: ubuntu-latest steps: - name: Privilege check (A1.1 — INFORMATIONAL log only, NOT a gate) @@ -187,7 +189,13 @@ jobs: # for the explicit status POST. Evaluator step stays on # SOP_TIER_CHECK_TOKEN (read-only) per deliberate security # separation: eval computes, POST writes, never the same cred. - if: github.event_name == 'pull_request_review' && always() + if: | + (github.event_name == 'pull_request_review_approved' || + (github.event_name == 'pull_request_review' && + (github.event.review.type == 'pull_request_review_approved' || + github.event.review.state == 'APPROVED' || + github.event.review.state == 'approved'))) + && always() env: GITEA_TOKEN: ${{ secrets.STATUS_POST_TOKEN }} GITEA_HOST: git.moleculesai.app diff --git a/.gitea/workflows/security-review.yml b/.gitea/workflows/security-review.yml index 35044f308..97e2be3a3 100644 --- a/.gitea/workflows/security-review.yml +++ b/.gitea/workflows/security-review.yml @@ -9,15 +9,18 @@ # # A1-α addendum (internal#760): review-event trigger added so the security # gate flips immediately when a team member submits an APPROVE review. -# Uses `pull_request_review` types: [submitted] — verified live via -# sop-tier-check.yml which provably fires this event (produces -# `sop-tier-check / tier-check (pull_request_review)` contexts). -# The job-level `if:` guard checks -# `github.event.review.state == 'APPROVED' || 'approved'` so only APPROVE -# reviews run the evaluator; COMMENT and REQUEST_CHANGES are skipped at -# the job level. Branch-protection requires the `(pull_request_target)` -# context variant, so the review-event path EXPLICITLY POSTS the required -# context via the API. Trust boundary preserved (BASE ref, no PR-head). +# We listen to BOTH `pull_request_review` (types: [submitted]) and +# `pull_request_review_approved`. Empirical evidence (live status audit) +# `pull_request_review_approved` does not always fire on this Gitea +# instance, while `pull_request_review` does (verified by sop-tier-check +# live status context). The job guard checks both +# `github.event.review.type` and `github.event.review.state` so only +# APPROVE reviews run the evaluator; COMMENT and REQUEST_CHANGES are +# skipped at the job level. `pull_request_review_approved` is retained +# as a forward-compatible trigger. Branch-protection requires the +# `(pull_request_target)` context variant, so the review-event path +# EXPLICITLY POSTS the required context via the API. Trust boundary +# preserved (BASE ref, no PR-head). name: security-review @@ -26,6 +29,7 @@ on: types: [opened, synchronize, reopened] pull_request_review: types: [submitted] + pull_request_review_approved: permissions: contents: read @@ -42,8 +46,11 @@ jobs: # Comment-triggered refires live in sop-checklist.yml review-refire job. if: | github.event_name == 'pull_request_target' || + github.event_name == 'pull_request_review_approved' || (github.event_name == 'pull_request_review' && - (github.event.review.state == 'APPROVED' || github.event.review.state == 'approved')) + (github.event.review.type == 'pull_request_review_approved' || + github.event.review.state == 'APPROVED' || + github.event.review.state == 'approved')) runs-on: ubuntu-latest steps: - name: Privilege check (A1.1 — INFORMATIONAL log only, NOT a gate) @@ -100,7 +107,13 @@ jobs: # for the explicit status POST. Evaluator step stays on # SOP_TIER_CHECK_TOKEN (read-only) per deliberate security # separation: eval computes, POST writes, never the same cred. - if: github.event_name == 'pull_request_review' && always() + if: | + (github.event_name == 'pull_request_review_approved' || + (github.event_name == 'pull_request_review' && + (github.event.review.type == 'pull_request_review_approved' || + github.event.review.state == 'APPROVED' || + github.event.review.state == 'approved'))) + && always() env: GITEA_TOKEN: ${{ secrets.STATUS_POST_TOKEN }} GITEA_HOST: git.moleculesai.app