Skip to content

Commit c637775

Browse files
authored
Publish to Test PyPI with every commit to main (#1042)
This modifies the `publish.yml` workflow to run with every commit to `main` branch. These commits will then lead to producing a Test PyPI release. That way, we will get to test out our publishing CI constantly, so that when we do want to push out a release, we don't need to be afraid that it might not work since the CI was modified and this is the first time it's running. Additionally, it will give our users the option to use these TestPyPI releases if they want a more up-to-date version of the library, without having to result to directly using git and building the package locally. This also gives users the benefit of having checkable attestations, proving that the build files were produced by our CI on the TestPyPI. Note 1: This modifies `uv-dynamic-versioning` to avoid including the commit sha as the local version component (e.g. instead of `0.6.0.post10.dev0+81baa11`, only produce `0.6.0.post10.dev0`). This is because PyPI [doesn't support](https://packaging.python.org/en/latest/specifications/version-specifiers/#version-specifiers) the use of local version components. Note 2: This drops support for the `workflow_call` trigger, if still we really want it, I should be able to integrate it with this, though I'm not sure how necessary it is. PS: See the Test PyPI installation instructions in [mcproto docs](https://py-mine.github.io/mcproto/latest/installation/#test-pypi-latest-main-commit-builds)
1 parent ca3e547 commit c637775

File tree

3 files changed

+75
-29
lines changed

3 files changed

+75
-29
lines changed

.github/workflows/publish.yml

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
name: Publish to PyPi
1+
---
2+
name: Publish to PyPI
23

34
on:
45
push:
56
tags:
67
# This pattern is not a typical regular expression, see:
78
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet
89
- "v*"
9-
workflow_dispatch:
10-
inputs:
11-
tag:
12-
description: Git Tag to use for the release
13-
required: true
14-
type: string
10+
branches:
11+
# Also run on every commit to main. This allows us to test the build & release pipeline and eventually leads to a
12+
# Test PyPI release. Unlike with a tag push, this will not release a full PyPI release, nor create a GitHub release.
13+
- main
1514

1615
permissions:
1716
contents: read
@@ -21,41 +20,56 @@ env:
2120

2221
jobs:
2322
build:
23+
name: "Build the project"
2424
runs-on: ubuntu-latest
2525

26-
steps:
27-
- name: Get Tag
28-
id: get_tag
29-
run: |
30-
if [[ "${{ github.event_name }}" == "push" ]]; then
31-
# For push events, the tag is in GITHUB_REF
32-
echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
33-
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
34-
# For workflow_dispatch, the tag is in the input
35-
echo "tag=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
36-
fi
26+
outputs:
27+
version: ${{ steps.check-version.outputs.version }}
28+
tagged_release: ${{ steps.check-version.outputs.tagged_release }}
3729

30+
steps:
3831
- name: Checkout repository
3932
uses: actions/checkout@v4
4033
with:
41-
# Checkout the specific tag
42-
ref: ${{ steps.get_tag.outputs.tag }}
34+
# Do a full clone for uv-dynamic-versioning to pick up the git version
35+
fetch-depth: 0
4336

4437
- name: Setup uv
4538
uses: astral-sh/setup-uv@v6
4639
with:
4740
version: "latest"
4841
python-version: ${{ env.PYTHON_VERSION }}
49-
enable-cache: true
50-
cache-suffix: "publish-ci"
5142
activate-environment: true
43+
enable-cache: true
44+
cache-suffix: "build"
5245

5346
- name: Install dependencies
5447
run: |
55-
uv sync --no-default-groups
48+
uv sync --no-default-groups --group release
5649
57-
- name: Build package
58-
run: uv build
50+
- name: Check version status
51+
id: check-version
52+
run: |
53+
version="$(hatchling version)"
54+
55+
echo "Project version: $version"
56+
echo "version=$version" >> "$GITHUB_OUTPUT"
57+
58+
# Determine whether we're doing a tagged release e.g. this workflow
59+
# was triggered by a git tag ref that matches the project's current
60+
# version, so a full PyPI release should be made, alongside all of
61+
# the other release steps. If this isn't the case, only a Test PyPI
62+
# release will be performed.
63+
if [[ "${GITHUB_REF}" == "refs/tags/v${version}" ]]; then
64+
echo "This is a new tagged release"
65+
echo "tagged_release=true" >> "$GITHUB_OUTPUT"
66+
else
67+
echo "This is an untagged dev release"
68+
echo "tagged_release=false" >> "$GITHUB_OUTPUT"
69+
fi
70+
71+
- name: Build project for distribution
72+
run: uv build --all-packages
5973

6074
- name: Upload build files
6175
uses: actions/upload-artifact@v4
@@ -65,22 +79,48 @@ jobs:
6579
if-no-files-found: error
6680
retention-days: 5
6781

82+
publish-test-pypi:
83+
name: "Publish to Test PyPI"
84+
# No if condition here, publish both tagged and untagged releases to Test PyPI.
85+
needs: build
86+
runs-on: ubuntu-latest
87+
environment: test-pypi # no approval
88+
permissions:
89+
# Used to authenticate to Test PyPI via OIDC.
90+
id-token: write
91+
92+
steps:
93+
- name: Download the distribution files from build artifact
94+
uses: actions/download-artifact@v5
95+
with:
96+
name: "dist"
97+
path: "dist/"
98+
99+
- name: Upload to Test PyPI
100+
uses: pypa/gh-action-pypi-publish@release/v1
101+
with:
102+
# the "legacy" in the URL doesn't mean it's deprecated
103+
repository-url: https://test.pypi.org/legacy/
104+
# Enable verbose mode for easy debugging
105+
verbose: true
106+
68107
publish-pypi:
69108
name: "Publish to PyPI"
109+
if: needs.build.outputs.tagged_release == 'true' # only publish to PyPI on tagged releases
70110
needs: build
71111
runs-on: ubuntu-latest
72-
environment: release
112+
environment: release # requires approval
73113
permissions:
74114
# Used to authenticate to PyPI via OIDC.
75115
id-token: write
76116

77117
steps:
78-
- name: Download the distribution files from PR artifact
118+
- name: Download the distribution files from build artifact
79119
uses: actions/download-artifact@v5
80120
with:
81121
name: "dist"
82122
path: "dist/"
83123

84124
# This uses PyPI's trusted publishing, so no token is required
85-
- name: Publish package distributions to PyPI
125+
- name: Release to PyPI
86126
uses: pypa/gh-action-pypi-publish@release/v1

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ docs = [
7070
"uv-dynamic-versioning", # actual version is in `release` group
7171
]
7272
release = [
73+
"hatchling>=1.27.0",
7374
"uv-dynamic-versioning>=0.8.2",
7475
]
7576

@@ -199,3 +200,4 @@ build-backend = "hatchling.build"
199200

200201
[tool.hatch.version]
201202
source = "uv-dynamic-versioning"
203+
metadata = false

uv.lock

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)