automate publishing: release github + release pypi

This commit is contained in:
ykcheungab
2026-09-12 16:50:55 +08:00
parent 388f34ca85
commit 174bceabc4
10 changed files with 1395 additions and 55 deletions
+99 -3
View File
@@ -1,4 +1,9 @@
"""Command line for ``python build/run.py release``."""
"""Command line for ``python build/run.py release``.
Commands: ``preflight`` (local gate), ``audit`` (single wheel), ``github`` (sync
the public repo + publish a GitHub Release), ``pypi`` (TestPyPI then PyPI).
The publish commands are dry-run unless ``--apply`` is passed.
"""
from __future__ import annotations
@@ -19,6 +24,7 @@ from common.verify.wheel import ( # noqa: E402
verify_wheel_runtime,
)
from common.verify.wheel_contents import inspect_wheel # noqa: E402
from release import github, pypi # noqa: E402
from release.preflight import PreflightOptions, run_preflight # noqa: E402
@@ -170,11 +176,97 @@ def _cmd_audit(argv: list[str]) -> int:
return exit_code
def _cmd_github(argv: list[str]) -> int:
parser = argparse.ArgumentParser(
prog="build/run.py release github",
description="Sync orisys-sdk-release, tag, and publish a GitHub Release.",
)
parser.add_argument("--version", required=True, help="release version, e.g. 0.5.2")
parser.add_argument(
"--apply",
action="store_true",
help="actually mutate the release repo, push, and create the release",
)
parser.add_argument("--notes-file", type=Path, default=None, help="release notes markdown")
parser.add_argument(
"--attach-preflight",
action="store_true",
help="also upload the preflight report as a release asset (contains local paths)",
)
parser.add_argument(
"--allow-dirty-release",
action="store_true",
help="proceed even if the release repo has uncommitted changes",
)
parser.add_argument("--skip-fetch", action="store_true", help="skip `git fetch --tags`")
parser.add_argument(
"--skip-checks", action="store_true", help="skip the manifest's downstream checks"
)
parser.add_argument(
"--skip-release-upload",
action="store_true",
help="stop after pushing the tag and print the `gh release create` command",
)
args = parser.parse_args(argv)
return github.publish(
github.Options(
version=args.version,
apply=args.apply,
notes_file=args.notes_file,
attach_preflight=args.attach_preflight,
allow_dirty_release=args.allow_dirty_release,
skip_fetch=args.skip_fetch,
skip_checks=args.skip_checks,
skip_release_upload=args.skip_release_upload,
)
)
def _cmd_pypi(argv: list[str]) -> int:
parser = argparse.ArgumentParser(
prog="build/run.py release pypi",
description="Upload the certified wheels to TestPyPI and then PyPI.",
)
parser.add_argument("--version", required=True, help="release version, e.g. 0.5.2")
parser.add_argument(
"--apply",
action="store_true",
help="actually upload (uploads are permanent and cannot be overwritten)",
)
parser.add_argument(
"--confirm-pypi",
action="store_true",
help="after TestPyPI, also publish to the real PyPI",
)
parser.add_argument(
"--repository", default="testpypi", help="twine repository for the first phase"
)
parser.add_argument(
"--skip-install-verify",
action="store_true",
help="skip fetching the artifact back out of the index",
)
parser.add_argument("--skip-check", action="store_true", help="skip `twine check`")
args = parser.parse_args(argv)
return pypi.publish(
pypi.Options(
version=args.version,
apply=args.apply,
confirm_pypi=args.confirm_pypi,
repository=args.repository,
verify_install=not args.skip_install_verify,
skip_check=args.skip_check,
)
)
def main(argv: list[str] | None = None) -> int:
argv = list(sys.argv[1:] if argv is None else argv)
if not argv or argv[0] in ("-h", "--help"):
print(__doc__)
print("Commands: preflight | audit")
print("Commands: preflight | audit | github | pypi")
return 0
command, rest = argv[0], argv[1:]
@@ -182,9 +274,13 @@ def main(argv: list[str] | None = None) -> int:
return _cmd_preflight(rest)
if command == "audit":
return _cmd_audit(rest)
if command == "github":
return _cmd_github(rest)
if command == "pypi":
return _cmd_pypi(rest)
print(f"Unknown release command: {command!r}", file=sys.stderr)
print("Choose from: preflight, audit", file=sys.stderr)
print("Choose from: preflight, audit, github, pypi", file=sys.stderr)
return 2