diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index db9556f3..5486e884 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,9 @@ -name: build +name: build & publish on: push +permissions: + contents: write # Required for creating releases and tags + jobs: test: strategy: @@ -9,8 +12,8 @@ jobs: python_version: ["3.10", "3.11", "3.12", "3.13", "3.14"] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.1.0 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} cache-dependency-path: "**/requirements-dev.txt" @@ -18,3 +21,89 @@ jobs: run: |- pip install -r requirements-dev.txt pytest + + build: + runs-on: ubuntu-latest + needs: + - test + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + - name: Install build dependencies + run: python -m pip install --upgrade build + - name: Build package + run: python -m build + - uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ + + check_version: + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + outputs: + should_publish: ${{ steps.check.outputs.should_publish }} + version: ${{ steps.check.outputs.version }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Check if version tag exists + id: check + run: | + VERSION=$(python -c "import re; print(re.search(r\"version\s*=\s*['\"']([^'\"']+)['\"']\", open('setup.py').read()).group(1))") + echo "version=$VERSION" >> $GITHUB_OUTPUT + if git rev-parse "v${VERSION}" >/dev/null 2>&1; then + echo "Tag v${VERSION} already exists, skipping publish" + echo "should_publish=false" >> $GITHUB_OUTPUT + else + echo "Tag v${VERSION} does not exist, will publish" + echo "should_publish=true" >> $GITHUB_OUTPUT + fi + + publish_to_pypi: + if: github.ref == 'refs/heads/master' && needs.check_version.outputs.should_publish == 'true' + runs-on: ubuntu-latest + needs: + - build + - check_version + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine + - uses: actions/download-artifact@v4 + with: + name: dist + path: dist/ + - name: Publish to PyPI + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: twine upload dist/* + + create_release: + if: github.ref == 'refs/heads/master' && needs.check_version.outputs.should_publish == 'true' + runs-on: ubuntu-latest + needs: + - publish_to_pypi + - check_version + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Create tag and release + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag v${{ needs.check_version.outputs.version }} + git push origin v${{ needs.check_version.outputs.version }} + gh release create v${{ needs.check_version.outputs.version }} --generate-notes + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 07903166..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Publish Python Package - -on: - release: - types: [created] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Setup Python # Set Python version - uses: actions/setup-python@v2 - with: - python-version: 3.14 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel twine - - name: Build and publish - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - run: | - python setup.py sdist bdist_wheel - twine upload dist/*