Skip to content

Bump Refiner to 0.3.1 (#202) #36

Bump Refiner to 0.3.1 (#202)

Bump Refiner to 0.3.1 (#202) #36

Workflow file for this run

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