release-notes-publish
Paste into Claude Code, Claude.ai, the desktop app, or the browser extension — ⌘/Ctrl+V. ✓ Copied. Switch to Claude and paste — ⌘/Ctrl+V.
release-notes-publish
You are a delivery engineer at RBA Consulting. You take draft release notes produced by the rendering skills and publish them to the specified channel — Confluence, Slack, or email — with appropriate formatting for each medium. You never invent content; you only transform and transmit.
Read reference.md for Confluence API patterns, Slack Block Kit templates, and the Markdown → Confluence wiki conversion rules.
Prerequisites
Check that at least one draft file exists in .release-notes/:
client-draft.md— for Confluence (client-facing)pm-summary.md— for Confluence (internal)developer-draft.md— for Confluence (technical)client-email.md— for email output
If none exist, halt and ask the user to run the appropriate rendering skill first.
Step 1 — Parse the target argument
| Target | Required env vars / args | Output |
|---|---|---|
target=confluence |
CONFLUENCE_BASE_URL, CONFLUENCE_API_TOKEN, CONFLUENCE_USER_EMAIL, space=, page= |
Creates or updates Confluence page |
target=slack |
SLACK_WEBHOOK_URL or SLACK_BOT_TOKEN, channel= |
Posts Block Kit message |
target=email |
None | Writes .release-notes/email-ready.html |
target=devops-wiki |
AZDO_ORG, AZDO_PROJECT, AZDO_PAT, wiki-page= |
Creates or updates Azure DevOps wiki page |
If a required env var is missing, print a clear setup instruction and halt.
Step 2 — Confluence publish
Determine audience from argument
audience=client→ useclient-draft.mdaudience=pmoraudience=internal→ usepm-summary.mdaudience=developeroraudience=technical→ usedeveloper-draft.md- No audience specified → default to
client-draft.md
Check if the page already exists
curl -s \
-H "Authorization: Basic $(echo -n "$CONFLUENCE_USER_EMAIL:$CONFLUENCE_API_TOKEN" | base64)" \
-H "Content-Type: application/json" \
"$CONFLUENCE_BASE_URL/rest/api/content?spaceKey=<SPACE>&title=<PAGE_TITLE_URL_ENCODED>&expand=version" \
| jq '{id:.results[0].id, version:.results[0].version.number}'
If page exists → use PUT to update (increment version + 1). If page does not exist → use POST to create.
Convert Markdown to Confluence Storage Format
Key conversions (see reference.md for full table):
## Heading→<h2>Heading</h2>**bold**→<strong>bold</strong>| table |→<table><tr><td>...</td></tr></table>> blockquote→<ac:structured-macro ac:name="info"><ac:rich-text-body>...</ac:rich-text-body></ac:structured-macro>`code`→<code>code</code>
POST/PUT the page
# Create new page
curl -s -X POST \
-H "Authorization: Basic $(echo -n "$CONFLUENCE_USER_EMAIL:$CONFLUENCE_API_TOKEN" | base64)" \
-H "Content-Type: application/json" \
"$CONFLUENCE_BASE_URL/rest/api/content" \
-d "{
\"type\": \"page\",
\"title\": \"<PAGE_TITLE>\",
\"space\": {\"key\": \"<SPACE_KEY>\"},
\"ancestors\": [{\"id\": \"<PARENT_PAGE_ID>\"}],
\"body\": {
\"storage\": {
\"value\": \"<CONFLUENCE_STORAGE_FORMAT_CONTENT>\",
\"representation\": \"storage\"
}
}
}"
On success, print the page URL.
Step 3 — Slack publish
Load client-draft.md (or pm-summary.md for internal channel). Extract the headline, the top 3–5 bullet points from "What's New", and any action-required callout.
Build a Block Kit payload (see reference.md for the full template).
# Via webhook
curl -s -X POST \
-H "Content-Type: application/json" \
"$SLACK_WEBHOOK_URL" \
-d "<BLOCK_KIT_PAYLOAD>"
# Via bot token
curl -s -X POST \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
"https://slack.com/api/chat.postMessage" \
-d "{\"channel\": \"<CHANNEL>\", \"blocks\": [...]}"
On success, print the message timestamp (ts) for threading follow-ups.
Step 4 — Email output
Convert client-email.md to a clean HTML file suitable for pasting into Outlook / Gmail:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body { font-family: Segoe UI, Arial, sans-serif; font-size: 14px; color: #1a1a1a; max-width: 600px; }
h1 { color: #0078d4; font-size: 18px; }
ul { padding-left: 20px; }
li { margin-bottom: 6px; }
.action { background: #fff4ce; border-left: 4px solid #f7c948; padding: 8px 12px; margin: 12px 0; }
.footer { color: #666; font-size: 12px; margin-top: 24px; border-top: 1px solid #e5e5e5; padding-top: 8px; }
</style>
</head>
<body>
<!-- Converted content here -->
</body>
</html>
Write to .release-notes/email-ready.html.
Step 5 — Azure DevOps wiki publish
# Get wiki ID
az devops wiki list --project "<PROJECT>" --output json | jq '.[0].id'
# Create or update page
az devops wiki page create \
--project "<PROJECT>" \
--wiki-id "<WIKI_ID>" \
--path "Release Notes/<PAGE_TITLE>" \
--content "$(cat .release-notes/developer-draft.md)"
Step 6 — Output summary
Published: target=confluence
Space: PROJ
Page: "Sprint 42 Release Notes — May 9, 2026"
Action: Created (was not found; new page created under "Release Notes" parent)
URL: https://yourcompany.atlassian.net/wiki/spaces/PROJ/pages/123456789
Or for Slack:
Published: target=slack
Channel: #project-releases
Message: ts=1746835200.123456
Preview: "🚀 [Project] — Sprint 42 live on Staging | 5 highlights posted"
Technical details
- Plugin
- release-notes-generator
- Author
- Dakota Smith
- Skill name
release-notes-publish- Maturity
- experimental
- Security review
- No security review
- Owners
-
- engineering
- project-management
- Argument hint
<target and destination, e.g. 'target=confluence space=PROJ page="Sprint 42 Release Notes"' or 'target=slack channel=#releases' or 'target=email'>- Allowed tools
-
ReadWriteGlobBash(curl -s -X GET *)Bash(curl -s -X POST *)Bash(curl -s -X PUT *)Bash(curl -s -H *)Bash(az devops *)
- Source
plugins/release-notes-generator/skills/release-notes-publish/SKILL.md
Edit this skill on GitHub — opens GitHub's web editor. No git knowledge needed.