From ff9d398f6e26a64fc79e781ea4b50842461c90bd Mon Sep 17 00:00:00 2001 From: Adam Bosnjakovic Date: Mon, 11 May 2026 13:24:12 +1000 Subject: [PATCH] ci: replace release-please with workflow_dispatch release Single workflow_dispatch action: bumps version (auto/patch/minor/major), regenerates vimdoc, commits, tags, pushes, creates GH release, uploads to LuaRocks. No intermediate release PR. --- .github/workflows/release.yml | 88 ++++++++++--------------- .release-please-manifest.json | 3 - release-please-config.json | 28 -------- scripts/release.sh | 117 ++++++++++++++++++++++++++++++++++ scripts/test_release.sh | 39 +----------- 5 files changed, 155 insertions(+), 120 deletions(-) delete mode 100644 .release-please-manifest.json delete mode 100644 release-please-config.json create mode 100755 scripts/release.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 12af1a5..026cdd6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,88 +1,70 @@ name: release on: - push: - branches: [main] + workflow_dispatch: + inputs: + bump: + description: "Version bump (auto|patch|minor|major)" + required: true + default: "auto" + type: choice + options: [auto, patch, minor, major] permissions: contents: write - pull-requests: write jobs: release: runs-on: ubuntu-latest steps: - - id: rp - uses: googleapis/release-please-action@v4 + - uses: actions/checkout@v5 with: + fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - config-file: release-please-config.json - manifest-file: .release-please-manifest.json - - if: ${{ steps.rp.outputs.release_created == 'true' }} - uses: actions/checkout@v5 - with: - fetch-depth: 0 + - name: Bump version and update CHANGELOG + id: bump + env: + BUMP: ${{ inputs.bump }} + RELEASE_NOTES_PATH: ${{ runner.temp }}/release-notes.md + run: | + set -euo pipefail + out=$(./scripts/release.sh --bump "$BUMP") + echo "$out" + echo "$out" >> "$GITHUB_OUTPUT" - - if: ${{ steps.rp.outputs.release_created == 'true' }} - uses: kdheepak/panvimdoc@main + - uses: kdheepak/panvimdoc@main with: vimdoc: nyan version: "Neovim >= 0.8.0" demojify: true treesitter: true - - if: ${{ steps.rp.outputs.release_created == 'true' }} - name: Commit vimdoc and move tag + - name: Commit, tag, push env: - TAG: ${{ steps.rp.outputs.tag_name }} + NEXT_VERSION: ${{ steps.bump.outputs.NEXT_VERSION }} run: | set -euo pipefail git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - if ! git diff --quiet -- doc/; then - git add doc/ - git commit -m "chore(release): regenerate vimdoc for ${TAG}" - git push origin HEAD:main - git tag -f "${TAG}" - git push origin "${TAG}" --force - fi - - - if: ${{ steps.rp.outputs.release_created == 'true' }} - id: changelog - env: - VERSION: ${{ steps.rp.outputs.version }} - run: | - set -euo pipefail - tmp=$(mktemp) - awk -v ver="$VERSION" ' - BEGIN { in_section = 0 } - /^## / { - if (in_section) exit - if ($0 ~ "^## \\[?" ver) { in_section = 1; next } - } - in_section { print } - ' CHANGELOG.md > "$tmp" - { - echo "body<> "$GITHUB_OUTPUT" + git add version.txt CHANGELOG.md doc/ + git commit -m "chore(release): v${NEXT_VERSION}" + git tag "v${NEXT_VERSION}" + git push origin HEAD:main + git push origin "v${NEXT_VERSION}" - - if: ${{ steps.rp.outputs.release_created == 'true' }} - name: Create GitHub release + - name: Create GitHub release env: GH_TOKEN: ${{ github.token }} - TAG: ${{ steps.rp.outputs.tag_name }} - BODY: ${{ steps.changelog.outputs.body }} + NEXT_VERSION: ${{ steps.bump.outputs.NEXT_VERSION }} + NOTES_FILE: ${{ steps.bump.outputs.RELEASE_NOTES_PATH }} run: | set -euo pipefail - gh release create "${TAG}" \ - --title "${TAG}" \ - --notes "${BODY}" + gh release create "v${NEXT_VERSION}" \ + --title "v${NEXT_VERSION}" \ + --notes-file "${NOTES_FILE}" - - if: ${{ steps.rp.outputs.release_created == 'true' }} - name: LuaRocks upload + - name: LuaRocks upload uses: nvim-neorocks/luarocks-tag-release@v7 env: LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json deleted file mode 100644 index 8d7e5f1..0000000 --- a/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "1.0.1" -} diff --git a/release-please-config.json b/release-please-config.json deleted file mode 100644 index b59c2ef..0000000 --- a/release-please-config.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", - "release-type": "simple", - "include-component-in-tag": false, - "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": false, - "packages": { - ".": { - "package-name": "nyan.nvim", - "extra-files": ["version.txt"], - "changelog-path": "CHANGELOG.md", - "changelog-sections": [ - { "type": "feat", "section": "Features" }, - { "type": "fix", "section": "Bug Fixes" }, - { "type": "perf", "section": "Performance Improvements" }, - { "type": "revert", "section": "Reverts" }, - { "type": "refactor", "section": "Code Refactoring" }, - { "type": "test", "section": "Tests" }, - { "type": "tests", "section": "Tests" }, - { "type": "build", "section": "Build System" }, - { "type": "ci", "section": "Continuous Integration" }, - { "type": "docs", "section": "Documentation" }, - { "type": "chore", "section": "Miscellaneous Chores", "hidden": true }, - { "type": "style", "section": "Styles", "hidden": true } - ] - } - } -} diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000..238c500 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +# Compute next semver from conventional commits since the last v* tag, +# update version.txt, and prepend a categorised entry to CHANGELOG.md. +# Pure file mutation — does not git add, commit, tag, or push. +# +# Usage: +# scripts/release.sh [--dry-run] [--bump auto|patch|minor|major] +# +# Outputs (for CI consumption): +# prints NEXT_VERSION=x.y.z on stdout +# prints BUMP_KIND=major|minor|patch|none on stdout +# exits 1 if no releasable commits found (and bump=auto) + +set -euo pipefail + +cd "$(dirname "$0")/.." + +DRY_RUN=0 +BUMP_MODE="auto" + +while [ $# -gt 0 ]; do + case "$1" in + --dry-run) DRY_RUN=1 ;; + --bump) BUMP_MODE="${2:?--bump requires a value}"; shift ;; + --bump=*) BUMP_MODE="${1#--bump=}" ;; + *) echo "unknown arg: $1" >&2; exit 2 ;; + esac + shift +done + +case "$BUMP_MODE" in + auto|patch|minor|major) ;; + *) echo "invalid --bump: $BUMP_MODE (expected auto|patch|minor|major)" >&2; exit 2 ;; +esac + +current=$(cat version.txt) +prev_tag=$(git describe --tags --abbrev=0 --match 'v*' 2>/dev/null || git rev-list --max-parents=0 HEAD) + +if [ "$BUMP_MODE" = "auto" ]; then + bump="none" + while IFS= read -r line; do + case "$line" in + *"BREAKING CHANGE"*|*"!:"*) bump="major" ;; + feat:*|feat\(*\):*) [ "$bump" != "major" ] && bump="minor" ;; + fix:*|fix\(*\):*|perf:*|perf\(*\):*) [ "$bump" = "none" ] && bump="patch" ;; + esac + done < <(git log "${prev_tag}..HEAD" --pretty=format:"%s" --no-merges) +else + bump="$BUMP_MODE" +fi + +if [ "$bump" = "none" ]; then + echo "BUMP_KIND=none" + echo "no feat/fix/perf commits since ${prev_tag}; nothing to release" >&2 + exit 1 +fi + +IFS='.' read -r major minor patch <<< "$current" +case "$bump" in + major) next="$((major + 1)).0.0" ;; + minor) next="${major}.$((minor + 1)).0" ;; + patch) next="${major}.${minor}.$((patch + 1))" ;; +esac + +repo_url=$(git config --get remote.origin.url | sed -E 's|\.git$||; s|^git@github.com:|https://github.com/|') +today=$(date -u +%Y-%m-%d) + +section() { + local title="$1"; shift + local pattern="$1" + local lines + lines=$(git log "${prev_tag}..HEAD" --no-merges --pretty=format:"%h%x09%s" \ + | awk -F'\t' -v p="$pattern" '$2 ~ p { sub(/^[a-z]+(\([^)]*\))?!?:[[:space:]]*/, "", $2); print $1 "\t" $2 }') + [ -z "$lines" ] && return + printf '\n### %s\n\n' "$title" + while IFS=$'\t' read -r sha msg; do + printf '* %s ([%s](%s/commit/%s))\n' "$msg" "$sha" "$repo_url" "$sha" + done <<< "$lines" +} + +entry=$( + printf '## [%s](%s/compare/v%s...v%s) (%s)\n' "$next" "$repo_url" "$current" "$next" "$today" + section "Features" '^feat[(!:]' + section "Bug Fixes" '^fix[(!:]' + section "Performance" '^perf[(!:]' + section "Reverts" '^revert[(!:]' + section "Code Refactoring" '^refactor[(!:]' + section "Tests" '^test[(!:]' + section "Build System" '^build[(!:]' + section "Continuous Integration" '^ci[(!:]' + section "Documentation" '^docs[(!:]' +) + +echo "BUMP_KIND=${bump}" +echo "NEXT_VERSION=${next}" + +if [ "$DRY_RUN" = "1" ]; then + echo "--- dry run: changelog entry ---" >&2 + printf '%s\n' "$entry" >&2 + exit 0 +fi + +printf '%s\n' "$next" > version.txt + +tmp=$(mktemp) +{ + head -n 1 CHANGELOG.md + echo + printf '%s\n' "$entry" + tail -n +2 CHANGELOG.md +} > "$tmp" +mv "$tmp" CHANGELOG.md + +# Emit changelog body (without leading "## [..](...)" heading) for downstream GH-release notes. +notes_path="${RELEASE_NOTES_PATH:-$(mktemp)}" +printf '%s\n' "$entry" | tail -n +2 > "$notes_path" +echo "RELEASE_NOTES_PATH=${notes_path}" diff --git a/scripts/test_release.sh b/scripts/test_release.sh index 88494c8..10a4a30 100755 --- a/scripts/test_release.sh +++ b/scripts/test_release.sh @@ -1,40 +1,7 @@ #!/usr/bin/env bash -# Local simulation of the release-please bump + CHANGELOG generation. -# Does not push, tag, or call gh; prints what the next release would look like. +# Dry run of the release script: prints next version and changelog preview +# without writing version.txt or CHANGELOG.md. set -euo pipefail cd "$(dirname "$0")/.." - -current=$(cat version.txt) -prev_tag=$(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD) - -# Walk commits since the last tag. Bump rules: -# feat!: / fix!: / BREAKING CHANGE: -> major -# feat: -> minor -# fix: / perf: -> patch -# anything else -> no bump -bump="none" -while IFS= read -r line; do - case "$line" in - *"BREAKING CHANGE"*|*"!:"*) bump="major" ;; - feat:*|feat\(*\):*) [ "$bump" != "major" ] && bump="minor" ;; - fix:*|fix\(*\):*|perf:*|perf\(*\):*) [ "$bump" = "none" ] && bump="patch" ;; - esac -done < <(git log "${prev_tag}..HEAD" --pretty=format:"%s" --no-merges) - -IFS='.' read -r major minor patch <<< "$current" -case "$bump" in - major) next="$((major + 1)).0.0" ;; - minor) next="${major}.$((minor + 1)).0" ;; - patch) next="${major}.${minor}.$((patch + 1))" ;; - none) next="(no release — no feat/fix/perf commits since ${prev_tag})" ;; -esac - -echo "current: ${current}" -echo "previous: ${prev_tag}" -echo "bump kind: ${bump}" -echo "next: ${next}" -echo -echo "--- changelog preview ---" -git log "${prev_tag}..HEAD" --pretty=format:"- %s" --no-merges || true -echo +exec ./scripts/release.sh --dry-run "$@"