WebHooker/docs/guide/message-format.md
RhenCloud fd6ccda411
fix(check): key check_run in-place edits on check name + head_sha
Providers that emit a fresh check run id per phase (e.g. Cloudflare Pages)
no longer post a new message for each status change; same name + commit
SHA now edits the existing message. Falls back to the run id when name or
head_sha is absent. Docs updated in sync.
2026-08-31 01:17:13 +08:00

36 lines
2.4 KiB
Markdown

# Message Format
Every event formatter produces a platform-neutral message (`NeutralMessage`), rendered by the platform drivers into a Discord embed or Telegram HTML message.
## Title
Every title must start with the repo, then an optional `#number`, then `: subject`:
```
{repo}{#number}: {subject} e.g. acme/widget#7: Add feature
```
The repo comes from `payload.repository.full_name` (falling back to a generic "repository" label when missing). Comments, reviews, and inline comments use the same `{repo}{#number}: {title}` title as their parent object — never `"Comment on org/repo"` prefixes.
## Links
Only the repo head is hyperlinked — never the whole title:
- **Discord** (embed titles cannot contain partial links): the title is the repo head `{repo}{#number}`, linked to the repository; the `: {subject}` text is rendered as the first line of the description, unlinked.
- **Telegram** (HTML supports inline links): the one-line title keeps the subject, with only the repo head wrapped in a link.
Messages whose title has no colon separator (a `:` followed by a space) keep the legacy whole-title link behavior.
Commit hashes, branches, and tags render as inline code wrapped in a hyperlink (e.g. ``[`abc123d`](https://…/commit/abc123def456)``), falling back to plain inline code when the repo base URL is unavailable.
## Emoji
Event-specific emoji are added by the formatters; per-group `Group.emoji` (default true) strips them all when disabled. Milestone progress bars are exempt. See [Message Language](./i18n).
## Forge Source Label
With `Group.forgeSources` (a list of `{ host, type, name? }` entries) the message footer names the matching source — the first entry whose type (`github` / `gitea`) matches the event's provider and whose host matches the repository URL's hostname, labeled with its optional `name` (falling back to the host) — so events from different forges can be told apart. See [Groups → Forge Source Label](./groups#forge-source-label).
## In-Place Updates
`workflow_run` and `check_run` messages are sent once and edited in place as the run progresses (queued → running → success/failure) — no duplicate messages. Tracking uses KV `msg:*` with a stable `updateKey` per run: `workflow_run` keys on the workflow id, while `check_run` keys on the check name + commit SHA (falling back to the run id) so deployments that emit a fresh run id per phase — e.g. Cloudflare Pages — still edit the same message.