Files
LOGAR/upload_release.py
T
2026-09-03 22:02:08 +02:00

136 lines
5.4 KiB
Python

import os
import sys
import json
import argparse
import urllib.request
import urllib.parse
import mimetypes
import package_dist
DEFAULT_GITEA_URL = os.environ.get("GITEA_SERVER_URL", "https://gitea.eibl.tech")
DEFAULT_REPO = os.environ.get("GITEA_REPOSITORY", "me0nline/LOGAR")
def get_existing_assets(base_url, repo, release_id, token):
url = f"{base_url}/api/v1/repos/{repo}/releases/{release_id}/assets"
req = urllib.request.Request(url, headers={"Authorization": f"token {token}", "Accept": "application/json"})
try:
with urllib.request.urlopen(req) as resp:
return json.loads(resp.read().decode("utf-8"))
except Exception:
return []
def delete_asset(base_url, repo, release_id, asset_id, token):
url = f"{base_url}/api/v1/repos/{repo}/releases/{release_id}/assets/{asset_id}"
req = urllib.request.Request(url, method="DELETE", headers={"Authorization": f"token {token}"})
try:
with urllib.request.urlopen(req) as resp:
pass
except Exception:
pass
def upload_file_to_release(base_url, repo, release_id, token, file_path):
filename = os.path.basename(file_path)
# Clean up existing asset with same name if already present
existing_assets = get_existing_assets(base_url, repo, release_id, token)
for asset in existing_assets:
if asset.get("name") == filename:
print(f"[*] Removing existing asset '{filename}' (ID: {asset['id']})...")
delete_asset(base_url, repo, release_id, asset["id"], token)
url = f"{base_url}/api/v1/repos/{repo}/releases/{release_id}/assets?name={urllib.parse.quote(filename)}"
with open(file_path, "rb") as f:
file_bytes = f.read()
req = urllib.request.Request(url, data=file_bytes, method="POST")
req.add_header("Authorization", f"token {token}")
req.add_header("Content-Type", "application/octet-stream")
req.add_header("Accept", "application/json")
try:
with urllib.request.urlopen(req) as resp:
data = json.loads(resp.read().decode("utf-8"))
print(f"[+] Attached {filename} ({len(file_bytes)} bytes) to release.")
return data
except urllib.error.HTTPError as e:
err = e.read().decode("utf-8", errors="ignore")
print(f"[!] Error uploading {filename}: HTTP {e.code} - {err}")
return None
def create_or_get_release(base_url, repo, tag, token, title=None, notes=None):
url = f"{base_url}/api/v1/repos/{repo}/releases"
headers = {
"Authorization": f"token {token}",
"Content-Type": "application/json",
"Accept": "application/json"
}
# Check if release exists
check_url = f"{base_url}/api/v1/repos/{repo}/releases/tags/{urllib.parse.quote(tag)}"
check_req = urllib.request.Request(check_url, headers={"Authorization": f"token {token}"})
try:
with urllib.request.urlopen(check_req) as resp:
existing = json.loads(resp.read().decode("utf-8"))
print(f"[*] Found existing release for tag {tag} (ID: {existing['id']})")
return existing["id"]
except urllib.error.HTTPError:
pass
# Create new release
payload = {
"tag_name": tag,
"name": title or f"LOGAR Release {tag}",
"body": notes or f"Automated binary release for {tag}.",
"draft": False,
"prerelease": False
}
req = urllib.request.Request(url, data=json.dumps(payload).encode("utf-8"), headers=headers, method="POST")
with urllib.request.urlopen(req) as resp:
created = json.loads(resp.read().decode("utf-8"))
print(f"[+] Created release {tag} (ID: {created['id']})")
return created["id"]
def main():
parser = argparse.ArgumentParser(description="Upload LOGAR compiled binaries directly to Gitea Release")
parser.add_argument("--tag", default=os.environ.get("GITEA_REF_NAME"), help="Release tag name (e.g. v1.0.0)")
parser.add_argument("--token", default=os.environ.get("GITEA_TOKEN"), help="Gitea Personal Access Token (or set GITEA_TOKEN env var)")
parser.add_argument("--url", default=DEFAULT_GITEA_URL, help="Base Gitea instance URL")
parser.add_argument("--repo", default=DEFAULT_REPO, help="Repository owner/name")
parser.add_argument("--skip-build", action="store_true", help="Skip running package_dist.py before upload")
args = parser.parse_args()
tag = args.tag
if not tag:
tag = input("Enter tag name (e.g. v1.0.0): ").strip()
token = args.token
if not token:
token = input("Enter Gitea Token: ").strip()
if not tag or not token:
print("[!] Tag and Token are required.")
sys.exit(1)
if not args.skip_build:
print("[*] Assembling compiled binaries...")
package_dist.main()
dist_dir = os.path.abspath("dist")
if not os.path.exists(dist_dir) or not os.listdir(dist_dir):
print("[!] No binaries found in dist/. Run package_dist.py first.")
sys.exit(1)
print(f"[*] Connecting to Gitea: {args.url} (repo: {args.repo})...")
release_id = create_or_get_release(args.url, args.repo, tag, token)
print(f"[*] Uploading binary assets from '{dist_dir}'...")
for f in sorted(os.listdir(dist_dir)):
fpath = os.path.join(dist_dir, f)
if os.path.isfile(fpath):
upload_file_to_release(args.url, args.repo, release_id, token, fpath)
print(f"\n[+] Release successfully published with binary assets: {args.url}/{args.repo}/releases/tag/{tag}")
if __name__ == "__main__":
main()