GRM-20: feat: replace inline workflow scripts with tested Python modules

This commit is contained in:
Emil Simeonov
2026-06-19 15:34:36 +02:00
parent 3048d7ade7
commit 4d2ac8d449
9 changed files with 741 additions and 97 deletions
+93
View File
@@ -0,0 +1,93 @@
#!/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()