feat(managementapi): emit the repository-created usage event (S23 Step 5)
What
S23 Step 5 of the usage-data foundation plan: the first catalog event, artifact_registry_repository_created.
internal/managementapi/create.goemits the event on the create handler's success path, after the row has committed and serialized cleanly and right before the 201 write, so a persisted-but-unserializable row emits nothing. Dimensions come from the resolved ADR-007 namespace anchor (via the Step 4requestNamespaceseam) and the created repository; the two container-image wire formats (docker,oci) collapse to the context's singlecontainermember. A namespace without a parseable(organization, entity_id)anchor emits nothing and logs at Error: ADR-007 guarantees the anchor, so that branch firing in production is a data defect, and the tracker's drop counter cannot see a skip that never reachesTrack.- The event name ships as the
managementapi.EventRepositoryCreatedconstant; the handler consumes the tracker through a consumer-sideUsageTrackerinterface (mirroringRepositoryCreator), threaded throughDepsandwireManagementAPIfrom the Step 3w.usageDataseam, with nil-guards at every layer. docs/dev/usage-data.md(pre-anticipated by the plan) documents local verification with Snowplow Micro: the GDK recipe, a standalone container with the GitLab iglu resolver the image lacks by default, the developmentusage_dataconfig, and how to read/micro/good.
Stacked on !934 (merged) (Step 3) — this MR targets jdrpereira/s23-usage-data-foundation-step-2's successor branch jdrpereira/s23-usage-data-foundation-step-3 and must merge after !912 (merged) and !934 (merged); GitLab retargets automatically as the stack merges.
Spec coverage
Spec: docs/specs/S23-usage-data-collection.md
This MR owns AC-9. All other rows are owned by the earlier steps of the same plan: Step 1 (!910 (merged)), Step 2 (!912 (merged)), Step 3 (!934 (merged)), Step 4 (!932 (merged)).
| # | Criterion | Tests |
|---|---|---|
| AC-9 | Repository create emits exactly one first event with the expected dimensions; failed creates emit none | TestCreateHandler_EmitsRepositoryCreatedEvent (per-format table incl. the docker/oci → container collapse, anchor and repository dimensions, correlation-ID forwarding), TestCreateHandler_FailurePaths_EmitNoEvent (400/409/422/500/nil-row/serialization failure), TestCreateHandler_UnattributableAnchor_EmitsNoEvent (guard clauses isolated per row, incl. the non-integer entity_id parse), TestCreateHandler_UnknownSlug_EmitsNoEvent |
Manual acceptance (a create against a local service shows the event in Snowplow Micro's /micro/good) is documented step-by-step in the new docs/dev/usage-data.md. Verified against a live Micro on this branch: 1 good, 0 bad, both com.gitlab contexts pass iglu validation. The doc's Option C points at the Caproni rig counterpart, gitlab-com/gl-infra/sandbox/caproni-demo!220 (merged), which deploys Micro in-cluster pre-wired.
Notes
- The first commit is the documented test-first
--no-verifycarve-out; every other commit ran the full hook chain. - The two merge commits at the base of the branch cascade
main(which now contains Step 4, !932 (merged)) down the stack so this diff builds on the anchor seam; they disappear from the diff as the stack merges.
Related to #272 (closed)