-
-
Notifications
You must be signed in to change notification settings - Fork 1
Add automated changelog and release management #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2648cd8
d8a03dc
bc5670f
5a3be4e
43d3bbc
3ee263f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| name: Update Changelog | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| paths-ignore: | ||
| - 'CHANGELOG.md' | ||
| - 'docs/**' | ||
| - '**.md' | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| update-changelog: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # Need full history for changelog generation | ||
|
|
||
| - name: Get last tag | ||
| id: last_tag | ||
| run: | | ||
| LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | ||
| if [ -z "$LAST_TAG" ]; then | ||
| echo "No previous tag found, using first commit" | ||
| LAST_TAG=$(git rev-list --max-parents=0 HEAD) | ||
| fi | ||
| echo "tag=$LAST_TAG" >> $GITHUB_OUTPUT | ||
| echo "Last tag: $LAST_TAG" | ||
|
|
||
| - name: Generate changelog for unreleased changes | ||
| id: changelog | ||
| run: | | ||
| if [ ! -f scripts/generate-changelog ]; then | ||
| echo "Changelog script not found, skipping" | ||
| echo "skip=true" >> $GITHUB_OUTPUT | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Generate changelog from last tag to HEAD | ||
| CHANGELOG=$(bash scripts/generate-changelog "${{ steps.last_tag.outputs.tag }}" "HEAD" || echo "") | ||
|
|
||
| if [ -z "$CHANGELOG" ]; then | ||
| echo "No new changes since last tag" | ||
| echo "skip=true" >> $GITHUB_OUTPUT | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Save to file | ||
| echo "$CHANGELOG" > /tmp/changelog-unreleased.md | ||
| echo "skip=false" >> $GITHUB_OUTPUT | ||
|
|
||
| - name: Update CHANGELOG.md | ||
| if: steps.changelog.outputs.skip != 'true' | ||
| run: | | ||
| # Check if [Unreleased] section exists | ||
| if ! grep -q "## \[Unreleased\]" CHANGELOG.md; then | ||
| echo "[Unreleased] section not found in CHANGELOG.md" | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Create backup | ||
| cp CHANGELOG.md CHANGELOG.md.bak | ||
|
|
||
| # Replace [Unreleased] section with new content | ||
| { | ||
| # Everything before [Unreleased] | ||
| sed -n '1,/## \[Unreleased\]/p' CHANGELOG.md | head -n -1 | ||
|
|
||
| # New changelog content | ||
| cat /tmp/changelog-unreleased.md | ||
|
|
||
| # Everything after [Unreleased] section | ||
| sed -n '/## \[Unreleased\]/,$ { | ||
| /## \[Unreleased\]/d | ||
| /^$/d | ||
| p | ||
| }' CHANGELOG.md | sed '1,/^## \[/d' | sed '1s/^/\n/' | ||
| } > CHANGELOG.md.tmp | ||
|
|
||
| # Check if there are actual changes | ||
| if diff -q CHANGELOG.md CHANGELOG.md.bak >/dev/null 2>&1; then | ||
| echo "No changes to CHANGELOG.md" | ||
| rm CHANGELOG.md.tmp CHANGELOG.md.bak | ||
| exit 0 | ||
| fi | ||
|
|
||
| mv CHANGELOG.md.tmp CHANGELOG.md | ||
| rm CHANGELOG.md.bak | ||
|
|
||
| - name: Commit changes | ||
| if: steps.changelog.outputs.skip != 'true' | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
|
|
||
| if git diff --quiet CHANGELOG.md; then | ||
| echo "No changes to commit" | ||
| exit 0 | ||
| fi | ||
|
|
||
| git add CHANGELOG.md | ||
| git commit -m "docs: Update unreleased changes in CHANGELOG.md | ||
|
|
||
| Automatically generated from recent commits | ||
|
|
||
| 🤖 Generated by GitHub Actions" | ||
|
|
||
| git push | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,7 +29,10 @@ POLICY_FILE ?= cassh.policy.example.toml | |
| icon app-bundle app-bundle-oss app-bundle-enterprise \ | ||
| dmg dmg-only pkg pkg-only \ | ||
| sign notarize \ | ||
| test lint | ||
| test test-race test-coverage test-ci test-list \ | ||
| test-ca test-config test-memes test-menubar \ | ||
| lint \ | ||
| changelog changelog-preview create-release | ||
|
|
||
| # Default: build all binaries | ||
| all: deps build | ||
|
|
@@ -301,6 +304,48 @@ dev-ca: | |
| @echo "CA key generated: dev/ca_key" | ||
| @echo "CA public key: dev/ca_key.pub" | ||
|
|
||
| # ============================================================================= | ||
| # Changelog and Release Management | ||
| # ============================================================================= | ||
|
|
||
| # Generate changelog preview from last tag to HEAD | ||
| changelog-preview: | ||
| @echo "Generating changelog preview..." | ||
| @./scripts/generate-changelog | ||
|
|
||
| # Update CHANGELOG.md with unreleased changes (same as CI does) | ||
| changelog: | ||
| @echo "Updating CHANGELOG.md with unreleased changes..." | ||
| @LAST_TAG=$$(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD); \ | ||
| ./scripts/generate-changelog "$$LAST_TAG" HEAD > /tmp/changelog-unreleased.md | ||
| @echo "Preview:" | ||
| @cat /tmp/changelog-unreleased.md | ||
| @echo "" | ||
| @read -p "Update CHANGELOG.md? [y/N] " -n 1 -r; echo; \ | ||
| if [[ $$REPLY =~ ^[Yy]$$ ]]; then \ | ||
| cp CHANGELOG.md CHANGELOG.md.bak; \ | ||
|
Comment on lines
+323
to
+326
|
||
| { \ | ||
| sed -n '1,/## \[Unreleased\]/p' CHANGELOG.md | head -n -1; \ | ||
| cat /tmp/changelog-unreleased.md; \ | ||
| echo ""; \ | ||
| sed -n '/## \[Unreleased\]/,$$ { /## \[Unreleased\]/d; /^$$/d; p }' CHANGELOG.md | sed '1,/^## \[/d' | sed '1s/^/\n/'; \ | ||
|
||
| } > CHANGELOG.md.tmp && mv CHANGELOG.md.tmp CHANGELOG.md; \ | ||
| rm CHANGELOG.md.bak; \ | ||
| echo "✓ CHANGELOG.md updated"; \ | ||
| else \ | ||
| echo "Cancelled"; \ | ||
| fi | ||
|
|
||
| # Create a new release (interactive) | ||
| # Usage: make create-release VERSION=1.2.0 | ||
| create-release: | ||
| @if [ -z "$(VERSION)" ]; then \ | ||
| echo "Error: VERSION not specified"; \ | ||
| echo "Usage: make create-release VERSION=1.2.0"; \ | ||
| exit 1; \ | ||
| fi | ||
| @./scripts/create-release $(VERSION) | ||
|
|
||
| # ============================================================================= | ||
| # Clean | ||
| # ============================================================================= | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The paths-ignore configuration will exclude all markdown files from triggering the workflow. This means that changes to non-documentation markdown files (if any exist) will also be ignored. More critically, this creates a potential infinite loop: if the workflow commits to CHANGELOG.md and the push includes other non-markdown code changes, it could trigger itself again. Consider a more specific approach or ensure the workflow checks for the commit author to avoid loops.