cancel-in-flight -> cancel-in-progress #5
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Pipeline | ||
|
Check failure on line 1 in .github/workflows/release.yml
|
||
| on: | ||
| push: | ||
| tags: | ||
| - 'v*' # trigger on version tags | ||
| pull_request: | ||
| branches: [ master ] | ||
| # Allow only one concurrent deployment to avoid conflicts | ||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true | ||
| jobs: | ||
| validate-version: | ||
| name: Validate tag version | ||
| runs-on: ubuntu-latest | ||
| if: startsWith(github.ref, 'refs/tags/v') | ||
| outputs: | ||
| tag_version: ${{ steps.tag-version.outputs.TAG_VERSION }} | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Extract package version | ||
| id: package-version | ||
| run: | | ||
| # Extract version from pyproject.toml | ||
| PACKAGE_VERSION=$(python -c " | ||
| import tomli | ||
| with open('pyproject.toml', 'rb') as f: | ||
| data = tomli.load(f) | ||
| print(data['project']['version']) | ||
| ") | ||
| echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_OUTPUT | ||
| - name: Extract tag version | ||
| id: tag-version | ||
| run: | | ||
| TAG_VERSION="${GITHUB_REF#refs/tags/v}" | ||
| echo "TAG_VERSION=$TAG_VERSION" >> $GITHUB_OUTPUT | ||
| - name: Validate versions match | ||
| run: | | ||
| PACKAGE_VERSION="${{ steps.package-version.outputs.PACKAGE_VERSION }}" | ||
| TAG_VERSION="${{ steps.tag-version.outputs.TAG_VERSION }}" | ||
| if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then | ||
| echo "? CRITICAL: VERSION MISMATCH DETECTED!" | ||
| echo "::error::Git tag version does not match package version!" | ||
| echo "::error::Tag version: v$TAG_VERSION" | ||
| echo "::error::Package version: $PACKAGE_VERSION" | ||
| echo "::error::" | ||
| echo "::error::To fix this:" | ||
| echo "::error::1. Delete the wrong tag: git tag -d v$TAG_VERSION" | ||
| echo "::error::2. Delete remote tag: git push --delete origin v$TAG_VERSION" | ||
| echo "::error::3. Update pyproject.toml with correct version" | ||
| echo "::error::4. Create correct tag: git tag -a v$PACKAGE_VERSION -m 'Release v$PACKAGE_VERSION'" | ||
| echo "::error::5. Push correct tag: git push origin v$PACKAGE_VERSION" | ||
| exit 1 | ||
| else | ||
| echo "? Versions match: v$TAG_VERSION" | ||
| fi | ||
| test: | ||
| name: Test on Python ${{ matrix.python-version }} | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Set up Python ${{ matrix.python-version }} | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: ${{ matrix.python-version }} | ||
| cache: 'pip' | ||
| - name: Install dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install -e .[dev] | ||
| - name: Run tests with pytest | ||
| run: | | ||
| pytest -v --cov=xmlassert --cov-report=xml | ||
| build: | ||
| name: Build package | ||
| runs-on: ubuntu-latest | ||
| needs: test # Only build if tests pass | ||
| if: startsWith(github.ref, 'refs/tags/v') | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: '3.8' | ||
| - name: Install build tools | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install build twine | ||
| - name: Build package | ||
| run: python -m build | ||
| - name: Verify package | ||
| run: twine check dist/* | ||
| - name: Inspect built packages (optional) | ||
| run: | | ||
| echo "Built packages:" | ||
| ls -la dist/ | ||
| echo "Wheel compatibility:" | ||
| for wheel in dist/*.whl; do | ||
| echo "$wheel:" | ||
| unzip -l "$wheel" | grep -E "(.py$|METADATA)" | head -5 | ||
| done | ||
| - name: Upload build artifacts (tags only) | ||
| if: startsWith(github.ref, 'refs/tags/v') | ||
| uses: actions/upload-artifact@v3 | ||
| with: | ||
| name: distribution-packages | ||
| path: dist/ | ||
| test-pypi: | ||
| name: Publish to TestPyPI | ||
| runs-on: ubuntu-latest | ||
| needs: [validate-version, build] | ||
| if: | | ||
| startsWith(github.ref, 'refs/tags/v') && | ||
| (contains(github.ref, 'alpha') || | ||
| contains(github.ref, 'beta') || | ||
| contains(github.ref, 'rc') || | ||
| github.ref == 'refs/tags/v0.0.0-test') # Custom condition for test releases | ||
| steps: | ||
| - name: Download build artifacts | ||
| uses: actions/download-artifact@v3 | ||
| with: | ||
| name: distribution-packages | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: '3.8' | ||
| - name: Install twine | ||
| run: pip install twine | ||
| - name: Publish to TestPyPI | ||
| env: | ||
| TWINE_USERNAME: __token__ | ||
| TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }} | ||
| run: twine upload --repository-url https://test.pypi.org/legacy/ dist/* | ||
| - name: Verify TestPyPI installation | ||
| run: | | ||
| python -m pip install --index-url https://test.pypi.org/simple/ \ | ||
| --extra-index-url https://pypi.org/simple/ \ | ||
| xmlassert==${{ needs.validate-version.outputs.tag_version }} | ||
| pypi: | ||
| name: Publish to PyPI | ||
| runs-on: ubuntu-latest | ||
| needs: [validate-version, build] | ||
| if: | | ||
| startsWith(github.ref, 'refs/tags/v') && | ||
| !contains(github.ref, 'alpha') && | ||
| !contains(github.ref, 'beta') && | ||
| !contains(github.ref, 'rc') && | ||
| github.ref != 'refs/tags/v0.0.0-test' | ||
| steps: | ||
| - name: Download build artifacts | ||
| uses: actions/download-artifact@v3 | ||
| with: | ||
| name: distribution-packages | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v4 | ||
| with: | ||
| python-version: '3.10' | ||
| - name: Install twine | ||
| run: pip install twine | ||
| - name: Publish to PyPI | ||
| env: | ||
| TWINE_USERNAME: __token__ | ||
| TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} | ||
| run: twine upload dist/* | ||
| - name: Verify PyPI installation | ||
| run: | | ||
| # Wait a moment for PyPI to update | ||
| sleep 30 | ||
| pip install \ | ||
| xmlassert==${{ needs.validate-version.outputs.tag_version }} | ||
| github-release: | ||
| name: Create GitHub Release | ||
| runs-on: ubuntu-latest | ||
| needs: [test-pypi, pypi] | ||
| if: always() && startsWith(github.ref, 'refs/tags/v') | ||
| steps: | ||
| - name: Download build artifacts | ||
| uses: actions/download-artifact@v3 | ||
| with: | ||
| name: distribution-packages | ||
| - name: Create GitHub Release | ||
| uses: softprops/action-gh-release@v1 | ||
| with: | ||
| files: | | ||
| dist/*.whl | ||
| dist/*.tar.gz | ||
| generate_release_notes: true | ||
| body: | | ||
| Automated release for ${{ github.ref_name }} | ||
| See CHANGELOG.md for details. | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||