WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Exercise historical business imports in PostgreSQL and roll back every case."""
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from apply_weknora_business import build_plan, target_snapshot, PRESERVED_TABLES
|
||||
from apply_weknora_identities import sql_run
|
||||
from verify_asset_etl import unchanged_check
|
||||
from verify_identity_etl import rejected_case
|
||||
from weknora_business_etl import LEDGER, TARGET_DATABASE, TARGET_TENANT, business_sql
|
||||
from weknora_category_etl import literal, save_json
|
||||
from weknora_etl import consistent_snapshot
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--sqlite', type=Path, required=True)
|
||||
parser.add_argument('--kb-mapping', type=Path, required=True)
|
||||
parser.add_argument('--artifact-root', type=Path, required=True)
|
||||
parser.add_argument('--out', type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
if args.out.exists():
|
||||
parser.error('Report exists')
|
||||
with consistent_snapshot(args.sqlite) as (db, info):
|
||||
plan = build_plan(db, args.kb_mapping, args.artifact_root)
|
||||
plan['source_snapshot_sha256'] = info['sha256']
|
||||
query = business_sql(plan)
|
||||
first = plan['resources'][0]['target']
|
||||
rid = literal(first['id'])
|
||||
owner = literal(next(uid for uid in plan['identity_mapping'].values() if uid != first['owner_id']))
|
||||
scope = f"target_id={rid} AND target_tenant_id={TARGET_TENANT}"
|
||||
cases = [
|
||||
('wrong_resource_tenant_rejected', f'UPDATE workbench_resources SET tenant_id={TARGET_TENANT + 1} WHERE id={rid};', 'Mapped business resource removed'),
|
||||
('wrong_resource_owner_rejected', f'UPDATE workbench_resources SET owner_id={owner} WHERE id={rid};', 'Mapped business resource removed'),
|
||||
('deleted_resource_not_recreated', f'DELETE FROM workbench_resources WHERE id={rid};', 'Mapped business resource removed'),
|
||||
('ledger_target_conflict_rejected', f"UPDATE {LEDGER} SET target_id='rollback-only' WHERE {scope};", 'Business durable mapping conflict'),
|
||||
('ledger_source_conflict_rejected', f"UPDATE {LEDGER} SET source_snapshot='{{}}' WHERE {scope};", 'Business durable mapping conflict'),
|
||||
('ledger_projection_conflict_rejected', f"UPDATE {LEDGER} SET native_snapshot='{{}}' WHERE {scope};", 'Business durable mapping conflict'),
|
||||
('id_without_provenance_rejected', f'DELETE FROM {LEDGER} WHERE {scope};', 'Native business ID or owner/name collision'),
|
||||
('inactive_tenant_rejected', f"UPDATE tenants SET status='suspended' WHERE id={TARGET_TENANT};", 'Business migration requires active target tenant'),
|
||||
]
|
||||
before = target_snapshot()
|
||||
ledger_before = sql_run(f"SELECT to_regclass('public.{LEDGER}') IS NOT NULL;")
|
||||
sql = "BEGIN ISOLATION LEVEL SERIALIZABLE; SET LOCAL statement_timeout='45s'; SET LOCAL lock_timeout='5s';\n"
|
||||
preserved = [(table, f'_preserved_{i}') for i, table in enumerate(PRESERVED_TABLES)]
|
||||
for table, name in preserved:
|
||||
sql += f'CREATE TEMP TABLE {name} ON COMMIT DROP AS SELECT * FROM {table};\n'
|
||||
sql += query
|
||||
pairs = [('workbench_resources', '_resource_repeat'), (LEDGER, '_ledger_repeat')]
|
||||
for table, name in pairs:
|
||||
sql += f'CREATE TEMP TABLE {name} ON COMMIT DROP AS SELECT * FROM {table};\n'
|
||||
sql += query + unchanged_check('exact_repeat_noop', pairs + preserved)
|
||||
for name, mutation, expected in cases:
|
||||
sql += rejected_case(name, mutation, expected, query)
|
||||
sql += f"UPDATE workbench_resources SET name='Rollback native edit',status='paused',version=99,data=jsonb_set(data,'{{description}}','\"Local edit\"'::jsonb) WHERE id={rid};\n"
|
||||
sql += 'CREATE TEMP TABLE _native_edit ON COMMIT DROP AS SELECT * FROM workbench_resources;\n'
|
||||
sql += query + unchanged_check('native_edits_preserved', [('workbench_resources', '_native_edit'), pairs[1], *preserved])
|
||||
sql += 'ROLLBACK;'
|
||||
checks = [json.loads(line) for line in sql_run(sql).splitlines() if line.startswith('{')]
|
||||
checks.extend([
|
||||
{'check': 'all_cases_executed', 'passed': len(checks) == len(cases) + 2},
|
||||
{'check': 'all_regressions_rolled_back', 'passed': before == target_snapshot() and ledger_before == sql_run(f"SELECT to_regclass('public.{LEDGER}') IS NOT NULL;")},
|
||||
{'check': 'source_unchanged', 'passed': not info['source_mutated']},
|
||||
])
|
||||
result = {'database': TARGET_DATABASE, 'committed': False, 'passed': all(c['passed'] for c in checks), 'checks': checks}
|
||||
save_json(args.out, result)
|
||||
print(json.dumps(result))
|
||||
return 0 if result['passed'] else 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user