discourse-release: announce published releases on the community forum
A composite action: reads the release from the event file with jq, looks up the repo's Announcements category (release-map.json) and posts as release-bot. One topic per repo+tag via the topic external_id, so a re-run is a no-op. Optional Discord webhook.
This commit is contained in:
1 parent
fab0c4d45e
commit
6245815b09
4 files changed
+142
No files matched your search
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/bin/bash
|
||||
# Called by action.yml. Everything user-written (release name, notes) comes in
|
||||
# through the event JSON file and is only ever handled by jq -- never spliced
|
||||
# into a command line or a JSON string by the shell.
|
||||
set -euo pipefail
|
||||
|
||||
category_path=$(jq -r --arg r "$REPO" '.[$r] // empty' "$MAP")
|
||||
if [ -z "$category_path" ]; then
|
||||
echo "::error::$REPO is not in discourse-release/release-map.json"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tag=$(jq -r '.release.tag_name' "$EVENT_PATH")
|
||||
# The category id, looked up anonymously (the category is public); the
|
||||
# release-bot key is scoped to creating posts and nothing else.
|
||||
category_id=$(curl -fsS "$FORUM/c/$category_path/find_by_slug.json" | jq -r '.category.id')
|
||||
|
||||
# One topic per repo+tag, ever: Discourse enforces external_id uniqueness.
|
||||
external_id="rel-$(printf '%s@%s' "$REPO" "$tag" | sha1sum | cut -c1-40)"
|
||||
|
||||
payload=$(jq -n --arg repo "$REPO" --argjson category "$category_id" --arg ext "$external_id" \
|
||||
--slurpfile ev "$EVENT_PATH" '
|
||||
($ev[0].release) as $r
|
||||
| ($repo | split("/") | last) as $name
|
||||
| ($r.name // "" | if . == "" then $r.tag_name else . end) as $title
|
||||
| {
|
||||
title: "\($name) \($title) released",
|
||||
category: $category,
|
||||
external_id: $ext,
|
||||
raw: (
|
||||
"**\($name) \($r.tag_name)** is out.\n\n"
|
||||
+ (if ($r.body // "") == "" then "" else "\($r.body)\n\n" end)
|
||||
+ "---\n[Release on Gitea](\($r.html_url))"
|
||||
)
|
||||
}')
|
||||
|
||||
status=$(curl -sS -o /tmp/discourse-release.out -w '%{http_code}' -X POST "$FORUM/posts.json" \
|
||||
-H "Api-Key: $API_KEY" -H "Api-Username: release-bot" \
|
||||
-H "Content-Type: application/json" --data-binary "$payload")
|
||||
body=$(cat /tmp/discourse-release.out)
|
||||
case "$status" in
|
||||
200)
|
||||
url="$FORUM/t/$(jq -r '.topic_slug' <<<"$body")/$(jq -r '.topic_id' <<<"$body")"
|
||||
echo "announced: $url" ;;
|
||||
422)
|
||||
if jq -e '.errors | tostring | test("External ID"; "i")' <<<"$body" >/dev/null; then
|
||||
echo "already announced (external_id $external_id); nothing to do"
|
||||
exit 0
|
||||
fi
|
||||
echo "::error::forum refused the post: $body"; exit 1 ;;
|
||||
*)
|
||||
echo "::error::forum returned HTTP $status: $body"; exit 1 ;;
|
||||
esac
|
||||
|
||||
if [ -n "${DISCORD_WEBHOOK:-}" ]; then
|
||||
jq -n --arg u "$url" --slurpfile ev "$EVENT_PATH" --arg repo "$REPO" '
|
||||
($ev[0].release) as $r
|
||||
| {content: ("**\($repo | split("/") | last) \($r.tag_name)** released\n\($u)")[0:1900]}' |
|
||||
curl -fsS -X POST "$DISCORD_WEBHOOK" -H "Content-Type: application/json" --data-binary @- >/dev/null \
|
||||
&& echo "posted to Discord" \
|
||||
|| echo "::warning::Discord webhook failed; the forum post stands"
|
||||
fi
|
||||
Reference in new issue
Block a user