Files
BudsieBuds 97045aca68 fix(release): normalize release tag version and automate template updates
- release.yml:
  - Normalize App.php, package.json, and package-lock.json to clean release version ($TARGET) prior to tagging, ensuring tagged commits contain clean release metadata in git history.
  - Update release commit message to `chore(release): release <version>` to reflect that code, manifests, and templates are committed.
  - Automate updating issue templates (bug report.yml and feature_request.yml) on release: prepends new release, retains top 5 versions, and preserves the fallback option.
  - Automate updating supported versions in SECURITY.md (>= $TARGET and < $TARGET).
  - Remove automated regex update of README.md: the intro sentence describes the v3.4 rewrite to CI4, so blindly regex-replacing the version on future releases produces misleading prose and is brittle against wording edits.
  - Add concurrency group `release` and restrict workflow execution to master branch.
  - Bump App.php, package.json, and package-lock.json to next dev snapshot ($NEXT) in post-release commit.

- build-release.yml:
  - Remove redundant VERSION="${VERSION%-dev}" check and in-runner normalization step now that release commits are clean.

- Templates and Security Policy:
  - Add OpenSourcePOS 3.4.3 to bug report.yml, feature_request.yml, and SECURITY.md.
  - Add "- Older version (specify in description)" fallback option to issue templates.
  - Remove default selection in bug report.yml so reporters specify version explicitly.
2026-10-24 23:14:50 +02:00

208 lines
9.1 KiB
YAML

name: Release
# Cuts the current release (changelog + tag + draft release) and, optionally,
# bumps master to the next dev version. One workflow, full release cycle.
#
# Flow:
# 1. Release current version:
# - generate git-cliff changelog section (base..HEAD)
# - insert it into CHANGELOG.md + GFM compare refs
# - normalize source version to clean release (strip -dev)
# - update issue templates / SECURITY.md
# - commit + push the release commit
# - tag the current version and push the tag with the repo PAT
# (a PAT push triggers build-release.yml, whose official-release job
# creates the DRAFT GitHub Release with the changelog + assets)
# 2. (optional) bump to the next dev version:
# - bump App.php / package.json / package-lock.json to next dev snapshot
# - commit + push
on:
workflow_dispatch:
inputs:
next_bump:
description: 'After cutting this release, bump master to the next dev version'
required: true
type: choice
options:
- patch
- minor
- major
- skip
default: 'patch'
concurrency:
group: release
cancel-in-progress: false
permissions:
contents: write
jobs:
release:
name: Cut release and bump next version
runs-on: ubuntu-22.04
if: github.ref == 'refs/heads/master'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
# Use the repo PAT (an admin token) so the changelog + bump pushes
# below can update the protected master branch (enforce_admins is off).
# GITHUB_TOKEN cannot, because master requires a PR review.
token: ${{ secrets.TOKEN }}
- name: Install git-cliff
run: |
V=2.14.2
curl -sLSfL "https://github.com/orhun/git-cliff/releases/download/v${V}/git-cliff-${V}-x86_64-unknown-linux-musl.tar.gz" -o /tmp/cliff.tar.gz
tar xzf /tmp/cliff.tar.gz -C /tmp
mv "/tmp/git-cliff-${V}/git-cliff" /usr/local/bin/git-cliff
chmod +x /usr/local/bin/git-cliff
git cliff --version
- name: Determine version
id: version
run: |
APP_VERSION=$(grep "application_version" app/Config/App.php | sed "s/.*= '\(.*\)';/\1/g")
# Master carries a -dev snapshot suffix; strip it for the release target.
TARGET="${APP_VERSION%-dev}"
if ! [[ "$TARGET" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "ERROR: target '$TARGET' is not in X.Y.Z form"; exit 1
fi
BASE=$(git tag --list | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1)
if [ -z "$BASE" ]; then
echo "ERROR: no previous release tag found"; exit 1
fi
if [ "$BASE" = "$TARGET" ]; then
echo "ERROR: target $TARGET equals base $BASE; nothing to release"; exit 1
fi
if ! printf '%s\n%s\n' "$BASE" "$TARGET" | sort -VC 2>/dev/null; then
echo "ERROR: target $TARGET is not greater than base $BASE"; exit 1
fi
echo "target=$TARGET" >> "$GITHUB_OUTPUT"
echo "base=$BASE" >> "$GITHUB_OUTPUT"
echo "Releasing $TARGET (previous release: $BASE)"
- name: Generate changelog section
run: |
git cliff --config cliff.toml \
--tag "${{ steps.version.outputs.target }}" \
--output /tmp/section.md \
"${{ steps.version.outputs.base }}..HEAD"
sed -i '/./,$!d' /tmp/section.md
echo "Generated $(grep -c '^- ' /tmp/section.md) entries"
echo "=== first 5 ==="
head -5 /tmp/section.md
- name: Insert into CHANGELOG.md
run: |
TARGET="${{ steps.version.outputs.target }}"
BASE="${{ steps.version.outputs.base }}"
sed -i "/^\[unreleased\]:/a [${TARGET}]: https://github.com/opensourcepos/opensourcepos/compare/${BASE}...${TARGET}" CHANGELOG.md
sed -i "s|^\[unreleased\]:.*|\[unreleased\]: https://github.com/opensourcepos/opensourcepos/compare/${TARGET}...HEAD|" CHANGELOG.md
LINE=$(grep -nE '^## \[[0-9]+\.' CHANGELOG.md | head -1 | cut -d: -f1)
printf '%s\n\n' "$(cat /tmp/section.md)" > /tmp/section_final.md
sed -i "$((LINE-1))r /tmp/section_final.md" CHANGELOG.md
echo "Inserted $TARGET section before line $LINE"
- name: Commit release and docs
run: |
TARGET="${{ steps.version.outputs.target }}"
# Normalize source version to clean release version so git tag does not carry -dev suffix
sed -i "s/public string \\\$application_version = '[^']*';/public string \\\$application_version = '$TARGET';/" app/Config/App.php
sed -i "s/\"version\": \"[^\"]*\",/\"version\": \"$TARGET\",/" package.json
awk -v v="$TARGET" '
/"name": "@opensourcepos\/opensourcepos"/ { expect=1 }
expect && /"version": / { sub(/"version": "[^"]*"/, "\"version\": \"" v "\""); expect=0 }
{ print }
' package-lock.json > .package-lock.tmp && mv .package-lock.tmp package-lock.json
# Update SECURITY.md supported version to current release
sed -i -E "s/>= [0-9]+\.[0-9]+\.[0-9]+/>= $TARGET/" SECURITY.md
sed -i -E "s/< [0-9]+\.[0-9]+\.[0-9]+/< $TARGET/" SECURITY.md
# Update issue templates with the released version
for template in ".github/ISSUE_TEMPLATE/bug report.yml" ".github/ISSUE_TEMPLATE/feature_request.yml"; do
[ -f "$template" ] || continue
awk -v v="$TARGET" -v max=5 '
BEGIN { in_opts=0; count=0 }
/id: ospos-version/ { in_opts=1 }
in_opts && /- (master \/ )?development \(unreleased\)/ {
print
print " - OpenSourcePOS " v
next
}
in_opts && /^[ ]*- OpenSourcePOS / {
if ($0 ~ "OpenSourcePOS " v "$") next
count++
if (count < max) print
next
}
in_opts && /^[ ]*(default:|validations:|- type:|- Other|- Older)/ {
in_opts=0
print
next
}
{ print }
' "$template" > "$template.tmp" && mv "$template.tmp" "$template"
done
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add CHANGELOG.md app/Config/App.php package.json package-lock.json SECURITY.md .github/ISSUE_TEMPLATE/
git commit -m "chore(release): release ${{ steps.version.outputs.target }}"
git push origin HEAD
- name: Tag and push (PAT triggers build-release.yml)
run: |
TAG="${{ steps.version.outputs.target }}"
git tag "$TAG"
# Push with the repo PAT (not GITHUB_TOKEN) so the tag-push event
# triggers build-release.yml, whose official-release job creates the
# draft release with the changelog and assets.
git push "https://x-access-token:${RELEASE_PAT}@github.com/opensourcepos/opensourcepos.git" "refs/tags/$TAG"
echo "Released $TAG — draft release will be created by build-release.yml"
env:
RELEASE_PAT: ${{ secrets.TOKEN }}
- name: Bump to next dev version (optional)
if: ${{ inputs.next_bump != 'skip' }}
run: |
CURRENT="${{ steps.version.outputs.target }}"
MAJOR=$(echo "$CURRENT" | cut -d. -f1)
MINOR=$(echo "$CURRENT" | cut -d. -f2)
PATCH=$(echo "$CURRENT" | cut -d. -f3)
case "${{ inputs.next_bump }}" in
major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
patch) PATCH=$((PATCH + 1)) ;;
*) echo "ERROR: unknown bump type ${{ inputs.next_bump }}"; exit 1 ;;
esac
NEXT="${MAJOR}.${MINOR}.${PATCH}-dev"
echo "Bumping to next dev version $NEXT"
sed -i "s/public string \\\$application_version = '[^']*';/public string \\\$application_version = '$NEXT';/" app/Config/App.php
sed -i "s/\"version\": \"[^\"]*\",/\"version\": \"$NEXT\",/" package.json
# Keep package-lock.json in sync: bump only the @opensourcepos/opensourcepos
# package version (top-level + packages.""), leave dependency versions alone.
awk -v v="$NEXT" '
/"name": "@opensourcepos\/opensourcepos"/ { expect=1 }
expect && /"version": / { sub(/"version": "[^"]*"/, "\"version\": \"" v "\""); expect=0 }
{ print }
' package-lock.json > .package-lock.tmp && mv .package-lock.tmp package-lock.json
echo "=== version refs after bump ==="
grep "application_version" app/Config/App.php
grep '"version"' package.json | head -1
grep -A1 '"name": "@opensourcepos/opensourcepos"' package-lock.json
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add app/Config/App.php package.json package-lock.json
git commit -m "chore: bump version to $NEXT"
git push origin HEAD