Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 33 additions & 113 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,50 +27,50 @@ jobs:
test:
uses: ./.github/workflows/test.yaml

check-version:
# Only run version check for manual releases
check-semver:
if: github.ref_name == github.event.repository.default_branch
# if: github.event_name == 'workflow_dispatch' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
runs-on: ubuntu-latest
timeout-minutes: 30

outputs:
release-version: ${{ steps.bump_version.outputs.release_version }}

steps:
- name: Checkout the code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Get version
id: version
- name: Get latest tag
id: get_tag
run: |
version=$(git describe --abbrev=0 --tags)
echo $version
echo "version=${version}" >> $GITHUB_OUTPUT

- name: Semver check
id: semver_check
uses: madhead/semver-utils@v4
with:
lenient: false
version: ${{ inputs.release-version }}
compare-to: ${{ steps.version.outputs.version }}
tag=$(git describe --tags --abbrev=0 || echo "v0.0.0")
echo "Latest tag: $tag"
echo "tag=$tag" >> $GITHUB_OUTPUT

- name: Semver ok
if: steps.semver_check.outputs.comparison-result != '>'
- name: Calculate next version
id: bump_version
run: |
echo "The release version is not valid Semver (${{ inputs.release-version }}) that is greater than the current version ${{ steps.version.outputs.version }}."
exit 1
latest=${{ steps.get_tag.outputs.tag }}
# Strip the 'v' prefix
latest=${latest#v}

release:
needs: [test, check-version]
if: needs.check-version.result == 'success'
# For manual releases, also need version check ------
IFS='.' read -r major minor patch <<< "$latest"
patch=$((patch + 1))
next_version="v$major.$minor.$patch"

echo "Next version will be: $next_version"
echo "release_version=$next_version" >> $GITHUB_OUTPUT

# if: always() && needs.test.result == 'success' && (needs.check-version.result == 'success' || needs.check-version.result == 'skipped')
release:
needs: [test, check-semver]
if: needs.check-semver.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 30

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_VERSION: ${{ needs.check-semver.outputs.release-version }}

steps:
- name: Checkout the code
Expand All @@ -84,112 +84,32 @@ jobs:
- name: Install the project
run: uv sync --frozen --all-groups --python 3.12

- name: Determine version
id: version
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "version=${{ inputs.release-version }}" >> $GITHUB_OUTPUT
echo "Manual release triggered with version: ${{ inputs.release-version }}"
else
# For automatic releases, use semantic versioning
# Get the latest tag
latest_tag=$(git describe --abbrev=0 --tags 2>/dev/null || echo "0.0.0")
echo "Latest tag: $latest_tag"

# Remove 'v' prefix if present for calculations
clean_tag=${latest_tag#v}

# Check commit messages for version bump type since last tag
if [ "$latest_tag" = "0.0.0" ]; then
commits=$(git log --pretty=format:"%s")
else
commits=$(git log ${latest_tag}..HEAD --pretty=format:"%s")
fi

echo "Commits since last tag:"
echo "$commits"

# Check if there are any commits
if [ -z "$commits" ]; then
echo "No new commits since last tag, skipping release"
echo "skip=true" >> $GITHUB_OUTPUT
exit 0
fi

# Determine version bump based on conventional commits
if echo "$commits" | grep -qE "^feat(\(.+\))?:|^BREAKING CHANGE"; then
# Minor version bump for features
new_version=$(echo $clean_tag | awk -F. '{print ($1"."($2+1)".0")}')
elif echo "$commits" | grep -qE "^fix(\(.+\))?:|^perf(\(.+\))?:"; then
# Patch version bump for fixes
new_version=$(echo $clean_tag | awk -F. '{print ($1"."$2"."($3+1))}')
else
echo "No version-bumping commits found (no feat:, fix:, or perf: commits)"
echo "Commits found:"
echo "$commits"
echo "skip=true" >> $GITHUB_OUTPUT
exit 0
fi

echo "version=$new_version" >> $GITHUB_OUTPUT
echo "Determined new version: $new_version"
fi

- name: Skip release if no version change
if: steps.version.outputs.skip == 'true'
run: |
echo "Skipping release - no version-bumping commits found"
exit 0

- name: Update version in pyproject.toml
if: steps.version.outputs.skip != 'true'
run: |
version="${{ steps.version.outputs.version }}"
echo "Updating pyproject.toml to version: $version"

# Update version in pyproject.toml
sed -i "s/version = \"[^\"]*\"/version = \"$version\"/" pyproject.toml

# Show the change
echo "Updated pyproject.toml:"
grep 'version = ' pyproject.toml

- name: Build Changelog
id: github_release
uses: mikepenz/release-changelog-builder-action@v5
with:
toTag: ${{ inputs.release-version }}
toTag: ${{ env.RELEASE_VERSION }}
configuration: ".github/changelog_config.json"

- name: Build the wheel and sdist
if: steps.version.outputs.skip != 'true'
run: uv build

- name: Create and push git tag
run: |

# Configure git
git config --global user.name "${GITHUB_ACTOR}"
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"

git tag -a "${RELEASE_VERSION}" -m "Release version ${RELEASE_VERSION}"
git push origin "${RELEASE_VERSION}"

# Tag the release
git tag -a "v$version" -m "Release version $version"

# Push the changes and tags
git push origin main
git push origin "${{ inputs.release-version }}"
- name: Build the wheel and sdist
run: uv build

- name: Publish package to PyPI
if: steps.version.outputs.skip != 'true'
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
packages-dir: dist/

- name: Create GitHub Release
if: steps.version.outputs.skip != 'true'
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.version.outputs.version }}
body: ${{steps.github_release.outputs.changelog}}
tag_name: ${{ env.RELEASE_VERSION }}
body: ${{ steps.github_release.outputs.changelog }}