"""本批静态校验及当前隔离 JAR 的契约对照,不修改契约。""" import json,pathlib,subprocess,sys,requests ROOT=pathlib.Path('D:/Workspaces/qsp-reapply-20261020') REPO=pathlib.Path(__file__).resolve().parents[3] rows=[] def check(name,ok,actual=None):rows.append({'case':name,'ok':bool(ok),'actual':actual}) p=subprocess.run([sys.executable,str(REPO/'docs/verify_openapi.py')],capture_output=True,text=True,encoding='utf-8',errors='replace',env={**__import__('os').environ,'PYTHONIOENCODING':'utf-8'}) (ROOT/'logs/static-openapi.log').write_text(p.stdout+p.stderr,encoding='utf-8');check('static verifier',p.returncode==0,p.returncode) static=json.loads((REPO/'docs/openapi-rc.json').read_text(encoding='utf-8')) r=requests.get('http://127.0.0.1:18090/api/v1/v3/api-docs',timeout=30);check('runtime OpenAPI reachable',r.status_code==200,r.status_code);runtime=r.json() (ROOT/'runtime-openapi.json').write_text(json.dumps(runtime,ensure_ascii=False),encoding='utf-8') check('same path identities',set(static['paths'])==set(runtime['paths'])) methods={'get','post','put','patch','delete','head','options','trace'} ops=lambda doc:{(p,m) for p,vs in doc['paths'].items() for m in vs if m in methods} check('same operation identities',ops(static)==ops(runtime)) for name in ['CandidateItemView','CandidateDetailView']: for field,fmt in [('attemptNumber','int32'),('previousApplicationId','int64')]: a=static['components']['schemas'][name]['properties'][field];b=runtime['components']['schemas'][name]['properties'][field] check(name+'.'+field,a.get('type')==b.get('type')=='integer' and a.get('format')==b.get('format')==fmt,{'static':a,'runtime':b}) forbidden=set(runtime['components']['schemas'][name]['properties'])&{'studentUserId','phone','email','resumeUrl','storagePath'} check(name+' remains redacted',not forbidden,sorted(forbidden)) for path in ['/applications','/applications/{id}/withdraw']: check(path+' description',static['paths'][path]['post']['description']==runtime['paths'][path]['post']['description']) (ROOT/'contract-results.json').write_text(json.dumps(rows,ensure_ascii=False,indent=2),encoding='utf-8') print('CONTRACT',len(rows),'FAIL',sum(not r['ok'] for r in rows));raise SystemExit(any(not r['ok'] for r in rows))