Files
Investidor-V2/tools/portal-onboarding-release-finalize.py
nala 287e991486
tests / ci (push) Waiting to run
oportunidades 7
2026-10-13 11:40:29 +02:00

50 lines
3.3 KiB
Python

from pathlib import Path
from datetime import datetime, timezone
import collections, csv, hashlib, json, zipfile
R=Path(__file__).resolve().parent.parent
P=R/'storage/app/private/investmoz-v2/portal-audit'
O=R/'outputs/investmoz-operational-onboarding-20261011'
load=lambda p:json.loads(p.read_text(encoding='utf-8-sig'))
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
m=load(O/'manifesto.json');wrapper=load(O/'manifesto-disponibilizacao.json')
assert wrapper['delta_sha256']==m['delta_sha256']
assert sha(O/'manifesto.json')==wrapper['original_manifest_sha256']
assert sha(O/m['package'])==m['package_sha256']==wrapper['package_sha256']
for file,value in wrapper['documents'].items(): assert sha(O/file)==value,file
expected={x['path']:x['after_sha256'] for x in m['files']}|{x['path']:x['sha256'] for x in m['assets']}
with zipfile.ZipFile(O/m['package']) as z:
assert set(z.namelist())==set(expected) and len(z.namelist())==len(expected)
for file,value in expected.items(): assert hashlib.sha256(z.read(file)).hexdigest()==value,file
for x in m['files']:
assert (sha(R/x['path']) if (R/x['path']).is_file() else None)==x['before_sha256'],x['path']
b=load(P/'onboarding-release-target-backup.json')
assert sha(Path(b['dump_path']))==b['dump_sha256'] and sha(Path(b['files_path']))==b['files_sha256']
assert datetime.now(timezone.utc)<datetime.fromisoformat(b['valid_until'])
assert b['active_writes']==0 and len(b['tables'])==295 and b['restored_target']['port']==55441
baseline=load(P/'onboarding-release-matrix-baseline.json')
csv.field_size_limit(10_000_000)
with (R/'docs/investmoz/v2/auditoria-portal/matriz-requisitos.csv').open(encoding='utf-8-sig',newline='') as f: rows=list(csv.reader(f))
assert len(rows)==len(baseline['rows']);changes=[]
for before,after in zip(baseline['rows'],rows):
assert len(before)==len(after)
for col,(a,v) in enumerate(zip(before,after)):
if a!=v:
header=rows[0][col]
assert header=='Evidência funcional' and baseline['updates'][before[0]][header]==v
changes.append(before[0])
assert sorted(changes)==['AUD-PROFILE-01','AUD-PROFILE-03','AUD-PROFILE-31']
proof={'at':datetime.now(timezone.utc).isoformat(),'result':'passed','delta':m['delta_sha256'][:12],
'package_sha256':m['package_sha256'],'release_manifest_sha256':sha(O/'manifesto-disponibilizacao.json'),
'source_files':len(m['files']),'compiled_assets':len(m['assets']),'active_payload_hashes_unchanged':True,
'backup_restored_verified_QA_only':True,'backup_table_count':len(b['tables']),'backup_file_count':b['file_count'],
'active_application_changes':0,'active_database_writes':0,'emails_sent':0,
'matrix_requirements':len(rows)-1,'matrix_source_occurrences':sum(int(row[rows[0].index('Quantidade de linhas de origem')]) for row in rows[1:]),
'matrix_changes':changes,'states_sources_versions_and_other_cells_preserved':True,
'matrix_states':dict(collections.Counter(row[rows[0].index('Estado')] for row in rows[1:])),
'readiness':'release_review_complete; authorization_pending; operational_enablement_separate',
'real_organization_representation_proof_upload':'pending_existing_backlog; does_not_block_validator_publisher_preparation',
'A_B_C37_preserved_not_retested':True}
(O/'verificacao-disponibilizacao.json').write_text(json.dumps(proof,indent=2,ensure_ascii=False),encoding='utf-8')
print(json.dumps(proof,ensure_ascii=False))