#!/usr/bin/env python3 import os import sys from typing import Optional try: import requests except ModuleNotFoundError: print("ERROR: Python 'requests' package is required. Please install it (e.g., pip install requests).") sys.exit(1) gitea_api_url = "https://gitea.psi.ch/api/v1/" repo_owner = "mx" repo_name = "jungfraujoch" gitea_token = os.getenv('GITEA_TOKEN') if gitea_token is None: print("ERROR: Required environment variables not set") sys.exit(1) def read_version(): try: with open('VERSION', 'r') as f: return f.readline().strip() except FileNotFoundError: print("ERROR: VERSION file not found") sys.exit(1) def create_release(version): headers = { 'Authorization': f'token {gitea_token}', 'Content-Type': 'application/json', } data = { 'tag_name': version, 'name': f'Release {version}', 'draft': False, 'prerelease': '-rc.' in version or '-alpha.' in version or '-beta.' in version } url = f'{gitea_api_url}/repos/{repo_owner}/{repo_name}/releases' response = requests.post(url, headers=headers, json=data) if response.status_code != 201: print(f"ERROR: Failed to create release. Status code: {response.status_code}") print(response.text) sys.exit(1) release = response.json() print(f"Successfully created release {version}") return release def get_release_by_tag(version: str): """ Fetch release information by tag name. Returns the release object (dict) or exits on error. """ headers = { 'Authorization': f'token {gitea_token}', 'Content-Type': 'application/json', } url = f'{gitea_api_url}/repos/{repo_owner}/{repo_name}/releases/tags/{version}' resp = requests.get(url, headers=headers) if resp.status_code != 200: print(f"ERROR: Failed to fetch release {version}. Status code: {resp.status_code}") print(resp.text) sys.exit(1) return resp.json() def upload_file_to_release(version: str, file_path: str, name: Optional[str] = None, label: Optional[str] = None): """ Upload a file as an asset to the release identified by the given version tag. :param version: Tag name of the release (e.g., '1.2.3' or '1.2.3-rc.1') :param file_path: Local file path to upload :param name: Optional asset name to display in release (defaults to filename) :param label: Optional asset label (display name) """ if not os.path.isfile(file_path): print(f"ERROR: File not found: {file_path}") sys.exit(1) asset_name = name if name else os.path.basename(file_path) print(f"Uploading file '{file_path}' to release {version} as {asset_name}") # Ensure the release exists and get its ID release = get_release_by_tag(version) release_id = release.get('id') if release_id is None: print("ERROR: Release ID not found in response") sys.exit(1) headers = { 'Authorization': f'token {gitea_token}', } data = {'name': asset_name} if label: data['label'] = label url = f'{gitea_api_url}/repos/{repo_owner}/{repo_name}/releases/{release_id}/assets' with open(file_path, 'rb') as f: files = { 'attachment': (asset_name, f, 'application/octet-stream'), } resp = requests.post(url, headers=headers, data=data, files=files) if resp.status_code not in (201, 200): print(f"ERROR: Failed to upload asset. Status code: {resp.status_code}") print(resp.text) sys.exit(1) asset = resp.json() browser_download_url = asset.get('browser_download_url') or asset.get('browser_url') or asset.get('url') print(f"Uploaded asset '{asset_name}' to release {version}: {browser_download_url}") if __name__ == '__main__': version = read_version() if len(sys.argv) != 2: exit(1) upload_file_to_release(version, sys.argv[1])