Repository navigation
Bump Refiner to 0.3.1 (#202) #36
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: Publish package | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - pyproject.toml | |
| workflow_dispatch: | |
| inputs: | |
| target: | |
| description: "Publishing target" | |
| required: true | |
| default: "testpypi" | |
| type: choice | |
| options: | |
| - testpypi | |
| - pypi | |
| permissions: | |
| contents: write | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.package_meta.outputs.version }} | |
| tag_name: ${{ steps.package_meta.outputs.tag_name }} | |
| should_run: ${{ steps.plan.outputs.should_run }} | |
| publish_testpypi: ${{ steps.plan.outputs.publish_testpypi }} | |
| publish_pypi: ${{ steps.plan.outputs.publish_pypi }} | |
| create_release: ${{ steps.plan.outputs.create_release }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Read package version | |
| id: package_meta | |
| run: | | |
| python - <<'PY' >> "$GITHUB_OUTPUT" | |
| import tomllib | |
| from pathlib import Path | |
| data = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8")) | |
| version = data["project"]["version"] | |
| print(f"version={version}") | |
| print(f"tag_name=v{version}") | |
| PY | |
| - name: Plan publish targets | |
| id: plan | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| DISPATCH_TARGET: ${{ github.event.inputs.target }} | |
| CURRENT_VERSION: ${{ steps.package_meta.outputs.version }} | |
| CURRENT_TAG: ${{ steps.package_meta.outputs.tag_name }} | |
| BEFORE_SHA: ${{ github.event.before }} | |
| GITHUB_REF: ${{ github.ref }} | |
| run: | | |
| should_run=false | |
| publish_testpypi=false | |
| publish_pypi=false | |
| create_release=false | |
| if [ "$EVENT_NAME" = "workflow_dispatch" ]; then | |
| target="${DISPATCH_TARGET:-testpypi}" | |
| if [ "$target" = "testpypi" ]; then | |
| should_run=true | |
| publish_testpypi=true | |
| elif [ "$target" = "pypi" ]; then | |
| if [ "$GITHUB_REF" != "refs/heads/main" ]; then | |
| echo "Manual PyPI publish is only allowed from main." >&2 | |
| exit 1 | |
| fi | |
| should_run=true | |
| publish_testpypi=true | |
| publish_pypi=true | |
| create_release=true | |
| else | |
| echo "Unknown dispatch target: $target" >&2 | |
| exit 1 | |
| fi | |
| else | |
| old_version="" | |
| if [ -n "$BEFORE_SHA" ] && [ "$BEFORE_SHA" != "0000000000000000000000000000000000000000" ]; then | |
| old_version="$(git show "$BEFORE_SHA:pyproject.toml" 2>/dev/null | sed -nE 's/^version = \"([^\"]+)\"$/\1/p' | head -n1 || true)" | |
| fi | |
| if [ "$old_version" != "$CURRENT_VERSION" ]; then | |
| should_run=true | |
| publish_testpypi=true | |
| publish_pypi=true | |
| create_release=true | |
| fi | |
| fi | |
| git fetch --tags --force | |
| if [ "$publish_pypi" = "true" ] && git rev-parse -q --verify "refs/tags/$CURRENT_TAG" >/dev/null; then | |
| echo "Tag $CURRENT_TAG already exists. Bump pyproject version before releasing." >&2 | |
| exit 1 | |
| fi | |
| { | |
| echo "should_run=$should_run" | |
| echo "publish_testpypi=$publish_testpypi" | |
| echo "publish_pypi=$publish_pypi" | |
| echo "create_release=$create_release" | |
| } >> "$GITHUB_OUTPUT" | |
| ci-gate: | |
| needs: prepare | |
| if: needs.prepare.outputs.should_run == 'true' | |
| uses: ./.github/workflows/ci.yml | |
| build: | |
| needs: | |
| - prepare | |
| - ci-gate | |
| if: needs.prepare.outputs.should_run == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.10" | |
| - name: Install build tools | |
| run: python -m pip install --upgrade build twine | |
| - name: Build distribution artifacts | |
| run: python -m build | |
| - name: Validate distribution metadata | |
| run: twine check dist/* | |
| - name: Ensure version did not change during workflow | |
| env: | |
| EXPECTED_VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| current_version="$(sed -nE 's/^version = \"([^\"]+)\"$/\1/p' pyproject.toml | head -n1)" | |
| if [ "$current_version" != "$EXPECTED_VERSION" ]; then | |
| echo "Version changed unexpectedly during workflow." >&2 | |
| exit 1 | |
| fi | |
| - name: Ensure release tag does not already exist | |
| if: needs.prepare.outputs.publish_pypi == 'true' | |
| env: | |
| TAG_NAME: ${{ needs.prepare.outputs.tag_name }} | |
| run: | | |
| git fetch --tags --force | |
| if git rev-parse -q --verify "refs/tags/${TAG_NAME}" >/dev/null; then | |
| echo "Tag ${TAG_NAME} already exists. Bump version before releasing." >&2 | |
| exit 1 | |
| fi | |
| - name: Upload distribution artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: python-dist | |
| path: dist/ | |
| if-no-files-found: error | |
| publish-testpypi: | |
| if: needs.prepare.outputs.publish_testpypi == 'true' | |
| needs: | |
| - prepare | |
| - build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write | |
| environment: | |
| name: testpypi | |
| url: https://test.pypi.org/p/macrodata-refiner | |
| steps: | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: python-dist | |
| path: dist/ | |
| - name: Publish to TestPyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| repository-url: https://test.pypi.org/legacy/ | |
| packages-dir: dist/ | |
| skip-existing: true | |
| verify-testpypi-install: | |
| if: needs.prepare.outputs.publish_testpypi == 'true' | |
| needs: | |
| - prepare | |
| - publish-testpypi | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.10" | |
| - name: Install from TestPyPI with retry | |
| env: | |
| PACKAGE_VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| python -m pip install --upgrade pip | |
| for attempt in $(seq 1 12); do | |
| if python -m pip install \ | |
| --index-url https://test.pypi.org/simple/ \ | |
| --extra-index-url https://pypi.org/simple \ | |
| "macrodata-refiner==${PACKAGE_VERSION}"; then | |
| echo "Installed macrodata-refiner==${PACKAGE_VERSION} from TestPyPI" | |
| exit 0 | |
| fi | |
| if [ "$attempt" -eq 12 ]; then | |
| echo "Package was not installable from TestPyPI after retries." >&2 | |
| exit 1 | |
| fi | |
| echo "Attempt ${attempt}/12 failed. Retrying in 10s..." | |
| sleep 10 | |
| done | |
| - name: Smoke test installed package | |
| run: | | |
| macrodata --help >/dev/null | |
| python - <<'PY' | |
| import refiner | |
| from refiner import from_items | |
| _ = from_items([{"ok": True}]) | |
| print("TestPyPI smoke checks passed") | |
| PY | |
| publish-pypi: | |
| if: needs.prepare.outputs.publish_pypi == 'true' | |
| needs: | |
| - prepare | |
| - build | |
| - publish-testpypi | |
| - verify-testpypi-install | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/macrodata-refiner | |
| steps: | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: python-dist | |
| path: dist/ | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| packages-dir: dist/ | |
| skip-existing: true | |
| tag-and-release: | |
| if: needs.prepare.outputs.create_release == 'true' | |
| needs: | |
| - prepare | |
| - publish-pypi | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Create and push release tag | |
| env: | |
| TAG_NAME: ${{ needs.prepare.outputs.tag_name }} | |
| run: | | |
| git fetch --tags --force | |
| if git rev-parse -q --verify "refs/tags/${TAG_NAME}" >/dev/null; then | |
| echo "Tag ${TAG_NAME} already exists." | |
| else | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git tag "${TAG_NAME}" "${GITHUB_SHA}" | |
| git push origin "${TAG_NAME}" | |
| fi | |
| - name: Create GitHub release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.prepare.outputs.tag_name }} | |
| name: ${{ needs.prepare.outputs.tag_name }} | |
| generate_release_notes: true |