#!/usr/bin/env python3 """ Helper script for the release workflow (.github/workflows/release.yml). Subcommands: build-payload [--github] Build the JSON payload for creating a release. Reads TAG, GH_SHA from env. With --github, includes generate_release_notes=True. Writes JSON to stdout. extract-id < response.json Print the release id from a release API response. extract-upload-url < response.json Print the upload_url from a GitHub release response (used as the asset upload endpoint template). This script exists to avoid bash heredoc-inside-YAML-literal indentation traps. """ import json import os import sys def build_payload(github: bool) -> int: tag = os.environ.get("TAG", "") sha = os.environ.get("GH_SHA", "unknown") payload = { "tag_name": tag, "name": tag, "body": ( "Automated release.\n\n" f"Built from commit {sha}.\n\n" "See the workflow run for the artifact." ), "draft": False, "prerelease": False, } if github: payload["generate_release_notes"] = True print(json.dumps(payload)) return 0 def extract_field(field: str) -> int: raw = sys.stdin.read() try: data = json.loads(raw) except json.JSONDecodeError as e: print(f"::error::Failed to parse JSON response: {e}", file=sys.stderr) return 1 value = data.get(field, "") if not value: print(f"::error::Field {field!r} missing from response: {raw}", file=sys.stderr) return 1 print(value) return 0 def usage() -> int: print(__doc__, file=sys.stderr) return 2 def main() -> int: if len(sys.argv) < 2: return usage() cmd = sys.argv[1] if cmd == "build-payload": return build_payload(github="--github" in sys.argv) if cmd == "extract-id": return extract_field("id") if cmd == "extract-upload-url": return extract_field("upload_url") if cmd == "extract-tag": return extract_field("tag_name") return usage() if __name__ == "__main__": sys.exit(main())