diff --git a/.github/scripts/pr-triage-act.sh b/.github/scripts/pr-triage-act.sh index 7098852a8b..41732125ef 100644 --- a/.github/scripts/pr-triage-act.sh +++ b/.github/scripts/pr-triage-act.sh @@ -182,10 +182,34 @@ eval_status_state() { } eval_run_exists_for_head() { - local count - count=$(gh api "repos/$REPO/actions/workflows/evaluation.yml/runs?head_sha=$HEAD_SHA" \ - --jq '.total_count // (.workflow_runs | length)') - [ "${count:-0}" -gt 0 ] + # Decide whether a *real* evaluation has already run (or is running) for the + # current head_sha. Filtering by event alone is not reliable: every PR push + # produces placeholder status runs (`pr-status` on pull_request, and + # `fork-pr-status` on pull_request_target — the latter concludes "success", + # not "skipped"), so an event/conclusion filter would count those and we'd + # never apply the evaluate-now label. See + # https://github.com/dotnet/skills/pull/703 and + # https://github.com/dotnet/skills/pull/720 for the original repro. + # + # The reliable discriminator is whether the run actually executed the `gate` + # job (the /evaluate and evaluate-now label entry points) or the `discover` + # job (manual/scheduled runs). In placeholder status runs both of those jobs + # are present but conclusion=="skipped"; in a real evaluation at least one of + # them is non-skipped (success/failure, or null while still in progress). + local run_ids + run_ids=$(gh api --paginate "repos/$REPO/actions/workflows/evaluation.yml/runs?head_sha=$HEAD_SHA" \ + --jq '.workflow_runs[].id') + [ -z "$run_ids" ] && return 1 + local id real + for id in $run_ids; do + real=$(gh api --paginate "repos/$REPO/actions/runs/$id/jobs" \ + --jq '[.jobs[] | select((.name == "gate" or .name == "discover") and .conclusion != "skipped")] | length' \ + | awk '{s+=$1} END{print s+0}') + if [ "${real:-0}" -gt 0 ]; then + return 0 + fi + done + return 1 } # ----------------------------------------------------------------------