From f87196b0d06d581cabac2465a5638552c9dc2b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kami=C5=84ski?= Date: Wed, 21 Oct 2026 12:35:49 +0000 Subject: [PATCH 1/2] feat(ci): add workflow for publishing packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduced a new `release.yml` workflow to handle the publishing of core distributions to PyPI and TestPyPI. - Updated `packaging.yml` to support calls from the new release workflow and adjusted Python version to 3.14. Signed-off-by: Patryk Kamiński --- .github/workflows/packaging.yml | 15 ++++- .github/workflows/release.yml | 114 ++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml index 4ca1e40..1554052 100644 --- a/.github/workflows/packaging.yml +++ b/.github/workflows/packaging.yml @@ -5,8 +5,12 @@ name: Packaging # identical to the canonical copies at the repository root. # Build backends stay silent when those files go missing, so the artifacts are # inspected explicitly. +# +# Also called by release.yml, which publishes the core distributions from the +# uploaded "dist" artifact. on: + workflow_call: workflow_dispatch: push: branches: [main] @@ -19,6 +23,7 @@ on: - "examples/*/third-party-programs.txt" - ".github/scripts/check_dist_licenses.py" - ".github/workflows/packaging.yml" + - ".github/workflows/release.yml" pull_request: paths: *packaging-paths @@ -42,11 +47,12 @@ jobs: with: # The core package version is derived from the git history. fetch-depth: 0 + persist-credentials: false - name: Set up Python uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: - python-version: "3.x" + python-version: "3.14" - name: Set up uv uses: astral-sh/setup-uv@557e51de59eb14aaaba2ed9621916900a91d50c6 # v6.6.1 @@ -73,3 +79,10 @@ jobs: - name: Verify license files in all distributions run: python3 .github/scripts/check_dist_licenses.py dist/core/* dist/examples/*.whl + + - name: Upload core distributions + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: dist + path: dist/core/ + if-no-files-found: error diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..0ad99d1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,114 @@ +name: Release + +# Publishes the torch-tweak core distributions to PyPI and TestPyPI. +# +# Only release tags are allowed, e.g. v0.5.0 or v0.5.0rc1. +# +on: + workflow_dispatch: + inputs: + target: + description: Package index to publish to + type: choice + options: + - testpypi + - pypi + default: testpypi + +# Never cancel a release midway: a partial upload cannot be redone with the +# same version. +concurrency: + group: release + cancel-in-progress: false + +permissions: + contents: read + +jobs: + validate-tag: + name: Validate release tag + runs-on: ubuntu-latest + + steps: + - name: Require a tagged commit + env: + REF_TYPE: ${{ github.ref_type }} + REF_NAME: ${{ github.ref_name }} + run: | + if [ "${REF_TYPE}" != "tag" ]; then + echo "::error::Run this workflow on a release tag." + exit 1 + fi + if ! printf '%s' "${REF_NAME}" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+(rc[0-9]+)?$'; then + echo "::error::Tag '${REF_NAME}' does not match vX.Y.Z or vX.Y.ZrcN." + exit 1 + fi + + - name: Checkout Torch Tweak repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Require the tagged commit to be on main + env: + REF_NAME: ${{ github.ref_name }} + run: | + if ! git merge-base --is-ancestor "${GITHUB_SHA}" origin/main; then + echo "::error::Tag '${REF_NAME}' points to ${GITHUB_SHA}, which is not on main." + exit 1 + fi + + # TODO: packaging.yml also builds the example wheels, which are never + # published, so a broken example blocks the release. + build: + name: Build + needs: validate-tag + uses: $/.github/workflows/packaging.yml + + publish: + name: Publish to ${{ inputs.target }} + needs: build + runs-on: ubuntu-latest + environment: + name: ${{ inputs.target }} + url: >- + ${{ inputs.target == 'pypi' + && format('https://pypi.org/project/torch-tweak/{0}/', steps.version.outputs.version) + || format('https://test.pypi.org/project/torch-tweak/{0}/', steps.version.outputs.version) }} + permissions: + id-token: write # PyPI trusted publishing (OIDC) and attestation signing + + steps: + - name: Download distributions + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: dist + path: dist/core/ + + - name: Require the built version to match the tag + id: version + env: + REF_NAME: ${{ github.ref_name }} + run: | + version="${REF_NAME#v}" + expected="$(printf '%s\n' \ + "torch_tweak-${version}-py3-none-any.whl" \ + "torch_tweak-${version}.tar.gz" | sort)" + actual="$(ls dist/core | sort)" + if [ "${actual}" != "${expected}" ]; then + echo "::error::dist/core does not match version ${version}." + printf 'Expected:\n%s\nActual:\n%s\n' "${expected}" "${actual}" + exit 1 + fi + echo "version=${version}" >> "${GITHUB_OUTPUT}" + + - name: Publish to ${{ inputs.target }} + uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3 + with: + attestations: true + packages-dir: dist/core/ + repository-url: >- + ${{ inputs.target == 'pypi' + && 'https://upload.pypi.org/legacy/' + || 'https://test.pypi.org/legacy/' }} From 897d0af526ebb2c3f461caf307893be1cc9366a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kami=C5=84ski?= Date: Fri, 23 Oct 2026 17:22:23 +0000 Subject: [PATCH 2/2] chore(ci): improve workflow comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patryk Kamiński --- .github/workflows/packaging.yml | 1 + .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml index 1554052..4c681f6 100644 --- a/.github/workflows/packaging.yml +++ b/.github/workflows/packaging.yml @@ -52,6 +52,7 @@ jobs: - name: Set up Python uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: + # Keeping this pinned, so we have stable release environment python-version: "3.14" - name: Set up uv diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ad99d1..94ce927 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,7 +59,7 @@ jobs: exit 1 fi - # TODO: packaging.yml also builds the example wheels, which are never + # Note: packaging.yml also builds the example wheels, which are never # published, so a broken example blocks the release. build: name: Build