diff --git a/.github/workflows/ci-cursor-review.yml b/.github/workflows/ci-cursor-review.yml new file mode 100644 index 0000000..26f9028 --- /dev/null +++ b/.github/workflows/ci-cursor-review.yml @@ -0,0 +1,46 @@ +name: CI - Cursor Review + +# Thin caller enrolling THIS repo in its own reusable cursor-review workflow. +# The review logic (panel matrix, judge consolidation, prompts, scripts) lives +# in cursor-review.yml in this same repo, but the caller still pins it by full +# commit SHA like every external consumer: a local `uses: ./...` path would run +# the PR's OWN copy of the reviewer, letting a PR weaken the panel judging it. +# Pinning to a merged main SHA keeps the reviewer tamper-proof; the bump-callers +# workflow keeps the pin fresh (this repo is enrolled in CURSOR_REVIEW_CALLERS). +# +# Label-triggered for now (apply `cursor-review` to a PR to fire the panel; +# `skip-cursor-review` vetoes) — the reusable's gate at this pin only honors +# label events. Once the pin advances past the commit adding the reusable's +# `run_without_label` input, the auto-bump PR for this file should also add +# `run_without_label: true` under `with:` and widen the trigger types to +# [opened, reopened, ready_for_review, labeled, unlabeled] — this repo has no +# labeling automation, and every non-draft PR here is worth a review (its +# files become other repos' required checks). + +on: + pull_request: + types: [labeled, unlabeled] + +# Cancel any earlier in-flight review run for the same PR when cursor-review is +# removed or re-applied. Scoping by label name ensures that removing an +# unrelated label does not kill a running cursor review. +concurrency: + group: cursor-review-pr-${{ github.event.pull_request.number }}-${{ github.event.label.name }} + cancel-in-progress: true + +jobs: + cursor-review: + permissions: + contents: read + pull-requests: write + uses: Comfy-Org/github-workflows/.github/workflows/cursor-review.yml@fe6b08e278c27ceacf2651cf441d0752ca2e78ee # main (fe6b08e) + with: + # Keep the assets ref in lock-step with the `uses:` ref above. + workflows_ref: fe6b08e278c27ceacf2651cf441d0752ca2e78ee + # No vendored/generated content in this repo; defensive excludes only. + diff_excludes: >- + :!**/*-lock.json + :!**/dist/** + secrets: + CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }} + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} diff --git a/.github/workflows/ci-detect-unreviewed-merge.yml b/.github/workflows/ci-detect-unreviewed-merge.yml new file mode 100644 index 0000000..b377fbb --- /dev/null +++ b/.github/workflows/ci-detect-unreviewed-merge.yml @@ -0,0 +1,32 @@ +# Caller enrolling THIS repo in its own reusable unreviewed-merge detector. +# Named ci-detect-unreviewed-merge.yml because the canonical caller path +# (detect-unreviewed-merge.yml) is occupied here by the reusable itself. +# Otherwise a verbatim copy of the template in +# Comfy-Org/unreviewed-merges/detector/detect-unreviewed-merge.yml. +# +# PREREQUISITE (operator): provision `secrets.UNREVIEWED_MERGES_TOKEN` in this +# repo's settings (see the unreviewed-merges repo README). Until it exists, +# this job fails loudly on pushes to main — deliberately, so enrollment is +# never silently inert. + +name: Detect Unreviewed Merge + +on: + push: + branches: [main] + +concurrency: + group: detect-unreviewed-merge-${{ github.sha }} + cancel-in-progress: false + +permissions: + contents: read + pull-requests: read + +jobs: + detect: + uses: Comfy-Org/github-workflows/.github/workflows/detect-unreviewed-merge.yml@4d9cb6b87f953bb7cd69954280e1465fb9bd2040 # v1 + with: + approval-mode: latest-per-reviewer + secrets: + UNREVIEWED_MERGES_TOKEN: ${{ secrets.UNREVIEWED_MERGES_TOKEN }} diff --git a/.github/workflows/cursor-review.yml b/.github/workflows/cursor-review.yml index cd9d447..c575012 100644 --- a/.github/workflows/cursor-review.yml +++ b/.github/workflows/cursor-review.yml @@ -107,6 +107,16 @@ on: type: string required: false default: '' + run_without_label: + description: >- + Run on plain pull_request events (opened / reopened / ready_for_review + / synchronize) instead of requiring the trigger label — for repos with + no labeling automation. The fork skip, the skip-cursor-review label, + and the same-commit dedupe all still apply. Default false + (label-triggered, unchanged for existing callers). + type: boolean + required: false + default: false secrets: CURSOR_API_KEY: description: Cursor API key for cursor-agent (the panel + judge models bill through it). @@ -149,6 +159,7 @@ jobs: GH_EVENT_ACTION: ${{ github.event.action }} HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} BASE_REPO: ${{ github.repository }} + RUN_WITHOUT_LABEL: ${{ inputs.run_without_label }} run: | # PRs from forks can't run this review. The pull_request event grants # fork PRs no access to secrets — so CURSOR_API_KEY is empty and every @@ -170,6 +181,20 @@ jobs: exit 0 fi + # Label-free mode (run_without_label input): callers in repos with no + # labeling automation opt in to running on plain PR events. Sits + # BELOW the fork skip and skip-cursor-review checks — those still + # veto — and the same-commit dedupe below still prevents re-reviews. + if [ "$RUN_WITHOUT_LABEL" = "true" ]; then + case "$GH_EVENT_ACTION" in + opened|reopened|ready_for_review|synchronize) + echo "run_without_label mode — running on '$GH_EVENT_ACTION'." + echo "should_run=true" >> "$GITHUB_OUTPUT" + exit 0 + ;; + esac + fi + # Only adding the trigger label fires the matrix. Removing it cancels # any in-progress run via the concurrency group and then no-ops here. if [ "$LABEL_NAME" = "$REVIEW_LABEL" ] && [ "$GH_EVENT_ACTION" = "labeled" ]; then