77 lines
3.8 KiB
Python
77 lines
3.8 KiB
Python
"""Publish only the root-authorized exact-input reconstruction branch."""
|
|
import base64
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import tomllib
|
|
import urllib.request
|
|
from datetime import datetime, timezone
|
|
|
|
BASE = Path(__file__).resolve().parent
|
|
SOURCE = BASE / 'source'
|
|
BRANCH = 'codex/contextual-prerelease-source-20260911'
|
|
COMMIT = 'd5650309a93f3d590a41f8a8f0322c6500568f69'
|
|
RESULT = BASE / 'source-push-result.json'
|
|
assert not RESULT.exists()
|
|
package = json.loads((BASE / 'package2-result.json').read_text(encoding='utf-8-sig'))
|
|
assert package['success'] and package['source_commit'] == COMMIT
|
|
config = tomllib.loads((Path.home() / '.codex/config.toml').read_text(encoding='utf-8'))
|
|
token = config['mcp_servers']['gitea']['env']['GITEA_ACCESS_TOKEN']
|
|
request = urllib.request.Request('http://217.177.34.108:3000/api/v1/user',
|
|
headers={'Authorization': 'token ' + token})
|
|
with urllib.request.urlopen(request, timeout=30) as response:
|
|
username = json.load(response)['login']
|
|
credential = base64.b64encode((username + ':' + token).encode()).decode()
|
|
env = {k: v for k, v in os.environ.items()
|
|
if not k.startswith(('GIT_TRACE', 'GIT_CONFIG_', 'GIT_CURL_VERBOSE'))}
|
|
env.update({'GIT_TERMINAL_PROMPT': '0', 'GIT_CONFIG_COUNT': '3',
|
|
'GIT_CONFIG_KEY_0': 'credential.helper', 'GIT_CONFIG_VALUE_0': '',
|
|
'GIT_CONFIG_KEY_1': 'http.http://217.177.34.108:3000/.extraHeader',
|
|
'GIT_CONFIG_VALUE_1': 'Authorization: Basic ' + credential,
|
|
'GIT_CONFIG_KEY_2': 'http.followRedirects', 'GIT_CONFIG_VALUE_2': 'false'})
|
|
|
|
def redact(value):
|
|
return value.replace(token, '[redacted]').replace(credential, '[redacted]')
|
|
|
|
def git(*args, check=True):
|
|
result = subprocess.run(['git', *args], cwd=SOURCE, env=env,
|
|
capture_output=True, text=True, timeout=120)
|
|
if result.stderr:
|
|
print(redact(result.stderr).strip(), flush=True)
|
|
if check and result.returncode:
|
|
raise RuntimeError('Git operation failed with exit ' + str(result.returncode))
|
|
return result
|
|
|
|
status = {'started': datetime.now(timezone.utc).isoformat(), 'branch': BRANCH, 'commit': COMMIT}
|
|
try:
|
|
assert git('rev-parse', 'HEAD').stdout.strip() == COMMIT
|
|
assert git('branch', '--show-current').stdout.strip() == BRANCH
|
|
assert not git('status', '--porcelain').stdout.strip()
|
|
remote_url = git('remote', 'get-url', 'gitea').stdout.strip()
|
|
assert remote_url.rstrip('/') in (
|
|
'http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio.git',
|
|
'http://217.177.34.108:3000/sorokin.oleg.edu/ARCADIA-Studio')
|
|
before = git('ls-remote', 'gitea', 'refs/heads/' + BRANCH).stdout.strip()
|
|
status['remote_before'] = before.split()[0] if before else None
|
|
if before:
|
|
remote_commit = before.split()[0]
|
|
if git('cat-file', '-e', remote_commit + '^{commit}', check=False).returncode:
|
|
git('fetch', '--no-tags', '--no-write-fetch-head', 'gitea', 'refs/heads/' + BRANCH)
|
|
if git('merge-base', '--is-ancestor', remote_commit, COMMIT, check=False).returncode:
|
|
raise RuntimeError('Remote branch is not an ancestor; no push attempted.')
|
|
git('push', 'gitea', COMMIT + ':refs/heads/' + BRANCH)
|
|
after = git('ls-remote', 'gitea', 'refs/heads/' + BRANCH).stdout.strip()
|
|
assert after.split()[0] == COMMIT
|
|
status.update({'success': True, 'remote_after': after.split()[0], 'user': username,
|
|
'scope': 'Only exact source reconstruction branch; no force, tag, release or asset operation.'})
|
|
except BaseException as error:
|
|
status.update({'success': False, 'error': redact(str(error))})
|
|
raise
|
|
finally:
|
|
status['finished'] = datetime.now(timezone.utc).isoformat()
|
|
with RESULT.open('x', encoding='utf-8', newline='\n') as output:
|
|
json.dump(status, output, indent=2)
|
|
output.write('\n')
|
|
print(json.dumps(status), flush=True)
|