From 42a86af6c3f2c43218378209f643d6ca244db949 Mon Sep 17 00:00:00 2001 From: Toto Tvalavadze Date: Thu, 7 May 2026 15:12:19 +0400 Subject: [PATCH] ci: add release note bodies Generate GitHub release notes with install steps, artifact checksums, and grouped changelog entries so tagged releases publish useful bodies. --- .github/workflows/release.yml | 14 ++++ README.md | 5 +- scripts/write-release-notes.sh | 114 +++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 2 deletions(-) create mode 100755 scripts/write-release-notes.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 553edc3..bd60d1a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -155,6 +155,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Determine version id: vars @@ -208,9 +210,21 @@ jobs: echo "intel_url=${intel_url}" >> "${GITHUB_OUTPUT}" echo "intel_sha=${intel_sha}" >> "${GITHUB_OUTPUT}" + - name: Write release notes + env: + VERSION: ${{ steps.vars.outputs.version }} + ARM_URL: ${{ steps.metadata.outputs.arm_url }} + ARM_SHA: ${{ steps.metadata.outputs.arm_sha }} + INTEL_URL: ${{ steps.metadata.outputs.intel_url }} + INTEL_SHA: ${{ steps.metadata.outputs.intel_sha }} + run: | + set -euo pipefail + ./scripts/write-release-notes.sh release-notes.md "${VERSION}" "${ARM_URL}" "${ARM_SHA}" "${INTEL_URL}" "${INTEL_SHA}" + - name: Publish GitHub release uses: softprops/action-gh-release@v2 with: + body_path: release-notes.md files: | dist/*.tar.gz dist/*.sha256 diff --git a/README.md b/README.md index 6876e82..831125e 100644 --- a/README.md +++ b/README.md @@ -367,8 +367,9 @@ Active roadmap items are tracked on GitHub and currently include: ## Release Process - Tag the commit you want to ship with `vX.Y.Z`; pushing the tag triggers the `Release` workflow. -- The workflow re-runs formatting, clippy, and tests on Ubuntu, then builds macOS Intel (macos-12) and Apple Silicon (macos-14) binaries with `cargo build --release`. -- Binaries are packaged as `arrowhead--.tar.gz` with `bin/arrowhead` plus the project README and uploaded to the GitHub release. +- The workflow re-runs formatting, clippy, and tests on Ubuntu, then builds macOS Intel and Apple Silicon binaries with `cargo build --release`. +- Binaries are packaged as `arrowhead--.tar.gz` with `bin/arrowhead`, `bin/arrowheadd`, and the project README. +- The GitHub release body includes install instructions, artifact SHA256 sums, and conventional-commit changelog notes since the previous tag. - Set a personal access token with `repo` scope as the `HOMEBREW_TAP_TOKEN` repository secret so the workflow can push tap updates to `totocaster/homebrew-tap`. - The tap formula is rewritten automatically to point at the new release URLs and SHA256 sums for both macOS architectures. diff --git a/scripts/write-release-notes.sh b/scripts/write-release-notes.sh new file mode 100755 index 0000000..308af3a --- /dev/null +++ b/scripts/write-release-notes.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ $# -ne 6 ]]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +OUTPUT_FILE="$1" +VERSION="$2" +ARM_URL="$3" +ARM_SHA="$4" +INTEL_URL="$5" +INTEL_SHA="$6" + +REPOSITORY="${GITHUB_REPOSITORY:-totocaster/arrowhead}" +TAG_NAME="${ARROWHEAD_RELEASE_TAG:-${GITHUB_REF_NAME:-v${VERSION}}}" +PREVIOUS_TAG="${ARROWHEAD_PREVIOUS_TAG:-}" + +if [[ -z "${PREVIOUS_TAG}" ]]; then + PREVIOUS_TAG="$(git describe --tags --abbrev=0 "${TAG_NAME}^" 2>/dev/null || true)" +fi + +if [[ -n "${PREVIOUS_TAG}" ]]; then + RANGE="${PREVIOUS_TAG}..${TAG_NAME}" + CHANGELOG_URL="https://github.com/${REPOSITORY}/compare/${PREVIOUS_TAG}...${TAG_NAME}" +else + RANGE="${TAG_NAME}" + CHANGELOG_URL="https://github.com/${REPOSITORY}/commits/${TAG_NAME}" +fi + +TMP_DIR="$(mktemp -d)" +trap 'rm -rf "${TMP_DIR}"' EXIT + +features="${TMP_DIR}/features.md" +fixes="${TMP_DIR}/fixes.md" +docs="${TMP_DIR}/docs.md" +maintenance="${TMP_DIR}/maintenance.md" +other="${TMP_DIR}/other.md" + +touch "${features}" "${fixes}" "${docs}" "${maintenance}" "${other}" + +while IFS=$'\t' read -r sha subject; do + [[ -n "${sha}" && -n "${subject}" ]] || continue + + short_sha="${sha:0:7}" + entry="- ${subject} ([${short_sha}](https://github.com/${REPOSITORY}/commit/${sha}))" + + case "${subject}" in + feat:*|feat\(*|feature:*|feature\(*) + printf '%s\n' "${entry}" >> "${features}" + ;; + fix:*|fix\(*) + printf '%s\n' "${entry}" >> "${fixes}" + ;; + docs:*|docs\(*) + printf '%s\n' "${entry}" >> "${docs}" + ;; + chore:*|chore\(*|ci:*|ci\(*|build:*|build\(*|test:*|test\(*|refactor:*|refactor\(*|perf:*|perf\(*) + printf '%s\n' "${entry}" >> "${maintenance}" + ;; + *) + printf '%s\n' "${entry}" >> "${other}" + ;; + esac +done < <(git log --no-merges --format='%H%x09%s' "${RANGE}") + +append_section() { + local title="$1" + local file="$2" + + if [[ -s "${file}" ]]; then + { + printf '\n### %s\n\n' "${title}" + cat "${file}" + } >> "${OUTPUT_FILE}" + fi +} + +cat > "${OUTPUT_FILE}" <> "${OUTPUT_FILE}" <