Screenery

Docs / Channels and promotion

Chat notifications

A rule can post to a Slack, Discord or Microsoft Teams channel when a build changes screenshots, when someone approves or rejects a channel, or after a rule promotes. You add the channel once, test it, and end a rule with "post to" it.

Adding a chat target

On the channels screen, an admin adds a target under Chat notifications: the platform, a name such as #design, and the channel's incoming-webhook URL.

PlatformWhere the URL comes from
SlackAn app with Incoming Webhooks, one URL per channel.
DiscordChannel settings → Integrations → Webhooks.
Microsoft TeamsA Workflows "post to a channel when a webhook request is received" flow, or an Incoming Webhook connector.

The URL is a password. Anyone who has it can post into that channel, so Screenery stores it encrypted and never shows it again.

After you add a target, the console shows only its host and last four characters. To change the URL, add the target again and point the rule at the new one. A target a rule still posts to cannot be removed.

Send a test posts a message that says it is a test, straight away, and shows what the chat service answered. A 404 usually means the URL was revoked or belongs to another platform.

Notify rules

+ notify rule starts a rule that posts when a build changes something. The document is a promotion rule with a notify action:

{
  "on": "build.finalized",
  "filter": { "conditions": { "branch": "main", "has_changes": true } },
  "actions": [
    { "kind": "notify_slack", "target": "ntg_…" }
  ]
}

The rule sentence reads it back as "When a build finalizes from branch main with changes, post to #design on Slack." The target is the target's id, never its URL, and the console picks it from the list by name.

ActionPosts to
notify_slackA Slack target.
notify_discordA Discord target.
notify_teamsA Microsoft Teams target.
onFires
build.finalized Once per push, when its build finalizes. Bound repository or not.
review.submitted When someone approves or rejects a channel, in the console or through an agent.
asset.wilted Once a day at most, listing the screenshots that started wilting: nobody pushes them any more. See Screenshots nobody pushes any more.

A build.finalized, review.submitted or asset.wilted rule can only post. It cannot promote or prune.

Release, pull-request and push rules can post too. Add a notify action after a promote, and the message says what the rule did: "promoted main → latest", or that it failed.

Conditions

Narrow a build, review or wilting rule with filter.conditions. Every condition you give must hold.

ConditionHolds when
channel A channel the build moved, the reviewed channel, or the channel watched for wilting, matches. pr-* matches every pull request.
branch The build's branch matches. release/* stops at a slash; ** does not. Builds only.
has_changes true: a screenshot changed or was removed. false: none did. Builds only.
worst_at_least The worst change is at least minor, moderate or major. Builds only.
mode monitoring: a screenery clip of a live page. ci: every other push. Builds only. See Monitoring.
verdict approve or reject. Reviews only.
still_served true: at least one of the wilting screenshots was requested in the last 7 days. false: none was. Wilting only. Until delivery metering has counted anything the rule waits, with the reason in the log, and gets those screenshots on the first day after it has.

Grades come from the push. A push graded nothing (for example, its first push, or a CLI that does not grade) has no changes as far as a rule can tell, and the rule log says that no screenshot was graded. A build its conditions skip still shows as not run in the log, with the reason.

What a message says

A build message is the top of the PR comment: how many screenshots were pushed, how many changed and how badly, the branch and channels, and a link to the build or pull request in the console. When several screenshots changed the same way, the message says it once: "1 change across 40 screenshots", with the first few names and one picture of it. Changes your flake ledger ignores are counted as "ignored as known flakes", not as changes.

Pictures are attached only for public screenshots.

For a public screenshot, the message carries its immutable @v_… URL, which Slack, Discord and Teams preview as an image. An unlisted or private screenshot is never attached and no signed URL or token is ever put in a chat message; the message says the changed screenshots are not public instead. Branch names, screenshot names and review notes are escaped, so none of them can mention @everyone or hide a link behind other text. A web address typed into a review note still shows as itself, and the chat app may make it clickable.

When it is sent

A rule queues its message, and it is usually posted within a minute or two; when the outbound queue is busy, it waits for a later run. If the chat service does not answer with success, it is attempted up to six times over about five hours, then marked failed on the target. Screenery refuses to post to private or internal network addresses and does not follow redirects, so paste the channel's final URL.

The target row on the channels screen shows the last message's result. Every rule run, including the ones it skipped, is in the rule log.