ci: auto generate changelog
This commit is contained in:
@@ -0,0 +1,104 @@
|
|||||||
|
name: release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
|
|
||||||
|
- name: Generate changelog
|
||||||
|
id: changelog
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
TAG="${GITHUB_REF_NAME}"
|
||||||
|
REPO="${GITHUB_REPOSITORY}"
|
||||||
|
|
||||||
|
# previous tag (parent of this tag)
|
||||||
|
PREV_TAG="$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")"
|
||||||
|
|
||||||
|
if [ -z "$PREV_TAG" ]; then
|
||||||
|
RANGE="HEAD"
|
||||||
|
echo "No previous tag, using all history"
|
||||||
|
else
|
||||||
|
RANGE="${PREV_TAG}..HEAD"
|
||||||
|
echo "Range: $RANGE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
FEATS=""
|
||||||
|
FIXES=""
|
||||||
|
|
||||||
|
# %H = hash, %s = subject (first line)
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
sha="${line%% *}"
|
||||||
|
subject="${line#* }"
|
||||||
|
# match conventional commits: feat, fix (with optional scope)
|
||||||
|
if echo "$subject" | grep -qE '^(feat|fix)(\(.+\))?: '; then
|
||||||
|
type="$(echo "$subject" | sed -E 's/^([a-z]+)(\(.+\))?:.*/\1/')"
|
||||||
|
# strip type prefix for display, keep rest as title
|
||||||
|
title="$(echo "$subject" | sed -E 's/^[a-z]+(\(.+\))?: //')"
|
||||||
|
short="$(echo "$sha" | cut -c1-7)"
|
||||||
|
url="https://github.com/${REPO}/commit/${sha}"
|
||||||
|
entry="- ${title} ([\`${short}\`](${url}))"
|
||||||
|
if [ "$type" = "feat" ]; then
|
||||||
|
FEATS="${FEATS}${entry}"$'\n'
|
||||||
|
elif [ "$type" = "fix" ]; then
|
||||||
|
FIXES="${FIXES}${entry}"$'\n'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < <(git log "$RANGE" --pretty=format:"%H %s" --no-merges)
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "# ${TAG}"
|
||||||
|
echo ""
|
||||||
|
if [ -n "$FEATS" ]; then
|
||||||
|
echo "## Features"
|
||||||
|
echo ""
|
||||||
|
printf "%s" "$FEATS"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
if [ -n "$FIXES" ]; then
|
||||||
|
echo "## Fixes"
|
||||||
|
echo ""
|
||||||
|
printf "%s" "$FIXES"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
if [ -z "$FEATS" ] && [ -z "$FIXES" ]; then
|
||||||
|
echo "_No relevant conventional commits (feat/fix) in this release._"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
echo "---"
|
||||||
|
echo ""
|
||||||
|
if [ -n "$PREV_TAG" ]; then
|
||||||
|
echo "**Full diff:** [\`${PREV_TAG}...${TAG}\`](https://github.com/${REPO}/compare/${PREV_TAG}...${TAG})"
|
||||||
|
else
|
||||||
|
echo "**Full history up to ${TAG}**"
|
||||||
|
fi
|
||||||
|
} > /tmp/notes.md
|
||||||
|
|
||||||
|
cat /tmp/notes.md
|
||||||
|
# multiline output for next step
|
||||||
|
{
|
||||||
|
echo "notes<<EOF"
|
||||||
|
cat /tmp/notes.md
|
||||||
|
echo "EOF"
|
||||||
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Create GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.ref_name }}
|
||||||
|
name: ${{ github.ref_name }}
|
||||||
|
body: ${{ steps.changelog.outputs.notes }}
|
||||||
|
generate_release_notes: false
|
||||||
Reference in New Issue
Block a user