docs: make ngit canonical and gate mirror publication

This commit is contained in:
archipelago
2026-10-05 11:47:12 -04:00
parent 833c939220
commit 138a541d01
4 changed files with 217 additions and 1 deletions
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""Read-only check of advertised Git refs; does not inspect PR metadata."""
import argparse
import re
import subprocess
import sys
def git(*args):
result = subprocess.run(['git', *args], capture_output=True, text=True,
timeout=120)
if result.returncode:
# Transport errors can contain credential-bearing remote URLs.
raise ValueError('Git lookup failed; check mirror access privately')
return result.stdout
def parse_refs(output):
return {ref: sha for sha, ref in (line.split() for line in output.splitlines())
if ref.startswith(('refs/heads/', 'refs/tags/'))}
def compare(left, right, refs):
failures = []
for ref in sorted(refs):
if ref not in left or ref not in right:
failures.append(f'{ref}: missing from at least one side')
elif left[ref] != right[ref]:
failures.append(f'{ref}: different object IDs')
return failures
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--remotes', nargs=2, default=['origin', 'ngit'])
parser.add_argument('--ref', action='append', default=[],
help='additional full branch/tag ref; main is always checked')
parser.add_argument('--all', action='store_true', help='audit all advertised branches/tags')
parser.add_argument('--local', action='store_true', help='also require local refs to match')
args = parser.parse_args()
try:
configured = set(git('remote').splitlines())
if any(remote not in configured for remote in args.remotes):
raise ValueError('Both arguments must name configured remotes')
refs = {'refs/heads/main', *args.ref}
for ref in refs:
if not re.match(r'^refs/(heads|tags)/', ref):
raise ValueError('Use full refs/heads/... or refs/tags/... names')
git('check-ref-format', ref)
left, right = [parse_refs(git('ls-remote', remote)) for remote in args.remotes]
if args.all:
refs.update(left)
refs.update(right)
# Compare both annotated tag objects and their peeled target commits.
refs.update(ref + '^{}' for ref in list(refs)
if ref + '^{}' in left or ref + '^{}' in right)
failures = compare(left, right, refs)
if args.local:
local = parse_refs(git('show-ref', '--dereference'))
failures += ['local: ' + error for error in compare(left, local, refs)]
if failures:
print('\n'.join(failures), file=sys.stderr)
return 1
print(f'PASS: {len(refs)} refs match on both mirrors'
+ (' and locally' if args.local else '')
+ '; PR metadata not checked.')
return 0
except (ValueError, subprocess.TimeoutExpired, OSError):
print('FAIL: unable to validate refs; check arguments and mirror access privately.',
file=sys.stderr)
return 1
if __name__ == '__main__':
sys.exit(main())
+73
View File
@@ -0,0 +1,73 @@
"""Exercise mirror gate against disposable local Git remotes."""
import pathlib
import subprocess
import sys
import tempfile
import unittest
CHECK = pathlib.Path(__file__).resolve().parents[1] / 'check-git-mirrors.py'
class MirrorTests(unittest.TestCase):
def test_publication_drift_and_annotated_tags(self):
with tempfile.TemporaryDirectory() as tmp:
root = pathlib.Path(tmp)
work = root / 'work'
work.mkdir()
def git(*args):
return subprocess.run(['git', *args], cwd=work, check=True,
capture_output=True, text=True).stdout
def check(*args, passes=True):
result = subprocess.run([sys.executable, str(CHECK), *args],
cwd=work, capture_output=True, text=True)
self.assertEqual(result.returncode, 0 if passes else 1,
result.stdout + result.stderr)
git('init', '-b', 'main')
git('config', 'user.name', 'Mirror test')
git('config', 'user.email', 'fixture@example.invalid')
git('config', 'commit.gpgsign', 'false')
git('config', 'tag.gpgsign', 'false')
for remote in ('origin', 'ngit'):
git('init', '--bare', str(root / remote))
git('remote', 'add', remote, str(root / remote))
git('commit', '--allow-empty', '-m', 'first')
check(passes=False) # Empty mirrors cannot pass.
git('push', 'origin', 'main')
check(passes=False) # Partial publication.
git('push', 'ngit', 'main')
check('--local')
git('commit', '--allow-empty', '-m', 'second')
check() # Remote equality alone does not imply local publication.
check('--local', passes=False)
git('push', 'origin', 'main')
check(passes=False)
git('push', 'ngit', 'main')
git('tag', '-a', 'v-test', '-m', 'original')
git('push', 'origin', 'refs/tags/v-test')
check('--ref', 'refs/tags/v-test', passes=False)
git('push', 'ngit', 'refs/tags/v-test')
check('--local', '--ref', 'refs/tags/v-test')
# Same commit, different annotation must fail too.
git('tag', '-f', '-a', 'v-test', '-m', 'different annotation')
check('--local', '--ref', 'refs/tags/v-test', passes=False)
git('push', '--force', 'ngit', 'refs/tags/v-test')
check('--all', passes=False)
git('tag', '-d', 'v-test')
git('fetch', 'origin', 'refs/tags/v-test:refs/tags/v-test')
git('push', '--force', 'ngit', 'refs/tags/v-test')
git('push', 'origin', 'HEAD:refs/heads/extra')
check('--local')
check('--all', passes=False)
git('push', 'ngit', 'HEAD:refs/heads/extra')
check('--all')
check('--ref', 'main', passes=False)
check('--remotes', 'origin', 'missing', passes=False)
git('remote', 'set-url', 'ngit', str(root / 'does-not-exist'))
check(passes=False)
if __name__ == '__main__':
unittest.main()