shahar1 opened a new pull request, #76672: URL: https://github.com/apache/airflow/pull/76672
<!-- HUMAN SUMMARY - AGENTS DO NOT MODIFY --> <!-- END OF HUMAN SUMMARY --> <details><summary>AI Summary</summary> ### Why The `main` and release-branch rulesets require `CI passed` and `CI run started` from any source. For a PR gated to fork CI, the Fork CI monitor posts `CI passed` as a commit status from the contributor's fork run. Adding `use project ci` released the PR to project CI but left that status at success. The PR stayed mergeable on the fork result, with or without auto-merge, while project CI was queued or had not started. #76536 shows it. Fork `CI passed` was posted at 13:34, `use project ci` was added at 13:36:52, the PR was closed and reopened at 13:36:55, project CI was queued at 13:37:01, and the PR merged at 13:38:29. Project CI was then cancelled. This was raised in the AIP-120 [VOTE] thread: https://lists.apache.org/thread/hh5p3j9cj66767lj3gpotfz8rgvkt0oh ### How While a PR carries `use project ci`, its head commit's `CI passed` status is never a fork result. It is `pending` until project CI's own `CI passed` job succeeds on that commit, and then `success`. - **At label time:** a new `pull_request_target: labeled` workflow (`fork-ci-project-ci-label.yml`) replaces any `CI passed` success not posted for project CI with `pending` ("Waiting for project CI (use project ci)"). - It never checks out or runs PR code, and event values go through `env:`. - Permissions: `statuses: write` and `actions: read`. - It waits until no `fork-ci-monitor.yml` run is queued or in progress, then revokes again. That covers a monitor run that read the PR before the label. A monitor run takes about 2 minutes (median 99 s, max 120 s over the last 40), so the wait is capped at 10 minutes and the job at 14. GitHub ends single-CPU runner jobs after 15 minutes. - **In the monitor, before the main loop:** it lists the head SHAs of open PRs labelled `use project ci` and writes no `CI passed` on them; `report_project_ci_passed` owns those SHAs. Statuses belong to a commit, so this also covers a second PR opened from the same branch. - **In the monitor, before posting any fork `success`:** it reads the PR itself (`GET pulls/{n}`) and the open PRs of the same head branch, not through search. It skips the post when one now carries the label or the head moved. The label search can lag by minutes. - **In the monitor, after the main loop:** `report_project_ci_passed` posts `success` once the newest project CI run on the head commit (any of `PROJECT_CI_WORKFLOW_FILES`) has a `CI passed` check run that succeeded. Otherwise it revokes any success. - It falls back to REST when the GraphQL search does not list the head commit, for example after a rebase that keeps old commit dates. - Revocations are never budget-limited, and successes count against the per-run status budget. - An error on one PR does not stop the others. - **If the labelled-PR search fails:** that run posts no fork success at all, but still posts revocations. ### What this does not do - **Project CI does not start automatically.** A maintainer still starts it as today, by close/reopen or a push. GitHub does not create workflow runs for events caused by `GITHUB_TOKEN`, except `workflow_dispatch` and `repository_dispatch`. Adding `labeled` to `ci-amd.yml` would run CI on every label and cancel runs in progress. This PR only makes sure nothing merges on the fork result in the meantime. - **The merge waits for the monitor.** After project CI passes, the PR stays blocked until the next monitor run posts `success`, which takes up to about 15 minutes. GitHub does not document how a required context is resolved when a commit status and a check run share the name `CI passed`, so the status must not be left `pending`. - **Known gaps (documented):** - A duplicate PR from a different branch at the same commit is not found by the live check. - The rulesets accept `CI passed` from any source, so a PR that changes workflows can produce its own `CI passed` check run. This is not new and applies to every project-CI PR; reviewers still have to check CI-file changes. ### Verification | Check | Result | |---|---| | `uv run --project dev/breeze pytest dev/breeze/tests/test_fork_ci_reconcile.py dev/breeze/tests/test_fork_ci_messages.py dev/breeze/tests/test_fork_ci_gate.py -q` | 494 passed | | `prek` on the changed files (yamllint, zizmor, ruff, mypy-dev included) | Passed | | GraphQL fields and REST fields (`check_runs[].check_suite.id`, workflow run `check_suite_id`), queried read-only against live apache/airflow commits | Present and matching | | `checkRuns(filterBy: {checkName})` on a commit with a re-run | Returns only the latest attempt | | `pulls?state=open&head=<owner>:<branch>` | Lists fork PRs. `commits/{sha}/pulls` and `associatedPullRequests` do not, so they are not used | | Two independent reviews, four rounds | Findings addressed or documented above | **Not tested:** the new workflow and the new API calls have not run on GitHub. All tests use mocks, and the shell logic was only checked locally with a stubbed `gh`. The first real test is a `use project ci` label after merge. related: #76536 </details> --- ##### Was generative AI tooling used to co-author this PR? - [X] Yes — Claude Code (Opus 5.5, with Sonnet 5.5 and Opus 5.5 subagents) Generated-by: Claude Code (Opus 5.5) following [the guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions) 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
