Skip to main content
Version: 0.1 (next)

Slack

Infrared has one Slack app per installation, and every org connects its own Slack workspaces to it: usually its own, and perhaps a community Slack too. The org then chooses destinations, the channels Infrared posts to, and for each one what goes there:

KindWhat it is
Summary videoseach new summary video, playing inline, with what shipped, where it runs and a link to the Change
Product owner announcementseach new product owner announcement video, the same way
Announce draftsthe drafts of Announce and the go-to-market workflows, for people to read

Everything Infrared posts goes to every destination that takes its kind, so an announcement can go to #announcements in your own Slack and #releases in a community Slack at once. A Product can add its own destinations or use only its own.

Set up the Slack app (once, a platform admin)​

  1. In Infrared, open Settings → Slack. A platform admin sees the steps and a ready-made app manifest, with this installation's redirect URL (https://<host>/api/v1/slack/oauth/callback) filled in. Copy it.

  2. At api.slack.com/apps, choose Create New App → From an app manifest, pick a workspace to own the app (any workspace you administer), paste the manifest, and create the app. The manifest asks for these bot scopes:

    ScopeWhy
    chat:write, chat:write.publicpost to the chosen channels, including public channels the app hasn't joined
    files:write, files:readupload the videos so they play in Slack, and read the post's link
    channels:read, groups:readlist channels for the picker (private ones only when the app is in them)
    team:readthe workspace's name
  3. Under Manage Distribution, turn on public distribution, so other orgs' workspaces can install the app. Slack doesn't list it anywhere; only people with Infrared's connect link can install it.

  4. From Basic Information → App Credentials, copy the Client ID, Client Secret and Signing Secret into Settings → Slack and choose Save the Slack app. Infrared keeps them in the Secret slack-app in its namespace.

With the API: GET /api/v1/slack/app returns the manifest and redirect URL; PUT /api/v1/slack/app with {"clientID", "clientSecret", "signingSecret"} stores the credentials (platform admins).

Connect a workspace (each org, an org admin)​

  1. Settings → Slack → Connect Slack. Slack asks which workspace to add Infrared to and shows the permissions above; approve.
  2. Back in Infrared, under Destinations, choose Add a destination, pick the workspace and channel, tick what goes there, and choose Save destinations. Infrared posts a short hello in each new destination, saying what it will post there.
    • Public channels are listed by name. A private channel shows up once the app is in it: in Slack, type /invite @Infrared in the channel, then reload the picker.
    • Label is optional, for your own reference (for example community).

Infrared keeps each workspace's bot token in its own Secret in the org's namespace (slack-<team id>, lowercase; the first workspace connected before several were possible keeps slack-bot), never in its database or logs.

Add a second workspace, such as a community Slack​

  1. Settings → Slack → Connect another workspace, and approve in the community workspace. You need to be allowed to install apps there; otherwise ask one of its admins to approve the request Slack sends them.
  2. Add a destination in the community workspace, pick its channel (for example #releases), and tick only Product owner announcements, so summaries and drafts stay in your own Slack.
  3. Save destinations. Infrared says hello in the new channel.

Disconnect beside a workspace revokes its token and removes its destinations, including Products' destinations there; the others keep working. Posts already in Slack stay.

Each video is posted once, when it's made, to every destination that takes it; a remade video is a new post. If some destinations fail (say the app was removed from one channel), the others still get the post, and the Change shows which ones didn't and why.

Share to Slack​

Share to Slack on a Change lists the destinations that take the video you're watching (summary or product owner announcement), all ticked. Untick any you want to skip and choose Post. The Change then lists each post, with a link, or why it didn't go.

Destinations per Product​

A Product's Settings → Slack destinations offers three choices:

  1. Use the org's destinations (the default).
  2. Add its own to the org's: for example the checkout Product also posts to #checkout.
  3. Use only its own: the Product posts nowhere else.

Its own destinations are edited the same way, in any of the org's workspaces, with the same kinds. Everything Infrared posts about the Product follows them: summary videos and product owner announcements (automatic and Share to Slack), its Announce drafts, and the drafts of its Release and go-to-market AgentWorkflowRuns. A Product given a single channel before destinations existed keeps it as its only destination.

The Product's page says where it announces, for example Announces in #announcements (darkshift) · #releases (community).

# Add #checkout to the org's destinations for this Product.
curl -X PUT https://<host>/api/v1/orgs/<org>/products/<product>/slack -H "Authorization: Bearer $INFRARED_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"mode": "add", "destinations": [{"teamID": "T0123456", "channelID": "C0123456", "channelName": "checkout"}]}'
# Back to the org's destinations.
curl -X PUT https://<host>/api/v1/orgs/<org>/products/<product>/slack -H "Authorization: Bearer $INFRARED_TOKEN" \
-H 'Content-Type: application/json' -d '{}'

They are the Product's spec.slack (mode: add or replace, and destinations).

Announcement drafts​

Drafts go through the bot to every destination that takes Announce drafts. An org with no connected workspace can still use an incoming webhook (Settings → Announcements), which works as before; once a workspace is connected, the webhook isn't used.

With the API​

# The org's workspaces and destinations, then the URL that starts connecting a workspace.
curl https://<host>/api/v1/orgs/<org>/slack -H "Authorization: Bearer $INFRARED_TOKEN"
curl -X POST https://<host>/api/v1/orgs/<org>/slack/connect -H "Authorization: Bearer $INFRARED_TOKEN"
# A workspace's channels, then the destinations (kinds: summary, announcement, drafts; leave it out for all three).
curl "https://<host>/api/v1/orgs/<org>/slack/channels?team=T0123456" -H "Authorization: Bearer $INFRARED_TOKEN"
curl -X PUT https://<host>/api/v1/orgs/<org>/slack/destinations -H "Authorization: Bearer $INFRARED_TOKEN" \
-H 'Content-Type: application/json' -d '{"destinations": [
{"teamID": "T0123456", "channelID": "C0123456", "channelName": "announcements"},
{"teamID": "T0999999", "channelID": "C0999999", "channelName": "releases", "name": "community", "kinds": ["announcement"]}]}'
# Share a Change's video now, to every destination that takes it or only some ("team/channel").
curl -X POST "https://<host>/api/v1/orgs/<org>/agentworkflowruns/<run>/summary-video/slack?kind=announcement&destination=T0999999/C0999999" \
-H "Authorization: Bearer $INFRARED_TOKEN"
# Disconnect one workspace (leave out team to disconnect them all).
curl -X DELETE "https://<host>/api/v1/orgs/<org>/slack?team=T0999999" -H "Authorization: Bearer $INFRARED_TOKEN"

Orgs set up before several workspaces were possible need no change: their workspace and channel read as the first workspace and a destination taking everything (or only drafts, if videos were turned off), and are moved to the new shape the next time Slack settings are saved.

When it doesn't post​

MessageFix
the Infrared app isn't in that private channelIn Slack, /invite @Infrared in the channel
the workspace connection no longer works / was revokedConnect that workspace again: Connect another workspace and choose it in Slack
the Slack app lacks a permissionUpdate the app from the current manifest at api.slack.com, then Connect that workspace again: Connect another workspace and choose it in Slack
this Infrared's Slack app isn't set up yetA platform admin sets it up first (above)