| workflow_payload |
name: Verify full Gitea customization ancestry
name: Verify full Gitea customization ancestry
"on":
push:
branches: [codex/runner-maintenance-diagnostic-20261101]
paths: [.gitea/workflows/gitea-customization-ancestry.yml]
workflow_dispatch:
jobs:
inspect:
name: inspect
runs-on: ubuntu-latest
if: github.repository == 'luoanwu/enterprise-platform'
steps:
- name: Locate official common ancestor without writing live source refs
run: |
set -eu
python3 <<'PY'
import datetime, json, os, pathlib, socket, subprocess
if os.geteuid()!=0 or socket.gethostname()!='iZ2zed3pt2nygf9dy1a9d2Z':raise RuntimeError('EXPECTED_HOST_REQUIRED')
os.umask(0o077)
base=pathlib.Path('/var/lib/eios-r1-maintenance')
if base.is_symlink() or not base.is_dir() or base.stat().st_uid!=0 or base.stat().st_mode&0o077:raise RuntimeError('PRIVATE_BASE_REQUIRED')
runid=os.environ.get('GITHUB_RUN_ID')
if not runid or not runid.isdigit():raise RuntimeError('REAL_RUN_ID_REQUIRED')
work=base/('ancestry-'+runid);work.mkdir(mode=0o700)
source=pathlib.Path('/root/gitea-src');candidate=base/'analysis-26765'/'candidate-source'
env={'PATH':'/usr/local/bin:/usr/bin:/bin','HOME':str(work),'LANG':'C.UTF-8','GIT_CONFIG_NOSYSTEM':'1','GIT_CONFIG_GLOBAL':'/dev/null','GIT_TERMINAL_PROMPT':'0','GIT_OPTIONAL_LOCKS':'0'}
def git(where,*args,timeout=30):
return subprocess.run(['git','-c','credential.helper=','-c','core.askPass=','-c','http.extraHeader=','-c','core.hooksPath=/dev/null','-C',str(where),*args],env=env,capture_output=True,timeout=timeout)
r=git(source,'rev-parse','HEAD')
if r.returncode or r.stdout.decode().strip()!='287bf811487c04cd90bcf07aa04905cbaf2e4c2d':raise RuntimeError('SOURCE_HEAD_CHANGED')
r=git(candidate,'rev-parse','HEAD')
if r.returncode or r.stdout.decode().strip()!='146cc3eec57174711eac0e0a0c7b38670c6e3922':raise RuntimeError('UPSTREAM_HEAD_CHANGED')
report={'kind':'GiteaCustomizationAncestryProbe','observedAtUTC':datetime.datetime.now(datetime.timezone.utc).isoformat(),'ci':{'sourceSha':os.environ.get('GITHUB_SHA'),'runId':runid},'releaseEligible':False,'liveSourceOrServiceChanged':False,'privateGitHistoryFetchOnly':True}
r=git(source,'log','--first-parent','-12','--format=%H %P %cI')
report['sourceFirstParentMetadata']=r.stdout.decode().splitlines() if r.returncode==0 else []
report['sourceShallow']=git(source,'rev-parse','--is-shallow-repository').stdout.decode().strip()
def emit(stage):
report['stage']=stage;print('GITEA_CUSTOM_ANCESTRY_JSON '+json.dumps(report,separators=(',',':')),flush=True)
emit('FETCHING_OFFICIAL_HISTORY_PRIVATELY')
shallow=git(candidate,'rev-parse','--is-shallow-repository').stdout.decode().strip()
args=['fetch','--no-tags','--filter=blob:none']
if shallow=='true':args.append('--unshallow')
args+=['https://github.com/go-gitea/gitea.git','refs/tags/v1.27.3']
r=git(candidate,*args,timeout=600)
(work/'official-fetch.stdout').write_bytes(r.stdout);(work/'official-fetch.stderr').write_bytes(r.stderr)
if r.returncode:
report['status']='OFFICIAL_HISTORY_FETCH_FAILED';report['exitCode']=r.returncode;emit('STOPPED');raise SystemExit(0)
r=git(candidate,'fetch','--no-tags',str(source),'HEAD:refs/heads/maintenance-current-custom-base',timeout=300)
(work/'custom-fetch.stdout').write_bytes(r.stdout);(work/'custom-fetch.stderr').write_bytes(r.stderr)
if r.returncode:
report['status']='CUSTOM_HISTORY_FETCH_FAILED';report['exitCode']=r.returncode;emit('STOPPED');raise SystemExit(0)
r=git(candidate,'merge-base','--all','146cc3eec57174711eac0e0a0c7b38670c6e3922','287bf811487c04cd90bcf07aa04905cbaf2e4c2d')
commons=r.stdout.decode().splitlines() if r.returncode==0 else []
report['commonAncestors']=commons
if len(commons)!=1:
report['status']='NO_UNIQUE_VERIFIABLE_COMMON_ANCESTOR';emit('STOPPED');raise SystemExit(0)
common=commons[0]
r=git(candidate,'show','-s','--format=%H %cI',common)
report['commonAncestorMetadata']=r.stdout.decode().strip() if r.returncode==0 else None
r=git(candidate,'diff','--no-ext-diff','--no-textconv','--numstat',common,'287bf811487c04cd90bcf07aa04905cbaf2e4c2d',timeout=120)
if r.returncode:raise RuntimeError('COMMITTED_FORK_DIFF_FAILED')
rows=[]
for line in r.stdout.decode().splitlines():
fields=line.split('\t',2)
if len(fields)!=3:continue
name=fields[2]
if any(x in name.lower() for x in ['.env','secret','credential','password','.pem','.key']):name='SENSITIVE_PATH_NOT_EXPORTED'
rows.append({'added':fields[0],'removed':fields[1],'path':name})
report['committedForkChangedFileCount']=len(rows)
report['committedForkDelta']=rows[:120]
report['committedForkDeltaTruncated']=len(rows)>120
report['status']='COMMON_ANCESTOR_AND_COMMITTED_CUSTOMIZATION_IDENTIFIED'
(work/'receipt.json').write_text(json.dumps(report,indent=2)+'\n')
emit('COMPLETE')
PY
shell: bash
timeout-minutes: "20"
permissions:
contents: read
... |