Summary
PostgresHookRegistry.create_release dedupes on (name, digest): redeploying a hook with the same image digest but changed config, limits, or source_ref returns the existing release unchanged (200 no-op) and never mints a new version. Since hook runs resolve and execute from the live release (#145), a config-only redeploy silently does not take effect — the old config keeps running while the author believes the new one deployed — and the release a run records describes what ran, but not what the author last declared.
The ingester registry had the identical semantics (deliberately mirrored) and was fixed in #208 (009df8e): idempotency by definition equality against the live release — byte-identical redeploy is a no-op; any difference (image, digest, config, limits, source_ref; built_by excluded) mints vN+1. The uq_(name, digest) constraint was dropped since a config-only redeploy legitimately mints a new release with the same digest.
Fix
Mirror #208's change exactly, keeping the two registries coherent (same family, same discipline):
Acceptance
- Config-only hook redeploy takes effect on the next run and is traceable to its own release version
- Identical redeploy remains a 200 no-op;
alembic check zero drift
Summary
PostgresHookRegistry.create_releasededupes on(name, digest): redeploying a hook with the same image digest but changedconfig,limits, orsource_refreturns the existing release unchanged (200 no-op) and never mints a new version. Since hook runs resolve and execute from the live release (#145), a config-only redeploy silently does not take effect — the old config keeps running while the author believes the new one deployed — and the release a run records describes what ran, but not what the author last declared.The ingester registry had the identical semantics (deliberately mirrored) and was fixed in #208 (
009df8e): idempotency by definition equality against the live release — byte-identical redeploy is a no-op; any difference (image, digest, config, limits, source_ref;built_byexcluded) mints vN+1. Theuq_(name, digest)constraint was dropped since a config-only redeploy legitimately mints a new release with the same digest.Fix
Mirror #208's change exactly, keeping the two registries coherent (same family, same discipline):
PostgresHookRegistry.create_release: compare full definition against the live release under the existing row lock; mint vN+1 on any differenceuq_hook_releases_hook_digest(incremental migration — live archives upgrade in place per the new migration policy; constraint drop is safe on populated tables)idempotent on (name, digest)→ definition equality)tests/integration/persistence/test_ingester_registry_repo.py::TestReleaseIdempotency(identical-redeploy no-op, config-only mints, rollback-then-redeploy compares against live)Acceptance
alembic checkzero drift