CI / Tests (PHP 8.1) (pull_request) Successful in 49s
CI / Tests (PHP 8.2) (pull_request) Successful in 48s
CI / No Debug Code (pull_request) Successful in 3s
CI / Tests (PHP 8.3) (pull_request) Successful in 7m54s
CI / PHPStan (pull_request) Successful in 9m2s
CI / Coding Standards (pull_request) Successful in 9m12s
CI / Build Plugin Zip (pull_request) Skipped
Add CHANGELOG.md (one section per version, newest first; the top section always reflects the current plugin header version — release status is purely a matter of tagging). The Release workflow now extracts the tagged version's changelog section and publishes it as the Gitea release body (POST on create, PATCH when the release was pre-created via the UI). After a stable release, a new bump-version job bumps the plugin to the next patch version, opens a fresh changelog section, and opens a PR. Pre-release tags are skipped. Co-Authored-By: Claude Opus 4.8 <[email protected]>
166 lines
6.8 KiB
YAML
166 lines
6.8 KiB
YAML
name: Release
|
|
|
|
# Fires when a v* tag is pushed — including tags created through Gitea's
|
|
# "New Release" UI. Builds the distributable plugin zip and attaches it to
|
|
# the release for that tag (creating the release if only a bare tag was
|
|
# pushed). The attached zip is what UpdateChecker serves to WordPress
|
|
# sites as the update package.
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
|
|
jobs:
|
|
release:
|
|
name: Build and Publish Release
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Setup PHP
|
|
uses: shivammathur/setup-php@v2
|
|
with:
|
|
php-version: '8.3'
|
|
tools: composer:v2
|
|
|
|
# A tag that disagrees with the plugin header would make sites see a
|
|
# phantom update forever (or never see a real one), so fail fast.
|
|
- name: Verify tag matches plugin version
|
|
id: meta
|
|
run: |
|
|
tag_version="${GITHUB_REF_NAME#v}"
|
|
header_version="$(sed -nE 's/^[[:space:]]*\*?[[:space:]]*Version:[[:space:]]*([^[:space:]]+).*/\1/p' unsupervised-schedular.php | head -1)"
|
|
if [ "$tag_version" != "$header_version" ]; then
|
|
echo "Tag ${GITHUB_REF_NAME} does not match plugin header Version: ${header_version}" >&2
|
|
exit 1
|
|
fi
|
|
echo "version=${header_version}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Install dependencies
|
|
run: composer install --prefer-dist --no-progress --no-interaction
|
|
|
|
- name: Run tests
|
|
run: composer test
|
|
|
|
- name: Build plugin zip
|
|
run: composer build
|
|
|
|
# Pull the section for this version out of CHANGELOG.md so it can become
|
|
# the release body. Matches "## [x.y.z]" and prints every line up to the
|
|
# next "## " heading. A missing section is a warning, not a failure — the
|
|
# release still publishes with empty notes.
|
|
- name: Extract changelog notes
|
|
run: |
|
|
version="${{ steps.meta.outputs.version }}"
|
|
awk -v ver="$version" '
|
|
$0 ~ "^## \\[" ver "\\]" { found = 1; next }
|
|
found && /^## / { exit }
|
|
found { print }
|
|
' CHANGELOG.md | sed -e '/./,$!d' | tac | sed -e '/./,$!d' | tac > release-notes.md
|
|
if [ ! -s release-notes.md ]; then
|
|
echo "::warning::No CHANGELOG.md section found for version ${version}"
|
|
fi
|
|
|
|
- name: Publish release with zip asset
|
|
env:
|
|
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
api="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
|
|
version="${{ steps.meta.outputs.version }}"
|
|
zip="dist/unsupervised-schedular-${version}.zip"
|
|
|
|
# Pre-release versions (1.2.3-rc.1) are flagged so Gitea's
|
|
# /releases/latest endpoint — and therefore the update checker —
|
|
# skips them.
|
|
prerelease=false
|
|
case "$version" in *-*) prerelease=true ;; esac
|
|
|
|
# Reuse the release if the tag was created via Gitea's release UI.
|
|
release_id="$(curl -sS -H "Authorization: token ${TOKEN}" \
|
|
"${api}/releases/tags/${GITHUB_REF_NAME}" | jq -r '.id // empty' || true)"
|
|
|
|
if [ -z "$release_id" ]; then
|
|
body="$(jq -Rs --arg tag "${GITHUB_REF_NAME}" --argjson pre "${prerelease}" \
|
|
'{tag_name:$tag, name:$tag, prerelease:$pre, body:.}' release-notes.md)"
|
|
release_id="$(curl -fsS -X POST "${api}/releases" \
|
|
-H "Authorization: token ${TOKEN}" \
|
|
-H 'Content-Type: application/json' \
|
|
-d "${body}" | jq -r '.id')"
|
|
else
|
|
# Release pre-created via the UI: fill in the notes from the changelog.
|
|
body="$(jq -Rs '{body:.}' release-notes.md)"
|
|
curl -fsS -X PATCH "${api}/releases/${release_id}" \
|
|
-H "Authorization: token ${TOKEN}" \
|
|
-H 'Content-Type: application/json' \
|
|
-d "${body}" > /dev/null
|
|
fi
|
|
|
|
echo "Attaching ${zip} to release ${release_id}"
|
|
curl -fsS -X POST \
|
|
"${api}/releases/${release_id}/assets?name=unsupervised-schedular-${version}.zip" \
|
|
-H "Authorization: token ${TOKEN}" \
|
|
-F "attachment=@${zip}" > /dev/null
|
|
|
|
# After a stable release, move main forward: bump the plugin to the next patch
|
|
# version and open a fresh changelog section for it, via a PR. Skipped for
|
|
# pre-releases (tags containing a hyphen, e.g. v1.2.0-rc.1) — those don't
|
|
# advance the mainline version.
|
|
bump-version:
|
|
name: Open next-version bump PR
|
|
needs: release
|
|
if: ${{ !contains(github.ref_name, '-') }}
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: main
|
|
fetch-depth: 0
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Compute next patch version
|
|
id: next
|
|
run: |
|
|
current="$(sed -nE 's/^[[:space:]]*\*?[[:space:]]*Version:[[:space:]]*([^[:space:]]+).*/\1/p' unsupervised-schedular.php | head -1)"
|
|
base="${current%%-*}" # drop any pre-release suffix
|
|
major="${base%%.*}"
|
|
rest="${base#*.}"
|
|
minor="${rest%%.*}"
|
|
patch="${rest#*.}"
|
|
next="${major}.${minor}.$((patch + 1))"
|
|
echo "next=${next}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Apply version bump and open changelog section
|
|
run: |
|
|
next="${{ steps.next.outputs.next }}"
|
|
# Plugin header + USC_VERSION constant must stay in lockstep.
|
|
sed -i -E "s/^([[:space:]]*\*?[[:space:]]*Version:[[:space:]]*).*/\1${next}/" unsupervised-schedular.php
|
|
sed -i -E "s/(define\('USC_VERSION', ')[^']+('\);)/\1${next}\2/" unsupervised-schedular.php
|
|
# Insert an empty section for the new version above the current top one
|
|
# (the first "## [" heading in the file).
|
|
awk -v ver="$next" '
|
|
!done && /^## \[/ { print "## [" ver "]"; print ""; done = 1 }
|
|
{ print }
|
|
' CHANGELOG.md > CHANGELOG.md.tmp && mv CHANGELOG.md.tmp CHANGELOG.md
|
|
|
|
- name: Open pull request
|
|
env:
|
|
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
next="${{ steps.next.outputs.next }}"
|
|
branch="release/bump-${next}"
|
|
api="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
|
|
|
|
git config user.name 'Release Bot'
|
|
git config user.email '[email protected]'
|
|
git checkout -b "${branch}"
|
|
git commit -am "Bump version to ${next} and open changelog section"
|
|
git push origin "${branch}"
|
|
|
|
curl -fsS -X POST "${api}/pulls" \
|
|
-H "Authorization: token ${TOKEN}" \
|
|
-H 'Content-Type: application/json' \
|
|
-d "$(jq -n --arg head "${branch}" --arg title "Bump version to ${next}" \
|
|
'{head:$head, base:"main", title:$title, body:"Automated post-release bump to the next patch version. Record changes for this version under its changelog heading."}')" \
|
|
> /dev/null
|