Skip to content

feat: automatic image updates via OCI registry digest polling - #8

Merged
stubbi merged 3 commits into
mainfrom
feat/auto-update
Mar 23, 2026
Merged

feat: automatic image updates via OCI registry digest polling#8
stubbi merged 3 commits into
mainfrom
feat/auto-update

Conversation

@stubbi

@stubbi stubbi commented Mar 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds automatic image update support to the operator. When enabled, the operator periodically polls the container registry for new image digests and triggers rolling updates automatically.

Usage

spec:
  image:
    repository: ghcr.io/paperclipinc/paperclip
    tag: latest
    autoUpdate:
      enabled: true
      interval: 5m

When a new image is pushed to ghcr.io/paperclipinc/paperclip:latest, the operator detects the digest change within the polling interval and triggers a rolling restart of the StatefulSet.

How it works

  1. Operator polls the registry via OCI Distribution API (HEAD /v2/{name}/manifests/{tag})
  2. Compares the Docker-Content-Digest header against the last known digest
  3. When changed, writes the new digest as a pod template annotation (paperclip.inc/resolved-digest)
  4. StatefulSet controller detects the annotation change and triggers a rolling update

Implementation

  • CRD: AutoUpdateSpec (enabled, interval) on ImageSpec, AutoUpdateStatus on InstanceStatus
  • Registry client (internal/registry): OCI registry client with bearer token auth flow, supports GHCR, Docker Hub, and private registries via imagePullSecrets
  • Reconciler: reconcileAutoUpdate method using requeue-based polling (leader-election safe, no background goroutines)
  • Rollout trigger: Pod annotation injection (same mechanism as kubectl rollout restart)

Test plan

  • 11 new unit tests (registry client: anonymous, bearer auth, credentials, errors, parsing; StatefulSet annotation injection)
  • All 34 tests pass
  • Lint clean (golangci-lint)
  • Manual: deploy with autoUpdate enabled, push new image, verify rollout

🤖 Generated with Claude Code

stubbi and others added 3 commits March 23, 2026 18:06
When spec.image.autoUpdate.enabled is true, the operator periodically
queries the container registry for the current digest of the configured
tag. When a new digest is detected, it injects a pod annotation that
triggers a rolling StatefulSet update.

- AutoUpdateSpec on ImageSpec with enabled/interval fields
- AutoUpdateStatus tracking lastCheckTime, resolvedDigest, lastUpdateTime
- OCI registry client (internal/registry) with bearer token auth flow
- Supports GHCR, Docker Hub, and private registries via imagePullSecrets
- Pod annotation-based rollout (same mechanism as kubectl rollout restart)
- Requeue-based polling (idiomatic controller-runtime, leader-election safe)
- 11 new tests (registry client + StatefulSet annotation injection)

Usage:
  spec:
    image:
      tag: latest
      autoUpdate:
        enabled: true
        interval: 5m

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI uses golangci-lint v2.1.0 which doesn't flag gosec G704 on these
lines, making the nolint:gosec directives unused.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The registry client makes HTTP requests to operator-configured registry
URLs (not untrusted user input). Add #nosec G704 directives for the
standalone gosec scanner used in CI security scan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@stubbi
stubbi merged commit 90858c1 into main Mar 23, 2026
8 checks passed
@stubbi
stubbi deleted the feat/auto-update branch March 23, 2026 17:29
@stubbi stubbi mentioned this pull request Mar 23, 2026
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.

1 participant