Add Gitea CI and automatic dev deployment
Main CI / check-and-build (push) Successful in 1m18s
Development CI / check-and-build (push) Successful in 34s
GitHub Git mirror / mirror (push) Successful in 7s
Development CI / deploy-development (push) Successful in 25s

This commit is contained in:
root committed 2026-10-29 21:30:28 +08:00
1 parent 543564a29c
commit b4f29d4966
20 files changed
+1109 -29

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env python3
"""Reconcile all business Git references from Gitea to GitHub under one lock."""
import argparse
import os
from pathlib import Path
import shlex
import tempfile
import time
from ci import SOURCE, locked, request_json, require, run, save
TARGET = '[email protected]:eezd/AlphaPulse.git'
DIRECTORY = Path('/docker/gitea/mirrors/AlphaPulse')
def refs(repository, remote=None, env=None):
args = ['ls-remote', remote, 'refs/heads/*', 'refs/tags/*'] if remote else [
'for-each-ref', '--format=%(objectname)\t%(refname)', 'refs/heads/', 'refs/tags/']
output = run('git', '-C', repository, *args, env=env)
return {ref: sha for line in output.splitlines() for sha, ref in [line.split()] if not ref.endswith('^{}')}
def synchronize(directory, source, target, env=None):
directory = Path(directory)
with locked(directory / '.mirror.lock'):
repository = directory / 'repository.git'
if not repository.exists():
run('git', 'init', '--bare', repository)
for _ in range(3):
run('git', '-C', repository, 'fetch', '--prune', '--no-tags', source,
'+refs/heads/*:refs/heads/*', '+refs/tags/*:refs/tags/*', env=env)
snapshot = refs(repository)
require('refs/heads/main' in snapshot, 'Source main is missing; refusing destructive synchronization')
if run('git', '-C', repository, 'log', '--all', '--format=', '--name-only', '--', '.gitattributes', '**/.gitattributes'):
run('git', '-C', repository, 'lfs', 'fetch', '--all', source, env=env)
run('git', '-C', repository, 'lfs', 'push', '--all', target, env=env)
run('git', '-C', repository, 'push', '--atomic', '--prune', target,
'+refs/heads/*:refs/heads/*', '+refs/tags/*:refs/tags/*', env=env)
require(refs(repository, target, env) == snapshot, 'GitHub references differ from the selected source snapshot')
if refs(repository, source, env) == snapshot:
save(directory / 'last-sync.json', {'refs': snapshot, 'verified_at': time.time()})
return
raise RuntimeError('Source kept changing; retry the mirror')
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.parse_args()
# A write-enabled deploy key limits GitHub access to this repository.
with tempfile.TemporaryDirectory(prefix='ap-mirror-auth-') as temporary:
key = Path(temporary) / 'key'
key.write_text(os.environ['ALPHAPULSE_GITHUB_SSH_KEY'])
key.chmod(0o600)
hosts = Path(temporary) / 'known_hosts'
hosts.write_text(''.join('github.com ' + entry + '\n' for entry in request_json('https://api.github.com/meta')['ssh_keys']))
command = ['ssh', '-i', str(key), '-o', 'IdentitiesOnly=yes', '-o', 'StrictHostKeyChecking=yes',
'-o', 'UserKnownHostsFile=' + str(hosts)]
env = {**os.environ, 'GIT_SSH_COMMAND': shlex.join(command), 'GIT_TERMINAL_PROMPT': '0'}
synchronize(DIRECTORY, SOURCE, TARGET, env)
print('GitHub business references and history verified')
if __name__ == '__main__':
main()