From e71195094ad9e3c245819379427a202d155bd8d0 Mon Sep 17 00:00:00 2001 From: Tumelo Konaite Date: Sat, 18 Oct 2025 10:30:53 +0200 Subject: [PATCH 1/3] Adding Tags --- .github/workflows/release.yml | 79 +++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c8585f7..da14dc3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,7 @@ on: push: branches: - main + workflow_dispatch: permissions: contents: write # push tags/commits & create releases @@ -16,7 +17,8 @@ jobs: - name: Checkout Code uses: actions/checkout@v4 with: - fetch-depth: 0 # fetch all history & tags + fetch-depth: 0 # fetch all history & tags + persist-credentials: true - name: Sync with remote main (rebase) run: | @@ -57,6 +59,8 @@ jobs: files: coverage_reports/coverage.xml fail_ci_if_error: true + # --- versioning & notes --- + - name: Determine Version Bump id: version run: | @@ -74,6 +78,7 @@ jobs: run: | git fetch --tags --force latest_tag=$(git tag --sort=-v:refname | head -n 1) + echo "Latest tag: ${latest_tag:-}" echo "tag=${latest_tag}" >> "$GITHUB_OUTPUT" - name: Calculate Next Version @@ -91,43 +96,65 @@ jobs: patch) new_version="$major.$minor.$((patch + 1))" ;; esac + echo "current=$current" echo "new_version=$new_version" >> "$GITHUB_OUTPUT" + - name: Generate Release Notes (commits since last tag) + id: notes + run: | + prev="${{ steps.get_tag.outputs.tag }}" + echo "# Release notes for v${{ steps.semver.outputs.new_version }}" > release_notes.md + echo "" >> release_notes.md + if [ -z "$prev" ]; then + echo "Initial release (no previous tag)." >> release_notes.md + echo "" >> release_notes.md + git log --no-merges --pretty=format:'- %s (%h) by %an' >> release_notes.md + else + echo "Changes since ${prev}:" >> release_notes.md + echo "" >> release_notes.md + git log "${prev}..HEAD" --no-merges --pretty=format:'- %s (%h) by %an' >> release_notes.md + fi + echo "---" + cat release_notes.md + # Escape for multiline output + notes=$(awk '{printf "%s\\n", $0}' release_notes.md) + echo "notes=$notes" >> "$GITHUB_OUTPUT" + + - name: Set up Git credentials for tagging/pushing + run: | + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} + - name: Update version in pyproject.toml run: | new_version=${{ steps.semver.outputs.new_version }} sed -i -E '/^\[project\]/,/^\[.*\]/ s/^version = ".*"/version = "'"$new_version"'"/' pyproject.toml - git config user.name "github-actions" - git config user.email "github-actions@github.com" - git commit -am "chore: bump version to v${new_version}" || echo "No changes to commit" + git add pyproject.toml + git commit -m "chore: bump version to v${new_version}" || echo "No changes to commit" - - name: Create Git Tag & Push (atomic) + - name: Create Annotated Tag with Release Notes run: | - set -e new_tag="v${{ steps.semver.outputs.new_version }}" - # Create the tag only if it doesn't already exist (idempotent reruns) - if ! git rev-parse -q --verify "refs/tags/$new_tag" >/dev/null; then - git tag -a "$new_tag" -m "Release $new_tag" - else - echo "Tag $new_tag already exists; leaving as-is." - fi - # Push commit (HEAD) to main and any new annotated tags together - git push --force-with-lease origin HEAD:main --follow-tags + { + echo "Release ${new_tag}" + echo + cat release_notes.md + } > TAG_MSG.txt + # Recreate tag locally to avoid failures on reruns + git tag -d "$new_tag" 2>/dev/null || true + git tag -a "$new_tag" -F TAG_MSG.txt + + - name: Push main and tag (atomic-ish) + run: | + git push origin main + git push origin "v${{ steps.semver.outputs.new_version }}" + + # --- build & publish --- - name: Build package run: | source .venv/bin/activate uv build - # This workflow runs on push to main, not on a tag ref. Publish using secrets directly. - - name: Publish to PyPI - run: | - source .venv/bin/activate - uv publish --username __token__ --password ${{ secrets.PYPI_TOKEN }} - - - name: Create GitHub Release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - new_tag="v${{ steps.semver.outputs.new_version }}" - gh release create "$new_tag" --title "$new_tag" --notes "Automated release for $new_tag" + - name: Pub From 9ddde0f4901f3ede318f95c157ca5cff8616a0b0 Mon Sep 17 00:00:00 2001 From: Tumelo Konaite Date: Sat, 18 Oct 2025 10:36:21 +0200 Subject: [PATCH 2/3] Adding Tags --- .github/workflows/release.yml | 43 ++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index da14dc3..498fcef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,12 +20,7 @@ jobs: fetch-depth: 0 # fetch all history & tags persist-credentials: true - - name: Sync with remote main (rebase) - run: | - git fetch origin --tags - git checkout main - git pull --rebase origin main - + # ---- build & test first ---- - name: Install uv (latest release) run: | wget -qO- https://astral.sh/uv/install.sh | sh @@ -59,8 +54,7 @@ jobs: files: coverage_reports/coverage.xml fail_ci_if_error: true - # --- versioning & notes --- - + # ---- versioning & release notes ---- - name: Determine Version Bump id: version run: | @@ -85,7 +79,10 @@ jobs: id: semver run: | current=${{ steps.get_tag.outputs.tag }} - if [ -z "$current" ]; then current="v0.1.0"; fi + # default when no tag exists + if [ -z "$current" ]; then + current="v0.1.0" + fi IFS='.' read -r major minor patch <<<"${current#v}" bump=${{ steps.version.outputs.bump }} @@ -116,11 +113,11 @@ jobs: fi echo "---" cat release_notes.md - # Escape for multiline output + # escape for multi-line output variable notes=$(awk '{printf "%s\\n", $0}' release_notes.md) echo "notes=$notes" >> "$GITHUB_OUTPUT" - - name: Set up Git credentials for tagging/pushing + - name: Set up Git credentials (for commit & tag push) run: | git config user.name "github-actions" git config user.email "github-actions@github.com" @@ -141,20 +138,34 @@ jobs: echo cat release_notes.md } > TAG_MSG.txt - # Recreate tag locally to avoid failures on reruns + # Recreate locally in case of rerun git tag -d "$new_tag" 2>/dev/null || true git tag -a "$new_tag" -F TAG_MSG.txt - - name: Push main and tag (atomic-ish) + - name: Push main and tag run: | git push origin main git push origin "v${{ steps.semver.outputs.new_version }}" - # --- build & publish --- - + # ---- build & publish ---- - name: Build package run: | source .venv/bin/activate uv build - - name: Pub + # We’re running on push to main, so publish explicitly (not tag-triggered) + - name: Publish to PyPI + run: | + source .venv/bin/activate + uv publish --username __token__ --password ${{ secrets.PYPI_TOKEN }} + + - name: Create/Update GitHub Release (with notes) + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + new_tag="v${{ steps.semver.outputs.new_version }}" + if gh release view "$new_tag" >/dev/null 2>&1; then + gh release edit "$new_tag" --title "$new_tag" --notes-file release_notes.md + else + gh release create "$new_tag" --title "$new_tag" --notes-file release_notes.md + fi From 7a5d9114c67d6507e11c010d5aa997f340b453b4 Mon Sep 17 00:00:00 2001 From: Tumelo Konaite Date: Sun, 19 Oct 2025 06:56:55 +0200 Subject: [PATCH 3/3] Updated README with Tags --- README.md | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cf0e27f..df335ff 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,28 @@ -[![codecov](https://codecov.io/gh/SoftwareVerse/userverse-python-client/branch/main/graph/badge.svg?token=YOUR_TOKEN)](https://codecov.io/gh/SoftwareVerse/userverse-python-client) + + + + +[![CI - Release Tag](https://github.com/SoftwareVerse/userverse-python-client/actions/workflows/release.yml/badge.svg)](https://github.com/SoftwareVerse/userverse-python-client/actions/workflows/release.yml) + + + +[![Latest Release](https://img.shields.io/github/v/release/SoftwareVerse/userverse-python-client?display_name=tag&sort=semver)](https://github.com/SoftwareVerse/userverse-python-client/releases/latest) + + + +[![Latest Tag](https://img.shields.io/github/v/tag/SoftwareVerse/userverse-python-client?label=tag&sort=semver)](https://github.com/SoftwareVerse/userverse-python-client/releases/latest) + + + +[![Release Date](https://img.shields.io/github/release-date/SoftwareVerse/userverse-python-client)](https://github.com/SoftwareVerse/userverse-python-client/releases/latest) +[![Downloads](https://img.shields.io/github/downloads/SoftwareVerse/userverse-python-client/total)](https://github.com/SoftwareVerse/userverse-python-client/releases) + + + +[![codecov](https://codecov.io/gh/SoftwareVerse/userverse-python-client/branch/main/graph/badge.svg?token=YOUR_TOKEN)](https://codecov.io/gh/SoftwareVerse/userverse-python-client) + # userverse-python-client Python client for the Userverse HTTP server. @@ -10,6 +32,7 @@ Python client for the Userverse HTTP server. Create and activate a virtual environment, then install the project in editable mode: ## linux configuration + ```bash uv venv source .venv\Scripts\activate @@ -17,11 +40,13 @@ uv pip install -e . ``` ## windows configuration + ```bash uv venv .venv\Scripts\activate uv pip install -e . ``` + ## Usage The package currently exposes a greeting helper and a simple arithmetic function. The example below prints both results: @@ -42,7 +67,6 @@ python examples/demo.py uv run python examples/demo.py ``` - ## Tests Run the unit tests with: @@ -53,5 +77,3 @@ python -m unittest discover -s tests -v ## uv run tests uv run python -m unittest discover -s tests -v ``` - -