Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a3400f1
Publish to PyPI via GitHub CI
EpicWink May 1, 2025
b7f3f7e
Don't cache pip in publish CI job
EpicWink May 3, 2025
759c36f
Improve language in noxfile comment
EpicWink May 3, 2025
70457e5
Use latest Python version available
EpicWink May 3, 2025
671d6ab
Switch PyPA action version comment to tag
EpicWink May 3, 2025
944e4ee
Split build out from release CI job
EpicWink May 3, 2025
cc9692b
Document approvals required for release
EpicWink May 4, 2025
d855d62
Link to version page in release deployment
EpicWink May 4, 2025
30cb9f2
Merge remote-tracking branch 'upstream/main' into publish-ci-workflow
EpicWink May 4, 2025
6d6ba8e
Separate install from build in release CI job
EpicWink May 8, 2025
ed64a23
Link to CI job approval documentation
EpicWink May 8, 2025
b2a9652
Add punctuation to release process documentation
EpicWink May 8, 2025
94b6576
Check built distribution during release
EpicWink May 8, 2025
a0fc13e
Run twine check in strict mode during release
EpicWink May 8, 2025
f250545
Run twine-check in linting CI workflow
EpicWink May 9, 2025
9edb7a5
Remove redundant Python-setup step in release-build CI job
EpicWink May 9, 2025
ef36fbd
Switch to 'git switch' for switching branches
EpicWink Jul 29, 2025
c43d566
Merge branch 'main' into publish-ci-workflow
EpicWink Jul 29, 2025
5f36418
Switch to release 'published' event for CI trigger
EpicWink Jul 29, 2025
75cee2c
Revert "Run twine-check in linting CI workflow"
EpicWink Aug 6, 2025
2bc8119
Merge remote-tracking branch 'upstream/main' into publish-ci-workflow
EpicWink Aug 6, 2025
d81fd82
Name checkout step
EpicWink Aug 7, 2025
100ed2f
Document install-only detection
EpicWink Aug 7, 2025
2eae318
Merge remote-tracking branch 'upstream/main' into publish-ci-workflow
EpicWink Sep 15, 2025
f5494b8
Use 'pypa/gh-action-pypi-publish' GitHub action v1.13
EpicWink Sep 15, 2025
7b7127e
Make publish job require build job
EpicWink Nov 19, 2025
b6b7da6
Merge remote-tracking branch 'upstream/main' into publish-ci-workflow
EpicWink Nov 20, 2025
2c405b9
Format and add type annotations
EpicWink Nov 20, 2025
1ebc7e5
Merge remote-tracking branch 'upstream/main' into publish-ci-workflow
EpicWink Dec 3, 2025
861784f
Switch to manual workflow run
EpicWink Dec 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Publish

on:
release:
types: [created]

env:
FORCE_COLOR: 1

jobs:
publish:
environment:
name: pypi
url: https://pypi.org/p/packaging
permissions:
id-token: write

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
name: Install Python
with:
python-version: "3.12"
cache: "pip"
allow-prereleases: false

- name: Build distribution via nox
run: pipx run nox --error-on-missing-interpreters -s release_build

- name: Publish distribution to PyPI
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # release/v1
with:
print-hash: true
4 changes: 3 additions & 1 deletion docs/development/release-process.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ Release Process

$ nox -s release -- YY.N

You will need the password for your GPG key as well as an API token for PyPI.
This creates and pushes a new tag for the release

#. Add a `release on GitHub <https://github.com/pypa/packaging/releases>`__.

This triggers a CI workflow which builds and publishes the package to PyPI

#. Notify the other project owners of the release.

.. note::
Expand Down
64 changes: 46 additions & 18 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import tempfile
import textwrap
import time
import webbrowser
from pathlib import Path

import nox
Expand Down Expand Up @@ -141,8 +140,48 @@ def release(session):
next_version = f"{major}.{minor + 1}.dev0"
_bump(session, version=next_version, file=version_file, kind="development")

# Checkout the git tag.
session.run("git", "checkout", "-q", release_version, external=True)
# Push the commits and tag.
# NOTE: The following fails if pushing to the branch is not allowed. This can
# happen on GitHub, if the main branch is protected, there are required
# CI checks and "Include administrators" is enabled on the protection.
session.run("git", "push", "upstream", "main", release_version, external=True)


@nox.session
def release_build(session):
package_name = "packaging"

# Parse version from command-line arguments, if provided, otherwise get
# from Git tag.
try:
release_version = _get_version_from_arguments(session.posargs)
except ValueError as e:
if session.posargs:
session.error(f"Invalid arguments: {e}")

release_version = session.run(
"git", "describe", "--exact-match", silent=True, external=True
)
release_version = release_version.strip()
session.debug(f"version: {release_version}")
checkout = False
else:
checkout = True

# Check state of working directory.
_check_working_directory_state(session)

# Ensure there are no uncommitted changes.
result = subprocess.run(
["git", "status", "--porcelain"], capture_output=True, encoding="utf-8"
)
if result.stdout:
print(result.stdout, end="", file=sys.stderr)
session.error("The working tree has uncommitted changes")

# Checkout the git tag, if provided.
if checkout:
session.run("git", "checkout", "-q", release_version, external=True)

session.install("build", "twine")

Expand All @@ -162,24 +201,13 @@ def release(session):
diff = "\n".join(diff_generator)
session.error(f"Got the wrong files:\n{diff}")

# Get back out into main.
session.run("git", "checkout", "-q", "main", external=True)
# Get back out into main, if we checked out before.
if checkout:
session.run("git", "checkout", "-q", "main", external=True)

# Check and upload distribution files.
# Check distribution files.
session.run("twine", "check", *files)

# Push the commits and tag.
# NOTE: The following fails if pushing to the branch is not allowed. This can
# happen on GitHub, if the main branch is protected, there are required
# CI checks and "Include administrators" is enabled on the protection.
session.run("git", "push", "upstream", "main", release_version, external=True)

# Upload the distribution.
session.run("twine", "upload", *files)

# Open up the GitHub release page.
webbrowser.open("https://github.com/pypa/packaging/releases")


@nox.session
def update_licenses(session: nox.Session) -> None:
Expand Down