diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index 56d0ee6..ac54103 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -4,6 +4,7 @@ on: workflow_dispatch: {} push: branches: [main] + tags: ['v*'] paths: - '**.go' - 'go.mod' @@ -97,40 +98,70 @@ jobs: xetup.exe echo "Signed and timestamped xetup.exe" - - name: Publish latest release + - name: Extract release notes from CHANGELOG.md + run: | + # On a version tag (v0.7) take that version's section; otherwise the + # latest released version section (first "## ["). Falls back to + # [Unreleased], then to a placeholder. + case "${{ github.ref }}" in + refs/tags/v*) + HEADER="## [$(echo "${{ github.ref }}" | sed 's#refs/tags/v##')]" ;; + *) + HEADER=$(grep -m1 -E '^## \[[0-9]' CHANGELOG.md 2>/dev/null || true) ;; + esac + [ -n "$HEADER" ] || HEADER="## [Unreleased]" + # Print the section body from HEADER (prefix match) until the next "## ". + awk -v h="$HEADER" ' + index($0, h) == 1 { f = 1; next } + f && /^## / { exit } + f { print } + ' CHANGELOG.md > /tmp/notes.md + [ -s /tmp/notes.md ] || echo "See CHANGELOG.md." > /tmp/notes.md + echo "Release notes for '$HEADER':"; cat /tmp/notes.md + + - name: Publish release env: TOKEN: ${{ secrets.FORGEJO_TOKEN }} API: http://xetup-forgejo:3000/api/v1 REPO: ${{ github.repository }} run: | SHORT=$(echo "${{ github.sha }}" | cut -c1-7) + # Version tag -> named, non-prerelease; anything else -> rolling 'latest'. + case "${{ github.ref }}" in + refs/tags/*) + RELTAG=$(echo "${{ github.ref }}" | sed 's#refs/tags/##') + RELNAME="$RELTAG"; PRERELEASE=false ;; + *) + RELTAG="latest"; RELNAME="latest"; PRERELEASE=true ;; + esac - # Delete existing 'latest' release and tag to recreate cleanly + # Body = changelog section + build footer; built with jq so newlines and + # quotes are escaped safely. + BODY=$(printf '%s\n\n_Built from %s_' "$(cat /tmp/notes.md)" "$SHORT") + PAYLOAD=$(jq -n --arg tag "$RELTAG" --arg name "$RELNAME" \ + --arg body "$BODY" --argjson pre "$PRERELEASE" \ + '{tag_name:$tag, name:$name, body:$body, prerelease:$pre}') + + # Replace any existing release for this tag. For rolling 'latest' also + # drop the git tag so it re-points to the new commit; never delete a + # real version tag. RID=$(curl -sf -H "Authorization: token $TOKEN" \ - "$API/repos/$REPO/releases/tags/latest" | jq -r '.id // empty') - if [ -n "$RID" ]; then - curl -sf -X DELETE -H "Authorization: token $TOKEN" \ - "$API/repos/$REPO/releases/$RID" || true - fi - curl -sf -X DELETE -H "Authorization: token $TOKEN" \ + "$API/repos/$REPO/releases/tags/$RELTAG" | jq -r '.id // empty') + [ -n "$RID" ] && curl -sf -X DELETE -H "Authorization: token $TOKEN" \ + "$API/repos/$REPO/releases/$RID" || true + [ "$RELTAG" = "latest" ] && curl -sf -X DELETE -H "Authorization: token $TOKEN" \ "$API/repos/$REPO/tags/latest" || true - # Create new 'latest' release RID=$(curl -sf -X POST \ - -H "Authorization: token $TOKEN" \ - -H "Content-Type: application/json" \ - "$API/repos/$REPO/releases" \ - -d "{\"tag_name\":\"latest\",\"name\":\"latest\",\"body\":\"Auto-built from ${SHORT}\",\"prerelease\":true}" \ - | jq -r '.id') + -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \ + "$API/repos/$REPO/releases" -d "$PAYLOAD" | jq -r '.id') - # Upload xetup.exe curl -sf -X POST \ - -H "Authorization: token $TOKEN" \ - -H "Content-Type: application/octet-stream" \ + -H "Authorization: token $TOKEN" -H "Content-Type: application/octet-stream" \ "$API/repos/$REPO/releases/$RID/assets?name=xetup.exe" \ --data-binary @xetup.exe - echo "Released xetup.exe (commit ${SHORT})" + echo "Released xetup.exe as '$RELNAME' (commit $SHORT)" - name: Update deploy.json # Cosmetic "last build" indicator. Requires docker.sock in the job