94 lines
2.6 KiB
Python
94 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Build package, optionally publish to PyPI, and create Gitea release.
|
|
|
|
Usage:
|
|
GITEA_TOKEN=<token> [PYPI_TOKEN=<token>] python3 scripts/publish.py <tag> <repo>
|
|
"""
|
|
import argparse
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
import requests
|
|
|
|
GITEA_API = "https://git.oblachno.oblachno.fyi/api/v1"
|
|
|
|
|
|
def build_package() -> None:
|
|
"""Build the Python package using python -m build."""
|
|
result = subprocess.run(
|
|
[sys.executable, "-m", "build"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
if result.returncode != 0:
|
|
print("ERROR: Package build failed.")
|
|
print(result.stderr)
|
|
sys.exit(1)
|
|
|
|
|
|
def publish_to_pypi(token: str) -> None:
|
|
"""Publish built packages to PyPI using twine."""
|
|
result = subprocess.run(
|
|
[
|
|
sys.executable, "-m", "twine", "upload", "dist/*",
|
|
"-u", "__token__", "-p", token,
|
|
],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
if result.returncode != 0:
|
|
print("ERROR: PyPI publish failed.")
|
|
print(result.stderr)
|
|
sys.exit(1)
|
|
print("Published to PyPI.")
|
|
|
|
|
|
def create_gitea_release(token: str, repo: str, tag: str) -> None:
|
|
"""Create a Gitea release for the given tag."""
|
|
url = f"{GITEA_API}/repos/{repo}/releases"
|
|
headers = {
|
|
"Authorization": f"token {token}",
|
|
"Content-Type": "application/json",
|
|
}
|
|
payload = {
|
|
"tag_name": tag,
|
|
"name": tag,
|
|
"body": f"Release {tag}\n\nSee CHANGELOG.md for details.",
|
|
"draft": False,
|
|
"prerelease": False,
|
|
}
|
|
response = requests.post(url, headers=headers, json=payload, timeout=30)
|
|
response.raise_for_status()
|
|
|
|
|
|
def main(args: list[str] | None = None) -> None: # pragma: no cover
|
|
argv = args if args is not None else sys.argv
|
|
parser = argparse.ArgumentParser(description="Build and publish release")
|
|
parser.add_argument("tag", help="Git tag (e.g. v1.0.0)")
|
|
parser.add_argument("repo", help="Repository full name (owner/repo)")
|
|
parsed = parser.parse_args(argv[1:])
|
|
|
|
gitea_token = os.environ.get("GITEA_TOKEN", "")
|
|
if not gitea_token:
|
|
print("ERROR: GITEA_TOKEN is not set.", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
pypi_token = os.environ.get("PYPI_TOKEN", "")
|
|
|
|
build_package()
|
|
|
|
if pypi_token:
|
|
publish_to_pypi(pypi_token)
|
|
else:
|
|
print("PYPI_TOKEN not set — skipping PyPI publish.")
|
|
|
|
create_gitea_release(gitea_token, parsed.repo, parsed.tag)
|
|
print(f"Gitea release {parsed.tag} created.")
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
main()
|