Skip to content

feat(cd): dispatch digest-pinned state updates to PostHog/charts after each release build - #87

Merged
fuziontech merged 1 commit into
mainfrom
sec/state-file-cd
Sep 3, 2026
Merged

feat(cd): dispatch digest-pinned state updates to PostHog/charts after each release build#87
fuziontech merged 1 commit into
mainfrom
sec/state-file-cd

Conversation

@fuziontech

Copy link
Copy Markdown
Member

Summary

Viaduck deploys to the managed-warehouse clusters from the mutable :prod/:dev tags with pullPolicy: Always and an auto-restart CronJob. Anyone who can retag the GHCR package ships code to production within ~10 minutes with no PR, no approval, and no recorded provenance — into a service that writes every tenant duckling bucket and holds every destination Postgres password. A security review flagged this as a High finding.

This PR onboards viaduck to the standard state-file digest-pin pipeline (like duckgres): after each release build, the workflow records <commit>@sha256:<digest> in state/viaduck.yaml via commit_state_update repository-dispatch. ArgoCD rolls the pinned digest with prod-approval gating.

Changes

  • release.yaml: github.repository == 'PostHog/viaduck' guard; push a :<commit-sha> tag; compute the manifest digest; dispatch commit_state_update with release: "viaduck" to PostHog/charts.
  • New actions pinned by SHA (same pins as duckgres's CD).
  • No existing tags removed — :latest/:dev/:prod keep flowing until the charts-side cutover PR lands. The promote-to-dev/prod retag workflows become deploy no-ops after cutover and can be retired in a follow-up.

Prerequisites

  • GH_APP_CHARTS_DEPLOYER_APP_ID / GH_APP_CHARTS_DEPLOYER_PRIVATE_KEY secrets must exist in this repo (or org) — same app as duckgres uses. gh secret list shows neither; needs an org admin if not org-level.

Testing

  • YAML validated; dispatch payload mirrors the proven duckgres contract. First real validation is the next main build after merge: expect a state/viaduck.yaml commit bumping image.sha.

Rollback

  • Revert; charts continues to follow the seed digest in state/viaduck.yaml.

Adds the state-file CD step to the existing release workflow (no second
image pipeline): after the multi-arch image push, record the manifest
digest and dispatch commit_state_update to PostHog/charts so
state/viaduck.yaml pins <commit>@sha256:<digest> and ArgoCD rolls it
with prod-approval gating.

Mutable :latest/:dev/:prod tags are kept for back-compat until the
charts-side cutover lands. Also tags the image with the commit SHA for
digest inspection and traceability, and guards the job to the canonical
repo.

Requires GH_APP_CHARTS_DEPLOYER_APP_ID / GH_APP_CHARTS_DEPLOYER_PRIVATE_KEY
secrets (not yet present in this repo).

Co-authored-by: Shelley <shelley@exe.dev>
@fuziontech
fuziontech requested a review from a team September 3, 2026 23:45
@jghoman

jghoman commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Same review as millpond#136 — mechanics sound (fork guard, pinned actions, immutable :<sha> tag + raw-manifest digest, back-compat tags, duckgres-shaped payload). Cutover preconditions for the charts side:

  1. Seed order: state/viaduck.yaml doesn't exist in charts and nothing consumes it yet; per charts' new-app-image-releases doc the hand-seed must be postdated by a real dispatch or the pin freezes at seed. Merge this first; confirm the charts handler's behavior for an unknown release in the interim.
  2. Autobounce collision: viaduck's autobounce CronJob rollout-restarts on digest drift vs the registry tag. Under a digest pin, every release moves :prod/:latest while the pin holds — that's either a permanent-drift restart loop or a no-op depending on the comparison; the charts cutover must retire/gate it explicitly. (Restart loops are extra costly here: each viaduck restart costs the whale destinations 20-30 min of catch-up.)
  3. Promote semantics: dispatch fires on every main merge; "prod-approval gated" depends on the charts approval environment being wired for this release.
  4. Consumer inventory: beyond the main deployment — viaduck-metrics, the per-destination metrics deployment, and the compaction/maintenance CronJobs (which run the millpond image, coordinating with millpond#136's cutover) all reference mutable tags today; the pin needs to reach the full set or the namespace runs half-pinned.

@fuziontech
fuziontech merged commit 5933ba5 into main Sep 3, 2026
16 checks passed
@fuziontech

Copy link
Copy Markdown
Member Author

Heads-up: the post-merge release build (run 33819793873) built and pushed the image fine, but the commit_state_update dispatch failed: GH_APP_CHARTS_DEPLOYER_APP_ID/GH_APP_CHARTS_DEPLOYER_PRIVATE_KEY are not available to this repo (duckgres gets them via org-level secrets with selected-repository visibility). An org admin needs to grant this repo access (or add repo-level equivalents). Until then state/viaduck.yaml stays at its seed digest — safe, but pins won't advance.

@fuziontech
fuziontech deleted the sec/state-file-cd branch September 4, 2026 00:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants