Skip to content

Push OpenAPI changes to archiver (replace archiver's Layer C poll) #214

Description

@gregoryfoster

Context

CannObserv/archiver vendors a generated watcher_client SDK from Watcher's OpenAPI (clients/watcher-python/). When Watcher changes a response shape, the committed client silently goes stale until it fails at runtime — that was incident archiver#66 (default_content_type dropped → KeyError on every parse).

Archiver now has three defensive layers (archiver#67):

Why this issue (the preferred long-term replacement)

Polling is the fallback. The cleaner design is Watcher pushing on change: when Watcher's OpenAPI changes, fire a repository_dispatch to archiver, which opens the regen PR. Event-driven, no scheduled flake, no archiver↔Watcher uptime coupling. Archiver could then retire the Layer C timer.

That wasn't buildable from archiver's side because this repo currently has no CI workflows and commits no OpenAPI snapshot — so there's nothing to detect "the OpenAPI changed" against, and nothing to fire the dispatch.

Proposed work (in this repo)

  1. Commit an OpenAPI snapshot + a CI gate. Add a script that dumps Watcher's own /openapi.json in-process (no server/DB, like archiver's scripts/dump_openapi.py), commit the snapshot, and add a CI job that fails if the regenerated spec differs from the committed one. This makes "the OpenAPI changed" a reviewable, detectable event.
  2. Dispatch on change. When the committed OpenAPI snapshot changes on main, fire a repository_dispatch (e.g. event_type: watcher-openapi-changed) to CannObserv/archiver. Archiver adds a workflow that, on receipt, regenerates watcher_client from the new spec and opens a bump PR.
  3. Retire archiver's poll. Once the push path is proven, archiver removes the Layer C on-VM timer (scripts/watcher_live_drift_pr.sh, ff_deploy_clone.sh, deploy/watcher-live-drift.*).

Notes

  • Needs a token with repository_dispatch permission on CannObserv/archiver, stored in this repo's Actions secrets.
  • The OpenAPI dump in (1) is also independently useful as Watcher's own contract-of-record.

Refs: archiver#70 (Layer C poll this replaces) · archiver#68 (Layer B gate) · archiver#67 (parent) · archiver#66 (incident).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions