#!/usr/bin/env python3 """Test creating a repo and pushing a commit via HTTPS on Gitea.""" import argparse import base64 import json import os import shutil import subprocess import sys import tempfile import time import urllib.error import urllib.request sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) from utils.tests.helpers import resolve_domain WORKSPACE = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) def load_testsecrets(domain): path = os.path.join(WORKSPACE, 'recipe-info', 'testsecrets', domain) if not os.path.exists(path): return {} secrets = {} with open(path) as f: for line in f: line = line.strip() if '=' in line: k, v = line.split('=', 1) secrets[k.strip()] = v.strip() return secrets def api(method, url, data=None, token=None, username=None, password=None): body = json.dumps(data).encode() if data is not None else None req = urllib.request.Request(url, data=body, method=method) req.add_header('Content-Type', 'application/json') if token: req.add_header('Authorization', f'token {token}') elif username and password: creds = base64.b64encode(f'{username}:{password}'.encode()).decode() req.add_header('Authorization', f'Basic {creds}') try: with urllib.request.urlopen(req, timeout=15) as resp: raw = resp.read() return resp.getcode(), json.loads(raw) if raw else {} except urllib.error.HTTPError as e: raw = e.read().decode(errors='replace') try: return e.code, json.loads(raw) except Exception: return e.code, {} def run_git(args, cwd, env=None): result = subprocess.run( ['git'] + args, cwd=cwd, capture_output=True, text=True, env={**os.environ, **(env or {})}, timeout=30, ) if result.returncode != 0: raise RuntimeError(f"git {' '.join(args)} failed:\n{result.stderr}") return result.stdout.strip() def main(): parser = argparse.ArgumentParser() parser.add_argument('--domain', default=os.environ.get('TEST_DOMAIN')) parser.add_argument('--username', default=os.environ.get('GITEA_ADMIN_USER')) parser.add_argument('--password', default=os.environ.get('GITEA_ADMIN_PASS')) args = parser.parse_args() domain = args.domain or resolve_domain('gitea') base_url = f'https://{domain}' # Load credentials from testsecrets if not provided via args/env username = args.username password = args.password if not username or not password: secrets = load_testsecrets(domain) username = username or secrets.get('admin_username') password = password or secrets.get('admin_password') if not username or not password: print(f'FAIL: No credentials found. Pass --username/--password or add ' f'admin_username/admin_password to recipe-info/testsecrets/{domain}') sys.exit(1) repo_name = f'test-push-{int(time.time())}' print(f'Testing git push on {base_url} as {username} ...') # 1. Create a test repo via API print(f' Creating repo {repo_name} ...') status, body = api('POST', f'{base_url}/api/v1/user/repos', data={'name': repo_name, 'private': False, 'auto_init': False}, username=username, password=password) if status != 201: print(f'FAIL: Could not create repo (HTTP {status}): {body}') sys.exit(1) clone_url = body.get('clone_url') or f'{base_url}/{username}/{repo_name}.git' print(f' Repo created: {clone_url}') tmpdir = tempfile.mkdtemp(prefix='gitea-test-') try: # 2. Clone (empty) and make a commit git_env = { 'GIT_AUTHOR_NAME': 'Test Bot', 'GIT_AUTHOR_EMAIL': 'test@example.com', 'GIT_COMMITTER_NAME': 'Test Bot', 'GIT_COMMITTER_EMAIL': 'test@example.com', # Embed credentials in the URL via a helper config 'GIT_CONFIG_COUNT': '1', 'GIT_CONFIG_KEY_0': f'url.https://{username}:{password}@{domain}/.insteadOf', 'GIT_CONFIG_VALUE_0': f'https://{domain}/', } print(' Cloning repo ...') run_git(['clone', clone_url, tmpdir], cwd='/tmp', env=git_env) # Write a test file test_file = os.path.join(tmpdir, 'README.md') with open(test_file, 'w') as f: f.write(f'# {repo_name}\n\nAutomated test commit.\n') run_git(['add', 'README.md'], cwd=tmpdir, env=git_env) run_git(['commit', '-m', 'test: automated push test'], cwd=tmpdir, env=git_env) # 3. Push print(' Pushing commit ...') run_git(['push', 'origin', 'HEAD:main'], cwd=tmpdir, env=git_env) print(' Push succeeded.') # 4. Verify via API — check the commit landed print(' Verifying commit via API ...') status, commits = api('GET', f'{base_url}/api/v1/repos/{username}/{repo_name}/commits?limit=1', username=username, password=password) if status != 200 or not commits: print(f'FAIL: Could not verify commit via API (HTTP {status}): {commits}') sys.exit(1) commit_msg = commits[0].get('commit', {}).get('message', '').strip() if 'automated push test' not in commit_msg: print(f'FAIL: Unexpected commit message: {commit_msg!r}') sys.exit(1) print(f' Commit verified: {commit_msg!r}') finally: shutil.rmtree(tmpdir, ignore_errors=True) # 5. Delete the test repo print(f' Deleting test repo {repo_name} ...') api('DELETE', f'{base_url}/api/v1/repos/{username}/{repo_name}', username=username, password=password) print('PASS: git push test completed successfully') if __name__ == '__main__': main()