112 lines
4.1 KiB
Python
112 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import urllib.error
|
|
import urllib.parse
|
|
import urllib.request
|
|
import zipfile
|
|
from pathlib import Path
|
|
|
|
|
|
def zip_resourcepack(resourcepack_root: Path, archive_path: Path) -> None:
|
|
archive_path.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
with zipfile.ZipFile(archive_path, mode="w", compression=zipfile.ZIP_DEFLATED) as archive:
|
|
for source_file in sorted(resourcepack_root.rglob("*")):
|
|
if source_file.is_dir():
|
|
continue
|
|
|
|
relative_path = source_file.relative_to(resourcepack_root).as_posix()
|
|
archive.write(source_file, relative_path)
|
|
|
|
|
|
def request_json(request: urllib.request.Request) -> dict[str, object]:
|
|
with urllib.request.urlopen(request) as response:
|
|
return json.load(response)
|
|
|
|
|
|
def create_release(api_base: str, repository: str, token: str, tag: str, name: str, body: str) -> dict[str, object]:
|
|
payload = json.dumps(
|
|
{
|
|
"tag_name": tag,
|
|
"name": name,
|
|
"body": body,
|
|
"draft": False,
|
|
"prerelease": False,
|
|
}
|
|
).encode("utf-8")
|
|
|
|
request = urllib.request.Request(
|
|
f"{api_base}/repos/{repository}/releases",
|
|
data=payload,
|
|
method="POST",
|
|
headers={
|
|
"Authorization": f"token {token}",
|
|
"Content-Type": "application/json",
|
|
"Accept": "application/json",
|
|
},
|
|
)
|
|
return request_json(request)
|
|
|
|
|
|
def upload_asset(api_base: str, repository: str, token: str, release_id: int, archive_path: Path, asset_name: str) -> dict[str, object]:
|
|
with archive_path.open("rb") as handle:
|
|
payload = handle.read()
|
|
|
|
query = urllib.parse.urlencode({"name": asset_name})
|
|
request = urllib.request.Request(
|
|
f"{api_base}/repos/{repository}/releases/{release_id}/assets?{query}",
|
|
data=payload,
|
|
method="POST",
|
|
headers={
|
|
"Authorization": f"token {token}",
|
|
"Content-Type": "application/zip",
|
|
"Accept": "application/json",
|
|
},
|
|
)
|
|
return request_json(request)
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Package the resource pack and publish it as a Gitea release asset.")
|
|
parser.add_argument("--resourcepack-root", default="resourcepack", help="Path to the resource pack root")
|
|
parser.add_argument("--archive-path", default="build/resourcepack.zip", help="Path to the generated zip archive")
|
|
parser.add_argument("--tag", required=True, help="Release tag to publish")
|
|
parser.add_argument("--name", default=None, help="Release name to publish")
|
|
parser.add_argument("--body", default=None, help="Release notes/body text")
|
|
args = parser.parse_args()
|
|
|
|
token = os.environ.get("RELEASE_TOKEN") or os.environ.get("GITEA_TOKEN") or os.environ.get("GITHUB_TOKEN")
|
|
server_url = os.environ.get("GITEA_SERVER_URL") or os.environ.get("GITHUB_SERVER_URL")
|
|
repository = os.environ.get("GITEA_REPOSITORY") or os.environ.get("GITHUB_REPOSITORY")
|
|
|
|
if not token:
|
|
raise SystemExit("RELEASE_TOKEN is required")
|
|
if not server_url:
|
|
raise SystemExit("GITEA_SERVER_URL or GITHUB_SERVER_URL is required")
|
|
if not repository:
|
|
raise SystemExit("GITEA_REPOSITORY or GITHUB_REPOSITORY is required")
|
|
|
|
api_base = server_url.rstrip("/") + "/api/v1"
|
|
resourcepack_root = Path(args.resourcepack_root).resolve()
|
|
archive_path = Path(args.archive_path).resolve()
|
|
release_name = args.name or args.tag
|
|
release_body = args.body or f"Automated resource pack release for {args.tag}."
|
|
asset_name = f"resourcepack-{args.tag}.zip"
|
|
|
|
zip_resourcepack(resourcepack_root, archive_path)
|
|
release = create_release(api_base, repository, token, args.tag, release_name, release_body)
|
|
|
|
release_id = release.get("id")
|
|
if not isinstance(release_id, int):
|
|
raise SystemExit("Release creation did not return a numeric release id")
|
|
|
|
upload_asset(api_base, repository, token, release_id, archive_path, asset_name)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main()) |