Skip to content

Commit e0c0877

Browse files
committed
chore: fix post-audit release convergence
1 parent 2f25001 commit e0c0877

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: Fix post-audit release convergence
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths: ['.github/workflows/tmp-fix-release-idempotence.yml']
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
patch:
13+
runs-on: ubuntu-latest
14+
timeout-minutes: 10
15+
steps:
16+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
17+
with:
18+
ref: main
19+
fetch-depth: 0
20+
21+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
22+
with:
23+
python-version: '3.12'
24+
25+
- name: Patch convergence and regression guard
26+
shell: bash
27+
run: |
28+
set -euo pipefail
29+
python - <<'PY'
30+
from pathlib import Path
31+
32+
sync = Path('.github/workflows/sync.yml')
33+
text = sync.read_text(encoding='utf-8')
34+
35+
old = ''' # The audit is allowed to mutate activation state. Re-run the same
36+
# idempotent finalizer against the original published generation so
37+
# late quarantine/metadata changes cannot escape provider/global cache
38+
# invalidation, and cannot double-bump earlier changes.
39+
python scripts/generate_language_manifests.py
40+
'''
41+
new = ''' # The audit may rewrite/quarantine provider artifacts after the first
42+
# publication finalizer. Converge runtime profiles/overrides again
43+
# before rebuilding projections/catalog and fingerprinting the exact
44+
# generation that will be pushed. A clean published checkout must be
45+
# idempotent under the same override finalizer.
46+
python scripts/build_provider_runtime_profiles.py
47+
python scripts/reapply_published_overrides.py
48+
python scripts/prune_unreferenced_providers.py
49+
python scripts/generate_language_manifests.py
50+
'''
51+
if text.count(old) != 1:
52+
raise SystemExit(f'sync audit anchor count={text.count(old)}')
53+
text = text.replace(old, new, 1)
54+
55+
old_verify = ''' npm test
56+
node engine_v2/tests/provider-catalog.test.mjs
57+
'''
58+
new_verify = ''' # Exact published main must already be a fixed point. Do not let npm
59+
# pretest be the first command that silently repairs the generation.
60+
python scripts/build_provider_runtime_profiles.py
61+
python scripts/reapply_published_overrides.py
62+
python scripts/prune_unreferenced_providers.py
63+
git diff --exit-code
64+
npm test
65+
node engine_v2/tests/provider-catalog.test.mjs
66+
'''
67+
if text.count(old_verify) != 1:
68+
raise SystemExit(f'sync verify anchor count={text.count(old_verify)}')
69+
sync.write_text(text.replace(old_verify, new_verify, 1), encoding='utf-8')
70+
71+
test = Path('tests/sync_atomic_publication_test.py')
72+
body = test.read_text(encoding='utf-8')
73+
old_test = '''audit = workflow.index("Audit content identity and media", first_activation)
74+
final_version = workflow.index("python scripts/sync_release_versions.py", audit)
75+
final_activation = workflow.index("python scripts/validate_activation_preservation.py", final_version)
76+
final_catalog = workflow.index("node engine_v2/scripts/bootstrap-provider-catalog.mjs", final_activation)
77+
'''
78+
new_test = '''audit = workflow.index("Audit content identity and media", first_activation)
79+
post_audit_profiles = workflow.index("python scripts/build_provider_runtime_profiles.py", audit)
80+
post_audit_reapply = workflow.index("python scripts/reapply_published_overrides.py", post_audit_profiles)
81+
post_audit_prune = workflow.index("python scripts/prune_unreferenced_providers.py", post_audit_reapply)
82+
final_version = workflow.index("python scripts/sync_release_versions.py", post_audit_prune)
83+
final_activation = workflow.index("python scripts/validate_activation_preservation.py", final_version)
84+
final_catalog = workflow.index("node engine_v2/scripts/bootstrap-provider-catalog.mjs", final_activation)
85+
'''
86+
if body.count(old_test) != 1:
87+
raise SystemExit(f'atomic test anchor count={body.count(old_test)}')
88+
body = body.replace(old_test, new_test, 1)
89+
old_assert = 'assert build < first_version < first_activation < audit < final_version < final_activation < final_catalog < hashes < commit < push < verify\n'
90+
new_assert = 'assert build < first_version < first_activation < audit < post_audit_profiles < post_audit_reapply < post_audit_prune < final_version < final_activation < final_catalog < hashes < commit < push < verify\n'
91+
if body.count(old_assert) != 1:
92+
raise SystemExit(f'atomic ordering anchor count={body.count(old_assert)}')
93+
body = body.replace(old_assert, new_assert, 1)
94+
body += '''\nverify_section = workflow[workflow.index("Verify exact published main", push):]\nassert verify_section.index("python scripts/reapply_published_overrides.py") < verify_section.index("npm test")\nassert verify_section.index("git diff --exit-code") < verify_section.index("npm test")\n'''
95+
test.write_text(body, encoding='utf-8')
96+
PY
97+
98+
python tests/sync_atomic_publication_test.py
99+
python tests/release_version_sync_test.py
100+
python tests/release_auto_bump_test.py
101+
102+
- name: Commit tested fix and remove temporary workflows
103+
shell: bash
104+
run: |
105+
set -euo pipefail
106+
git config user.name 'github-actions[bot]'
107+
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
108+
git rm .github/workflows/tmp-fix-release-idempotence.yml
109+
if [ -f .github/workflows/tmp-apply-brain-historical-learning-v2.yml ]; then
110+
git rm .github/workflows/tmp-apply-brain-historical-learning-v2.yml
111+
fi
112+
git add .github/workflows/sync.yml tests/sync_atomic_publication_test.py
113+
git commit -m 'fix: converge release after catalogue audit'
114+
git fetch origin main
115+
git rebase origin/main
116+
git push origin HEAD:main

0 commit comments

Comments
 (0)