swarm: the notification router tells a PR's author when CI on it fails or is cancelled
This commit is contained in:
parent
d4e58f8741
commit
c8eaa93268
1 changed files with 490 additions and 60 deletions
|
|
@ -12,11 +12,14 @@ 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` |
|
||||
| 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 |
|
||||
|
||||
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
|
||||
|
|
@ -39,12 +42,16 @@ router notices an unassign only on an issue it has seen an assign event for.
|
|||
|
||||
## The path
|
||||
|
||||
1. swarm-controller registers two instance-wide hooks, one for the `issues`
|
||||
and `issue_assign` events at `/webhook/forge/issues` and one for
|
||||
1. swarm-controller registers three instance-wide hooks, one for the `issues`
|
||||
and `issue_assign` events at `/webhook/forge/issues`, one for
|
||||
`pull_request`, `pull_request_assign`, `pull_request_sync` (a push to an
|
||||
open PR's branch) and the submitted-review events `pull_request_review_approved`,
|
||||
`pull_request_review_rejected` and `pull_request_review_comment` at `/webhook/forge/pull-request`. At each start it adds
|
||||
any of these events a registered hook lacks.
|
||||
`pull_request_review_rejected` and `pull_request_review_comment` at `/webhook/forge/pull-request`,
|
||||
and one for `workflow_run_failure` and `workflow_run_cancelled` (a finished CI run) at
|
||||
`/webhook/forge/workflow-run`. At each start it adds
|
||||
any of these events a registered hook lacks, except for the CI run events:
|
||||
Forgejo's hook edit never sets them, so the `workflow-run` hook gets them
|
||||
only when it's created. Adding a run event later means a new hook kind.
|
||||
2. On each delivery the controller checks the HMAC and publishes the body,
|
||||
unchanged, to the `SWARM_EVENTS` stream on
|
||||
`$SWARM.events.forge.<X-Forgejo-Event-Type>`, such as
|
||||
|
|
@ -78,7 +85,7 @@ 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 three flows above, each a source → match on `action` →
|
||||
The router ships the six flows above, each a source → match on `action` →
|
||||
todo, 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
|
||||
|
|
@ -93,7 +100,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, 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` or `workflow_run_cancelled`, and condition and recipient fields from the event's field list. The same goes for the `{field}`
|
||||
placeholders in a todo's key and text. 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`](../../2-handbook/swarm/ui.md#notification-flows) shows the document and
|
||||
|
|
@ -179,6 +186,33 @@ review once the classifier has approved:
|
|||
|
||||
The skip rule above applies: the router asks for argus's review once per head.
|
||||
|
||||
**CI runs as a source.** A finished CI run arrives as `workflow_run_failure`
|
||||
(a job failed, once every job has ended) or `workflow_run_cancelled`. The body
|
||||
holds the run, and the run holds the webhook that started it as a JSON string
|
||||
in `run.event_payload`. For a run on a PR that's the PR's own delivery, so the
|
||||
router reads the PR from it: `repo`, `number`, `title`, `url` and `author` are
|
||||
the PR's, `action` is the run's outcome (`failure` or `cancelled`), and
|
||||
`sender` is the account that triggered the run. A run that started from
|
||||
anything else, such as a push to a branch with no PR, names no PR and the
|
||||
router ignores it. The `author` field is the account that opened the issue or
|
||||
PR, so a flow can send to it:
|
||||
|
||||
| node | setting |
|
||||
| ------ | ------------------------------------------------------------- |
|
||||
| source | `workflow_run_failure` |
|
||||
| todo | `to` = field `author`, key `forge:{repo}#{number}:ci`, upsert |
|
||||
|
||||
A clear of one key, such as `ci-cleared`'s, leaves the agent in the issue's
|
||||
holders, because it may still hold the assignment todo that `closed` must find.
|
||||
Only a prefix clear drops the holder. An author whose CI ever failed gets
|
||||
the `closed` todo when their PR closes or merges, like an assignee.
|
||||
|
||||
A run reports in when it ends, and a push cancels the runs before it, so an old
|
||||
run can end after the push cleared the `:ci` todo. The router keeps the PR's
|
||||
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.
|
||||
|
||||
**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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue