"""Run the actual controller migration/stream framing in pinned Forgejo userspace.""" from pathlib import Path import importlib.util import json import subprocess HERE=Path(__file__).resolve().parent IMAGE='code.forgejo.org/forgejo/forgejo@sha256:691657c7e64af7730a2e885e6d022cf16ae60724931c5392bd61838afadcaeba' spec=importlib.util.spec_from_file_location('r4',HERE/'rollout.py');r=importlib.util.module_from_spec(spec);spec.loader.exec_module(r) m=r.support();C=json.loads((r.ORIGINAL/'inputs.json').read_bytes()) def main(): argv=['docker','run','-d','--rm','--network=none','--user=1000:1000','--read-only','--cap-drop=ALL','--security-opt=no-new-privileges:true', '--tmpfs','/tmp:rw,size=64m,uid=1000,gid=1000','--tmpfs','/data:rw,size=64m,uid=1000,gid=1000', '--mount','type=bind,src='+str(r.ORIGINAL)+',dst=/original,readonly','--entrypoint=/bin/sh',IMAGE,'-c','tail -f /dev/null'] created=subprocess.run(argv,capture_output=True,timeout=30) if created.returncode:raise RuntimeError('fixture-container-start-failed') cid=created.stdout.decode().strip();events=[];phase='setup' def shell(script,args=(),data=None,timeout=180): q=subprocess.run(['docker','exec','-i',cid,'/bin/sh','-c',script,'sh',*args],input=data,capture_output=True,timeout=timeout) if q.returncode:raise RuntimeError('fixture-command-failed:'+phase) return q.stdout try: script=r'''set -eu n=0 while test "$n" -lt 171; do name=$(printf test%03d "$n") repo=/data/git/gitea-repositories/coulomb/$name.git for hook in pre-receive post-receive update pre-receive.d/gitea post-receive.d/gitea update.d/gitea pre-receive.d/20-authorize post-receive.d/20-notify; do path="$repo/hooks/$hook";mkdir -p "${path%/*}" printf 'unchanged generated hook\n' > "$path";chmod 775 "$path" done file="$repo/hooks/pre-receive.d/10-custodian-secret-scan" cp /original/before-hook "$file";chmod 775 "$file" if test "$n" -lt 3; then chmod 755 "$file"; fi if test "$n" -lt 16; then chmod 755 "$repo/hooks/pre-receive"; fi n=$((n+1)) done ''' shell(script) class TestRunner(r.make_runner(m)): def shell(self,pod,script,args=(),data=None,timeout=90):return shell(script,args,data,max(timeout,180)) def event(self,name,**fields):events.append({'event':name,**fields}) runner=TestRunner(C);before=runner.inventory('fixture',{C['old_hook_sha256']});runner.receipt['before_hooks']=before phase='initial-migration';runner.migrate('fixture','apply') phase='simulate-fsgroup';shell("find /data -type f -exec chmod g+w {} +") phase='post-recreate-migration';runner.migrate('fixture','apply') assert events[-1]['group_write_additions_reversed']==19 phase='simulate-second-fsgroup';shell("find /data -type f -exec chmod g+w {} +") phase='rollback-migration';runner.migrate('fixture','rollback') after=runner.inventory('fixture',{C['old_hook_sha256']});assert after==before # Unknown protected data must stop before any scanner rewrite. phase='protected-drift';shell("printf 'owner content drift\\n' > /data/git/gitea-repositories/coulomb/test000.git/hooks/pre-receive") try:runner.migrate('fixture','apply') except RuntimeError as exc:assert str(exc)=='protected-hook-content-drift' else:raise AssertionError('protected-drift-not-refused') still=runner.inventory('fixture',{C['old_hook_sha256']});assert len(still)==171 result={'result':'passed','image':IMAGE,'repositories':171,'hooks':sum(len(x) for x in before.values()), 'cases':['initial-migration','post-recreate-mode-restoration','rollback-mode-restoration','protected-drift-before-write'], 'group_write_additions_reversed':19,'events':events,'native_mutation':False} (HERE/'controller-image-tests.json').write_text(json.dumps(result,indent=2)+'\n');print(json.dumps(result)) except Exception as exc: (HERE/'controller-image-tests-failed.json').write_text(json.dumps({'result':'unverified','phase':phase,'error':type(exc).__name__,'image':IMAGE,'native_mutation':False},indent=2)+'\n') raise finally: subprocess.run(['docker','stop','--time=0',cid],capture_output=True,timeout=30) if __name__=='__main__':main()