| name | post-release-status |
| description | Post or update a release status message in Slack tracking cherry-picked PRs and their current status. Use when the user asks to post, update, or check cherry-pick status for a release.
|
post-release-status
Post or update a top-level Slack message that tracks the status of all cherry-picked PRs for a release branch.
Configuration
This skill reads environment-specific values from environment variables (see the repo README.md):
SLACK_BOT_TOKEN — Slack bot token with channels:history, channels:read, chat:write, and chat:update OAuth scopes.
INTERNAL_REPO — owner/repo that holds your release branches and cherry-pick PRs.
REPO_DIR — absolute path to your local checkout of INTERNAL_REPO.
RELEASE_SLACK_CHANNEL — Slack channel name (or ID) to post the status in.
RELEASE_CHANNELS — space-separated release channels used to derive the channel label from a branch (default preview stable).
STATUS_EMOJI_IN_REVIEW / STATUS_EMOJI_MERGED / STATUS_EMOJI_VERIFIED — Slack emoji for each PR status (defaults :large_yellow_square: / :merged: / :verified:).
All git/gh operations run inside INTERNAL_REPO. Run cd "$REPO_DIR" before executing any git or gh commands.
Step 1: Clarify inputs
Before proceeding, ensure you have:
Derive the channel (one of $RELEASE_CHANNELS) and version string from the branch name for display.
If $SLACK_BOT_TOKEN is not set, ask the user for it before proceeding.
Step 2: Find cherry-pick PRs
List all PRs targeting the release branch:
gh pr list --repo "$INTERNAL_REPO" --base $BRANCH_NAME --state all --json number,title,url,state --limit 100
Each PR will have:
state: OPEN or MERGED
number, title, url: for display
Step 3: Look for an existing status message
Search the Slack channel for the most recent message matching this release:
curl -s -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
"https://slack.com/api/conversations.history?channel=<SLACK_CHANNEL_ID>&limit=50" | \
jq '[.messages[] | select(.text | test("<VERSION_OR_BRANCH_PATTERN>"))] | first | {ts, text}'
Use a pattern that matches the release version or branch name in the message text (e.g. the version string from Step 1).
If a matching message is found:
- Save its
ts for updating later.
- Parse the message to find previously tracked PRs and their statuses. Look for these emoji patterns:
$STATUS_EMOJI_IN_REVIEW (default :large_yellow_square:) → in review
$STATUS_EMOJI_MERGED (default :merged:) → merged
$STATUS_EMOJI_VERIFIED (default :verified:) → verified
- Preserve
$STATUS_EMOJI_VERIFIED status — do not downgrade a verified PR back to merged.
If no matching message is found: proceed with current GitHub state only.
Step 4: Determine final PR statuses
For each cherry-pick PR, determine the display status:
- If the PR was
$STATUS_EMOJI_VERIFIED in the previous message → keep as $STATUS_EMOJI_VERIFIED
- Else if the PR state is
MERGED on GitHub → $STATUS_EMOJI_MERGED
- Else if the PR state is
OPEN on GitHub → $STATUS_EMOJI_IN_REVIEW
Step 5: Format the message
Use Slack Block Kit so the release name renders as a true header (larger text). Build a blocks JSON array and a plain-text text fallback (used for notifications and for searching in Step 3):
[
{
"type": "header",
"text": {
"type": "plain_text",
"text": "<version> <channel> release"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "• :large_yellow_square: <https://github.com/OWNER/REPO/pull/123|PR #123> — <title>\n• :merged: <https://github.com/OWNER/REPO/pull/456|PR #456> — <title>\n• :verified: <https://github.com/OWNER/REPO/pull/789|PR #789> — <title>"
}
}
]
Also set TEXT_FALLBACK to the plain version of the title (e.g. "v0.YYYY.MM.DD stable release") — this is used for notifications and for the search pattern in Step 3.
Use Slack mrkdwn hyperlink format in the section block: <URL|display text>.
Step 6: Post or update the message
If updating an existing message (message ts found in Step 3):
curl -s -X POST \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
--data "$(jq -n \
--arg channel "<SLACK_CHANNEL_ID>" \
--arg ts "<EXISTING_MESSAGE_TS>" \
--arg text "$TEXT_FALLBACK" \
--argjson blocks "$BLOCKS_JSON" \
'{channel: $channel, ts: $ts, text: $text, blocks: $blocks}')" \
"https://slack.com/api/chat.update" | jq '{ok, ts, error}'
If posting a new message:
curl -s -X POST \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
--data "$(jq -n \
--arg channel "<SLACK_CHANNEL_ID>" \
--arg text "$TEXT_FALLBACK" \
--argjson blocks "$BLOCKS_JSON" \
'{channel: $channel, text: $text, blocks: $blocks}')" \
"https://slack.com/api/chat.postMessage" | jq '{ok, ts, error}'
Step 7: Confirm
Share the permalink with the user:
curl -s -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
"https://slack.com/api/chat.getPermalink?channel=<SLACK_CHANNEL_ID>&message_ts=<MESSAGE_TS>" | \
jq -r '.permalink'
Notes
- The message is always a top-level message, not a thread reply.
- When updating, PR statuses are refreshed from GitHub, but
$STATUS_EMOJI_VERIFIED statuses are preserved from the previous message.
- If the API returns
ok: false, check the error field. Common errors: not_in_channel, missing_scope, message_not_found.
- To manually mark a PR as verified, the user can ask to update a specific PR's status.