Merge pull request #1575 from sbadakhc/issue-1574/release-v1-1-41 #28
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| permissions: | |
| contents: write | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Tag to release (e.g. v1.2.3)' | |
| required: true | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Extract version from tag | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then | |
| VERSION="${{ github.event.inputs.tag }}" | |
| else | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| fi | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "Releasing version: $VERSION" | |
| - name: Extract and transform changelog to release notes | |
| id: changelog | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| # Determine previous tag for Full Changelog comparison | |
| PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${VERSION}"^ 2>/dev/null || echo "") | |
| if [ -z "$PREVIOUS_TAG" ]; then | |
| PREVIOUS_TAG=$(git tag --sort=-creatordate | grep -v "^${VERSION}$" | head -1 || echo "") | |
| fi | |
| if [ -z "$PREVIOUS_TAG" ]; then | |
| PREVIOUS_TAG="previous" | |
| fi | |
| echo "Previous tag: $PREVIOUS_TAG" | |
| # Run awk transformation: extract CHANGELOG section, emit release notes in RELEASE_TEMPLATE v3.0 format | |
| awk -v VERSION="$VERSION" -v PREV="$PREVIOUS_TAG" ' | |
| # Locate the section for this version | |
| index($0, "## [" VERSION "]") == 1 { in_section=1; next } | |
| index($0, "## [") == 1 && in_section { in_section=0 } | |
| !in_section { next } | |
| # Section header detection (accept both ###Summary and ### Summary) | |
| match($0, /^###[ \t]*Summary/) { section="Summary"; is_summary=1; next } | |
| match($0, /^###[ \t]*Fixed/) { section="Fixed"; next } | |
| match($0, /^###[ \t]*Changed/) { section="Changed"; next } | |
| match($0, /^###[ \t]*Added/) { section="Added"; next } | |
| match($0, /^###[ \t]*Removed/) { section="Removed"; next } | |
| # End on unknown header or separator | |
| match($0, /^###[ \t]*[^ \t]/) || $0 == "---" { section=""; is_summary=0; next } | |
| # Capture summary paragraph (first non-empty line after ###Summary) | |
| is_summary && $0 != "" { summary_text=$0; is_summary=0; next } | |
| is_summary { next } | |
| # Collect checklist items only within recognised sections | |
| section != "" && $1 == "-" && $2 == "[x]" { | |
| $1=""; $2="" | |
| sub(/^[ \t]+/, "") | |
| item=$0 | |
| # Strip surrounding **bold** markers | |
| gsub(/^\*\*/, "", item) | |
| gsub(/\*\*:/, ":", item) | |
| gsub(/\*\*$/, "", item) | |
| # Normalise "(Fixes #N)" and "(fixes #N)" to "(#N)" | |
| gsub(/\(Fixes #/, "(#", item) | |
| gsub(/\(fixes #/, "(#", item) | |
| # Store in the appropriate section list | |
| if (section == "Fixed") { fixed[++fi] = item } | |
| if (section == "Changed") { changed[++ch] = item } | |
| if (section == "Added") { added[++ad] = item } | |
| if (section == "Removed") { removed[++re] = item } | |
| next | |
| } | |
| END { | |
| # Emit release notes in RELEASE_TEMPLATE.md v3.0 format | |
| print "## AIXCL " VERSION | |
| print "" | |
| if (summary_text != "") print summary_text | |
| print "" | |
| heading = "### What\x27s New in " VERSION | |
| print heading | |
| print "" | |
| if (ad > 0) { | |
| print "#### Added" | |
| for (i=1; i<=ad; i++) print "- ✅ " added[i] | |
| print "" | |
| } | |
| if (ch > 0) { | |
| print "#### Changed" | |
| for (i=1; i<=ch; i++) print "- ✅ " changed[i] | |
| print "" | |
| } | |
| if (fi > 0) { | |
| print "#### Fixed" | |
| for (i=1; i<=fi; i++) print "- ✅ " fixed[i] | |
| print "" | |
| } | |
| if (re > 0) { | |
| print "#### Removed" | |
| for (i=1; i<=re; i++) print "- ✅ " removed[i] | |
| print "" | |
| } | |
| print "### Documentation" | |
| print "- [Getting Started](README.md)" | |
| print "- [Development Workflow](docs/developer/development-workflow.md)" | |
| print "- [Changelog](CHANGELOG.md)" | |
| print "" | |
| print "---" | |
| print "" | |
| print "**Full Changelog**: [" PREV "..." VERSION "](../../compare/" PREV "..." VERSION ")" | |
| } | |
| ' CHANGELOG.md > /tmp/release-notes.md | |
| if [ -s /tmp/release-notes.md ] && grep -qE '^#### (Added|Changed|Fixed|Removed)' /tmp/release-notes.md; then | |
| echo "Generated release notes for $VERSION" | |
| cat /tmp/release-notes.md | |
| else | |
| echo "WARNING: No changelog content found for $VERSION; using generic fallback" | |
| { | |
| echo "## AIXCL ${VERSION}" | |
| echo "" | |
| echo "Release ${VERSION}" | |
| echo "" | |
| echo "### Documentation" | |
| echo "- [Getting Started](README.md)" | |
| echo "- [Development Workflow](docs/developer/development-workflow.md)" | |
| echo "- [Changelog](CHANGELOG.md)" | |
| echo "" | |
| echo "---" | |
| echo "" | |
| echo "**Full Changelog**: [${PREVIOUS_TAG}...${VERSION}](../../compare/${PREVIOUS_TAG}...${VERSION})" | |
| } > /tmp/release-notes.md | |
| cat /tmp/release-notes.md | |
| fi | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3 | |
| with: | |
| tag_name: ${{ steps.version.outputs.version }} | |
| name: "AIXCL ${{ steps.version.outputs.version }}" | |
| body_path: /tmp/release-notes.md | |
| draft: false | |
| prerelease: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |