The release workflow was already right; what it would have uploaded was not. `fluksio` had no readme, so its PyPI page would have been blank — the app repo's own README is a contributor's map of `frontend/` and `docker/`, which is the wrong front page for `pip install fluksio`. It now has one of its own, aimed at somebody who landed on the project page. Both distributions gain authors, urls, keywords and classifiers; `twine check` passes clean on all four artifacts where it warned on two before. The workflow publishes `fluksio-worker` first, because `fluksio` depends on it and the other order leaves a few seconds — the whole of a first release — in which the dependency cannot be resolved. `--check-url` makes a re-run skip what is already uploaded rather than failing on it, which matters because a version on PyPI can never be replaced. Licence metadata is deliberately still absent: LICENSE is MIT in somebody else's name, inherited from the template this was scaffolded from, and whose it should be is not a decision to make in a commit. NOTEPAD carries it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ue1tkFWB1bcGy3aWhCKpU
57 lines
2.1 KiB
YAML
57 lines
2.1 KiB
YAML
# Publish both distributions to PyPI on a version tag.
|
|
#
|
|
# Tags are the trigger rather than pushes to main: a release is a decision, and
|
|
# a version already on PyPI cannot be replaced.
|
|
name: Publish
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- "v*"
|
|
|
|
jobs:
|
|
publish:
|
|
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: Set up uv
|
|
uses: astral-sh/setup-uv@v7
|
|
- name: The tag is what the packages say they are
|
|
# Publishing 0.2.0 from a v0.3.0 tag is the kind of thing nobody
|
|
# notices until an install pulls the wrong one.
|
|
run: |
|
|
version="${GITHUB_REF_NAME#v}"
|
|
for project in backend worker; do
|
|
declared=$(uv version --short --directory "$project")
|
|
[ "$declared" = "$version" ] || {
|
|
echo "$project declares $declared, tag says $version" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
- run: uv build --all-packages --out-dir dist
|
|
- name: Both wheels install and run
|
|
run: |
|
|
uv run --no-project --with dist/fluksio_worker-*.whl fluksio-worker --help
|
|
uv run --no-project --with dist/fluksio-*.whl --with dist/fluksio_worker-*.whl \
|
|
fluksio --version
|
|
- name: Publish
|
|
env:
|
|
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
|
# The worker first: `fluksio` depends on it, and for the seconds
|
|
# between two uploads the other order leaves a dependency that cannot
|
|
# be resolved — which on a first release is the whole of the window in
|
|
# which the package exists at all.
|
|
#
|
|
# `--check-url` makes a re-run skip what is already up there rather
|
|
# than failing on it, so a job that died between the two uploads can
|
|
# simply be run again. A version on PyPI can never be replaced, and
|
|
# this is the difference between retrying and burning a version.
|
|
run: |
|
|
uv publish --check-url https://pypi.org/simple/ dist/fluksio_worker-*
|
|
uv publish --check-url https://pypi.org/simple/ dist/fluksio-0*
|