diff --git a/.github/workflows/fullsend.yaml b/.github/workflows/fullsend.yaml index 3e2dba45f..ae036bcf8 100644 --- a/.github/workflows/fullsend.yaml +++ b/.github/workflows/fullsend.yaml @@ -202,6 +202,10 @@ jobs: && github.event.review.user.login == format('{0}-review[bot]', github.repository_owner) && github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name && !contains(github.event.pull_request.labels.*.name, 'fullsend-no-fix') + && ( + endsWith(github.event.pull_request.user.login, '[bot]') + || contains(github.event.pull_request.labels.*.name, 'fullsend-fix') + ) steps: - name: Build minimal payload id: payload diff --git a/.github/workflows/reusable-dispatch.yml b/.github/workflows/reusable-dispatch.yml index 553225836..a77e7d136 100644 --- a/.github/workflows/reusable-dispatch.yml +++ b/.github/workflows/reusable-dispatch.yml @@ -78,6 +78,7 @@ jobs: TRIGGERING_LABEL: ${{ github.event.label.name }} PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} PR_BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }} + PR_USER_LOGIN: ${{ github.event.pull_request.user.login }} ORG_NAME: ${{ github.repository_owner }} run: | set -euo pipefail @@ -185,8 +186,10 @@ jobs: if [[ -n "${PR_HEAD_REPO}" && -n "${PR_BASE_REPO}" ]]; then if [[ "${PR_HEAD_REPO}" == "${PR_BASE_REPO}" ]]; then if ! has_label "fullsend-no-fix" "${PR_LABELS}"; then - STAGE="fix" - TRIGGER_SOURCE="${REVIEW_USER_LOGIN}" + if [[ "${PR_USER_LOGIN}" =~ \[bot\]$ ]] || has_label "fullsend-fix" "${PR_LABELS}"; then + STAGE="fix" + TRIGGER_SOURCE="${REVIEW_USER_LOGIN}" + fi fi fi fi diff --git a/.github/workflows/reusable-fix.yml b/.github/workflows/reusable-fix.yml index a21a3af9e..1bf6054e7 100644 --- a/.github/workflows/reusable-fix.yml +++ b/.github/workflows/reusable-fix.yml @@ -238,7 +238,7 @@ jobs: echo "Fix iteration: ${ITERATION} (${FIX_COMMITS} previous fix commits)" >&2 echo "iteration=${ITERATION}" >> "${GITHUB_OUTPUT}" - - name: Check fullsend-no-fix label + - name: Check fix eligibility env: GH_TOKEN: ${{ steps.app-token.outputs.token }} TRIGGER_SOURCE: ${{ inputs.trigger_source }} @@ -246,12 +246,24 @@ jobs: SOURCE_REPO: ${{ inputs.source_repo }} run: | if [[ "${TRIGGER_SOURCE}" =~ \[bot\]$ ]]; then - HAS_NO_FIX=$(gh pr view "${PR_NUM}" --repo "${SOURCE_REPO}" \ - --json labels --jq '[.labels[].name] | any(. == "fullsend-no-fix")' 2>/dev/null || echo "false") + PR_INFO=$(gh pr view "${PR_NUM}" --repo "${SOURCE_REPO}" \ + --json labels,author --jq '{labels: [.labels[].name], author: .author.login}' 2>/dev/null \ + || echo '{"labels":[],"author":""}') + + HAS_NO_FIX=$(echo "${PR_INFO}" | jq -r '.labels | any(. == "fullsend-no-fix")') if [[ "${HAS_NO_FIX}" == "true" ]]; then echo "::warning::PR #${PR_NUM} has 'fullsend-no-fix' label — skipping bot-triggered fix" exit 1 fi + + PR_AUTHOR=$(echo "${PR_INFO}" | jq -r '.author') + if [[ ! "${PR_AUTHOR}" =~ \[bot\]$ ]]; then + HAS_FIX_LABEL=$(echo "${PR_INFO}" | jq -r '.labels | any(. == "fullsend-fix")') + if [[ "${HAS_FIX_LABEL}" != "true" ]]; then + echo "::warning::Human-authored PR #${PR_NUM} without 'fullsend-fix' label — skipping bot-triggered fix" + exit 1 + fi + fi fi - name: Checkout target repository at PR HEAD diff --git a/internal/scaffold/fullsend-repo/.github/workflows/dispatch.yml b/internal/scaffold/fullsend-repo/.github/workflows/dispatch.yml index 0d5d1301c..09cfad7ae 100644 --- a/internal/scaffold/fullsend-repo/.github/workflows/dispatch.yml +++ b/internal/scaffold/fullsend-repo/.github/workflows/dispatch.yml @@ -1,4 +1,4 @@ -# lint-workflow-size: max-lines=380 +# lint-workflow-size: max-lines=385 # Dispatcher workflow that routes events to agent workflows based on stage. # Routing logic determines the stage from event context — the shim only # forwards the raw event. Adding a new stage requires only a case branch @@ -41,6 +41,7 @@ jobs: TRIGGERING_LABEL: ${{ github.event.label.name }} PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} PR_BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }} + PR_USER_LOGIN: ${{ github.event.pull_request.user.login }} ORG_NAME: ${{ github.repository_owner }} run: | set -euo pipefail @@ -165,8 +166,10 @@ jobs: # Check no-fix label (use PR_LABELS — issue.labels is empty # on pull_request_review events) if ! has_label "fullsend-no-fix" "${PR_LABELS}"; then - STAGE="fix" - TRIGGER_SOURCE="${REVIEW_USER_LOGIN}" + if [[ "${PR_USER_LOGIN}" =~ \[bot\]$ ]] || has_label "fullsend-fix" "${PR_LABELS}"; then + STAGE="fix" + TRIGGER_SOURCE="${REVIEW_USER_LOGIN}" + fi fi fi fi