Skip to content

Announce a release to a chat channel

Goal: have a release say so in Discord, without a person posting it.

Configure the adapter

In .colophon.yaml:

announce:
  discord:
    webhook: $DISCORD_RELEASE_WEBHOOK
    when: minor

webhook names an environment variable. It is not the URL. A literal is refused when the file is parsed, because .colophon.yaml is committed and a webhook URL lets anyone holding it post to your channel.

when is the smallest release this adapter announces — any, patch, minor or major. It is the size of the release, not the shape of its version, so it works for a project whose versions are not semver. On such a project any is the sentence that means something.

Supply the webhook

Set DISCORD_RELEASE_WEBHOOK as a CI variable, masked and protected. Protected matters: if your release tags are protected — and they should be — an unprotected variable will not reach the tag pipeline, and the job will quietly announce nothing because it has no webhook to post to.

In this estate it is already a group-level variable, so most projects need no per-project setting.

Announce to more than one channel

Name the channels under channels, each with its own webhook variable and, if it wants one, its own when:

announce:
  discord:
    channels:
      releases:
        webhook: $DISCORD_RELEASES_WEBHOOK
        when: minor
      majors:
        webhook: $DISCORD_MAJORS_WEBHOOK
        when: major

Each webhook is one more CI variable, masked and protected like the first. The name is yours. It is what the report prints, and what --only takes when you re-send to one channel. The manifest reference has the rules.

Post through a bot instead

A webhook is one secret per channel. A bot is one token for every channel in a server, with the channel ids written in the manifest:

announce:
  discord:
    bot:
      token: $DISCORD_BOT_TOKEN
      guild: "1100000000000000000"
    channels:
      releases:
        channel: "1200000000000000000"
        when: minor
  1. Create a bot application for announcing, and invite it to the server with only View Channel and Send Messages in the announce channels.
  2. Set DISCORD_BOT_TOKEN as a CI variable, masked and protected.
  3. Turn on Developer Mode in Discord, then right-click the server and the channel to copy their ids.

A bot of its own is the recommendation, not a requirement. The token of a bot already running elsewhere works too, but a release job on it can race that bot to answer clicks on its own prompts, so keep its prompts out of the announce channels. A bot post is plain text, where a webhook's is an embed.

Run it after the release exists

announce reads the release object, so it goes after the job that creates one:

announce:
  stage: release
  image: registry.gitlab.com/phpboyscout/images/release-tools:v0.1.12
  rules:
    - if: '$CI_COMMIT_TAG'
  needs:
    - job: colophon-release
  script:
    - colophon --ci announce --tag "$CI_COMMIT_TAG"

The needs is the part worth getting right. Without it the job may run before the release exists, and announcing a release that is not there is refused — correctly, since the announcement would link to nothing.

What you will see

$ colophon announce --tag v1.4.0
  announced  discord

A release too small for the filter:

  skipped    discord — a patch release, and this announces minor or larger

And a failure:

  failed     discord — 502 Bad Gateway

1 of 1 did not go out. The release stands; nothing here failed the pipeline.

The exit code is zero in all three cases. By the time this runs the release is public; a red pipeline over a chat message is worse signal than a yellow one. If you want a failed announcement to be loud, watch for the warning line rather than the job status.

With channels, each has its own line:

  announced  discord releases
  failed     discord majors — discord refused the announcement: 502 Bad Gateway

If it announces twice

It will, if the job is retried. Announcing is the one thing colophon does that it cannot make idempotent — a webhook has no key to deduplicate on — so delivery is at least once and colophon does not pretend otherwise.

Retry a release job freely; retry the announce job only if you want the message again.

When one channel failed and the others did not, re-send to that one alone:

$ colophon announce --tag v1.4.0 --only discord.majors
  announced  discord majors

--only takes an adapter (discord) or one channel of it (discord.majors), as often as you like. A name the manifest does not configure is refused before anything is posted, with the names it does.

Why announcing is different has the reasoning.

If nothing is announced

what you see why
Nothing to announce to: .colophon.yaml names no adapters. no announce block, or an empty one
skipped discord — $DISCORD_RELEASE_WEBHOOK is empty in this job the variable is empty or absent in this job, often because it is protected and the tag is not
skipped discord — a patch release… when is larger than this release
announce: no release to announce the tag has no release object yet — check the needs

See also