recipe-maintainer: public snapshot (secrets + deployment plans removed, single commit)
Sanitized single-commit public mirror of recipe-maintainer. - Removed test-ssh/.testenv (live creds); added test-ssh/.testenv.example placeholders. - Removed plans/ and planned-updates/ (deployment-planning docs) so no client/ deployment domains appear in the public repo. - All other secret stores were already gitignored. - docs.coopcloud.tech retained as a submodule (public upstream).
This commit is contained in:
161
recipe-info/gitea/tests/git_push.py
Normal file
161
recipe-info/gitea/tests/git_push.py
Normal file
@ -0,0 +1,161 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user