Skip to content

Merge pull request #46 from cloudengine-labs/release/v0.4.1 #4

Merge pull request #46 from cloudengine-labs/release/v0.4.1

Merge pull request #46 from cloudengine-labs/release/v0.4.1 #4

Workflow file for this run

name: Release — Version Bump & Publish
# Runs on every direct push to main (human or PR merge).
# Bot-authored commits are skipped to prevent infinite loops.
on:
push:
branches: [main]
permissions:
contents: write # needed to push the release branch and create tags
pull-requests: write # needed to open the version-bump PR
jobs:
version-bump:
name: Bump patch version, update docs, open PR & tag
runs-on: ubuntu-latest
# Skip commits that were already made by this workflow (or any bot) to
# avoid triggering an infinite bump loop.
# Also skip merges of the automated release/vX.Y.Z PRs: a regular merge
# produces a commit message starting with "Merge pull request" that also
# references the release/vX.Y.Z branch name.
if: >-
github.actor != 'github-actions[bot]' &&
!contains(github.event.head_commit.message, '[skip ci]') &&
!(startsWith(github.event.head_commit.message, 'Merge pull request') &&
contains(github.event.head_commit.message, 'release/v'))
steps:
- name: Checkout repository (full history for tagging)
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
# ── 1. Compute new patch version ─────────────────────────────────────
- name: Compute and apply patch version bump
id: bump
run: |
python - <<'PYEOF'
import re, sys
path = "cli/__version__.py"
with open(path) as fh:
content = fh.read()
m = re.search(r'__version__\s*=\s*"(\d+)\.(\d+)\.(\d+)"', content)
if not m:
print("ERROR: could not find __version__ in cli/__version__.py", file=sys.stderr)
sys.exit(1)
major, minor, patch = int(m.group(1)), int(m.group(2)), int(m.group(3))
new_version = f"{major}.{minor}.{patch + 1}"
new_content = re.sub(
r'(__version__\s*=\s*)"[^"]+"',
f'\\1"{new_version}"',
content,
)
with open(path, "w") as fh:
fh.write(new_content)
print(f"Bumped {major}.{minor}.{patch} → {new_version}")
# Expose new version to subsequent steps via GITHUB_OUTPUT
import os
with open(os.environ["GITHUB_OUTPUT"], "a") as out:
out.write(f"new_version={new_version}\n")
PYEOF
# ── 2. Update CHANGELOG.md ────────────────────────────────────────────
- name: Prepend CHANGELOG entry for new version
env:
NEW_VERSION: ${{ steps.bump.outputs.new_version }}
run: |
python - <<'PYEOF'
import os
from datetime import date
new_version = os.environ["NEW_VERSION"]
today = date.today().isoformat()
entry = (
f"\n## [{new_version}] - {today}\n\n"
f"### Changed\n"
f"- Automated patch release — version bump to {new_version}.\n\n"
f"---\n"
)
with open("CHANGELOG.md") as fh:
content = fh.read()
# Insert the new entry before the first existing release section
marker = "\n## ["
if marker not in content:
print("WARNING: no existing release section found in CHANGELOG.md; appending entry")
new_content = content + entry
else:
insert_at = content.index(marker)
new_content = content[:insert_at] + entry + content[insert_at:]
with open("CHANGELOG.md", "w") as fh:
fh.write(new_content)
print(f"CHANGELOG updated with {new_version} entry")
PYEOF
# ── 3. Update version badge in Hugo docs index ────────────────────────
- name: Update version badge in Hugo docs
env:
NEW_VERSION: ${{ steps.bump.outputs.new_version }}
run: |
# Replace any existing version-X.Y.Z-blue badge with the new version
sed -i -E \
"s|version-[0-9]+\.[0-9]+\.[0-9]+-blue|version-${NEW_VERSION}-blue|g" \
hugo-docs/content/_index.md
# ── 4. Open a PR with the version-bump changes ────────────────────────
# peter-evans/create-pull-request creates commits via the GitHub API so
# they are automatically verified (signed), satisfying the branch
# protection rule that requires signed commits. It also opens a PR
# instead of pushing directly to main, satisfying the rule that all
# changes must go through a pull request.
- name: Create pull request for version bump
id: cpr
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: release/v${{ steps.bump.outputs.new_version }}
commit-message: "chore: bump version to v${{ steps.bump.outputs.new_version }} [skip ci]"
title: "chore: bump version to v${{ steps.bump.outputs.new_version }}"
body: |
Automated patch version bump to `v${{ steps.bump.outputs.new_version }}`.
- Updates `cli/__version__.py`
- Prepends entry to `CHANGELOG.md`
- Updates version badge in `hugo-docs/content/_index.md`
labels: |
release
automated
add-paths: |
cli/__version__.py
CHANGELOG.md
hugo-docs/content/_index.md
# ── 5. Tag the PR branch's head commit ──────────────────────────────────
# Tag the commit on the release branch (not the local main checkout) so
# the tag always points to the exact commit that carries the version bump.
- name: Create and push git tag
if: steps.cpr.outputs.pull-request-number != ''
env:
NEW_VERSION: ${{ steps.bump.outputs.new_version }}
TAG_SHA: ${{ steps.cpr.outputs.pull-request-head-sha }}
run: |
git tag "v${NEW_VERSION}" "${TAG_SHA}"
git push origin "v${NEW_VERSION}"