an agent gets one todo when its pr starts conflicting with the target branch
This commit is contained in:
parent
32155f70aa
commit
11eb7dac9c
1 changed files with 963 additions and 21 deletions
|
|
@ -12,14 +12,16 @@ the way it did. An agent can get the same news from both.
|
|||
|
||||
## What an agent gets
|
||||
|
||||
| Flow | Event | The agent's todo |
|
||||
| -------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `assigned` | someone assigns an agent to an issue or PR | `you are assigned to issue <repo>#<n>: <title> (<url>)`, key `forge:<repo>#<n>:assignment` |
|
||||
| `unassigned` | someone takes an agent off an issue or PR | the same key rewritten: `you are not assigned to issue <repo>#<n> anymore: <title> (<url>)` |
|
||||
| `closed` | someone closes or merges the issue or PR | the router clears every router todo it queued for it, then queues `closed` on each agent that held one: `<kind> <repo>#<n> was closed: <title> (<url>)`, key `forge:<repo>#<n>:closed` |
|
||||
| `ci-failed` | a CI run on a PR finishes with a failed job | the PR's author gets `CI failed on PR <repo>#<n>: <title> (<url>)`, key `forge:<repo>#<n>:ci` |
|
||||
| `ci-cancelled` | a CI run on a PR gets cancelled | the same key rewritten: `CI was cancelled on PR <repo>#<n>: <title> (<url>)` |
|
||||
| `ci-cleared` | someone pushes to the PR's branch | the router clears the PR author's `:ci` todo, as the push starts a new run; the author's other todos for the PR stay |
|
||||
| Flow | Event | The agent's todo |
|
||||
| ------------------ | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `assigned` | someone assigns an agent to an issue or PR | `you are assigned to issue <repo>#<n>: <title> (<url>)`, key `forge:<repo>#<n>:assignment` |
|
||||
| `unassigned` | someone takes an agent off an issue or PR | the same key rewritten: `you are not assigned to issue <repo>#<n> anymore: <title> (<url>)` |
|
||||
| `closed` | someone closes or merges the issue or PR | the router clears every router todo it queued for it, then queues `closed` on each agent that held one: `<kind> <repo>#<n> was closed: <title> (<url>)`, key `forge:<repo>#<n>:closed` |
|
||||
| `ci-failed` | a CI run on a PR finishes with a failed job | the PR's author gets `CI failed on PR <repo>#<n>: <title> (<url>)`, key `forge:<repo>#<n>:ci` |
|
||||
| `ci-cancelled` | a CI run on a PR gets cancelled | the same key rewritten: `CI was cancelled on PR <repo>#<n>: <title> (<url>)` |
|
||||
| `ci-cleared` | someone pushes to the PR's branch | the router clears the PR author's `:ci` todo, as the push starts a new run; the author's other todos for the PR stay |
|
||||
| `conflict` | the controller finds that a PR no longer merges into its target branch | the PR's author gets `PR <repo>#<n> no longer merges into its target branch: <title> (<url>)`, key `forge:<repo>#<n>:conflict`, once until the PR merges again |
|
||||
| `conflict-cleared` | the controller finds that a conflicting PR merges again | the router clears the PR author's `:conflict` todo |
|
||||
|
||||
The todos are subsystem `router` in the agent's todo list. A todo under the
|
||||
same key replaces the one before, so an issue gives an agent one assignment
|
||||
|
|
@ -85,8 +87,8 @@ under a `todo` or a `request_reviewer`. The most is 64 nodes, 16
|
|||
levels deep, and 100 custom flows. A `todo` node sends to the agents an event
|
||||
field holds (`assignees_added`, `todo_holders`, …) or to one named agent.
|
||||
|
||||
The router ships the six flows above, each a source → match on `action` →
|
||||
todo, and `head-classifier`: source `pull_request` and `pull_request_sync` →
|
||||
The router ships the eight flows above, each a source → match on `action` →
|
||||
todo (`conflict` and `conflict-cleared` also match `mergeability_changed`), and `head-classifier`: source `pull_request` and `pull_request_sync` →
|
||||
match on `action` (`opened`, `reopened`, `synchronized`) and `draft` = `false`, or on
|
||||
`undrafted` → `request_reviewer` for `review-classifier` ([below](#requesting-a-review)). The code defines them
|
||||
(`swarm_wire::notify_flows::builtins`), so a build that changes one reaches
|
||||
|
|
@ -100,7 +102,7 @@ switched off, and the custom flows. Only the controller writes it, through
|
|||
compare-and-set. The controller answers 400 unless every flow passes the tree
|
||||
check above and reads only what exists: a source event from `issues`,
|
||||
`issue_assign`, `pull_request`, `pull_request_assign`, `pull_request_sync` or one of the
|
||||
three `pull_request_review_*` events, `workflow_run_failure` or `workflow_run_cancelled`, and condition and recipient fields from the event's field list. The same goes for the `{{ field }}`
|
||||
three `pull_request_review_*` events, `workflow_run_failure`, `workflow_run_cancelled` or `pull_request_mergeability`, and condition and recipient fields from the event's field list. The same goes for the `{{ field }}`
|
||||
variables in a todo's key and text, which are Jinja templates (see [`hive-template`](../../../hive-template/README.md)). A `PUT` must carry the `revision` it read, `0` for no
|
||||
document, and gets 409 when the stored revision is another. Swarm UI's
|
||||
[notification router card on `/swarm`](../web-ui/swarm-ui.md#notification-flows) shows the document and
|
||||
|
|
@ -213,6 +215,35 @@ head commit from the last delivery about the PR that wasn't a run. A run whose
|
|||
delivery names another head began before the latest push, and the router drops
|
||||
it. With no head kept yet, it can't tell and sends the todo.
|
||||
|
||||
**Merge conflicts as a source.** Forgejo sends no delivery when a push to a
|
||||
branch changes whether the PRs targeting it merge, and the router has no forge
|
||||
client. swarm-controller makes the event instead: on each `push` delivery on its
|
||||
instance-wide `push` hook, for a branch push that didn't delete the branch, it
|
||||
waits 30 seconds for the forge to recompute, then lists the open PRs that
|
||||
target the branch (one call per page of 50) and publishes one
|
||||
`pull_request_mergeability` event per PR to `$SWARM.events.forge`, where
|
||||
`action` is `conflicting` or `mergeable`. The body is a `pull_request`
|
||||
delivery, so `repo`, `number`, `title`, `url`, `author` and `assignees` read as
|
||||
for any PR.
|
||||
|
||||
Forgejo's `mergeable` flag is false for a conflict, for an error, for a draft
|
||||
and while the check still runs. The controller leaves drafts out and counts a
|
||||
PR as conflicting only when two reads 30 seconds apart both say false. A PR
|
||||
that reads undecided gets read again, up to four reads in all. One check runs
|
||||
per branch at a time; a push during it makes it run once more when it ends. A
|
||||
push to a branch with no open PR costs one list call. With open PRs that all
|
||||
merge it's still one; each PR that reads false or undecided adds a second read
|
||||
at least, and four is the most.
|
||||
|
||||
The event also carries `mergeability_changed`, which the router sets to `true`
|
||||
only when the event moves the PR into or out of conflict, judged against the
|
||||
`conflicting` flag it keeps per PR in its snapshot. `conflict` and
|
||||
`conflict-cleared` match on it, so a PR that stays in conflict across many
|
||||
pushes to its target branch gets the one todo, and a PR that merges and never
|
||||
conflicted gets nothing. The flag resets when the PR closes, so the router tells a reopened PR
|
||||
that still conflicts again. A PR whose author fixed it stays flagged
|
||||
until the next push to its target branch finds it merging.
|
||||
|
||||
**What the router runs.** It reads the key at most every 10 seconds, when an
|
||||
event arrives, and runs the built-ins you left on, then the custom flows that
|
||||
are on and pass the tree check. It logs a custom flow that fails the check,
|
||||
|
|
@ -239,7 +270,7 @@ holding such a node (a custom flow with one) as one it can't read and keeps the
|
|||
flows it had; it also has no `head-classifier`. A router that has `head-classifier`
|
||||
but predates the `draft` and `undrafted` fields requests the review of a draft PR
|
||||
as before. A router that has `request_reviewer`, with a
|
||||
controller that predates it, gets no answer to the request and logs that. A controller that predates this leaves the key absent, and the
|
||||
controller that predates it, gets no answer to the request and logs that. A router that predates the `conflict` flows ignores the `pull_request_mergeability` events a newer controller sends, and gives no conflict todos; a controller that predates them sends none, so the new flows never run. A controller that predates this leaves the key absent, and the
|
||||
router runs the built-ins as before. A router that predates this ignores the
|
||||
document, so the page and the API show a state the router isn't yet running.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue