Skip to content

Experimental: Show Flux reconciliation history (status.history) for Kustomization & HelmRelease #397

@laszlocph

Description

@laszlocph

Why

Flux controllers persist a small rolling reconciliation/release history directly on the CR in status.history. This is useful for operators debugging “what changed, when, and did it work?” without digging through events/logs.

I want to add an experimental UI in Capacitor to render this history so we can validate whether it is useful in day-to-day app operations.

Reference implementation/inspiration: flux-operator web UI history timeline + navigation fix:


Data source (no new backend required)

Capacitor already watches/loads Flux resources; the history is part of the watched object JSON.

Kustomization

  • kustomize.toolkit.fluxcd.io/Kustomization
  • status.history[] entries typically contain:
    • digest, firstReconciled, lastReconciled, lastReconciledDuration, lastReconciledStatus, totalReconciliations
    • metadata.revision (+ sometimes metadata.originRevision)

HelmRelease

  • helm.toolkit.fluxcd.io/HelmRelease
  • status.history[] entries typically contain:
    • version, status (e.g. deployed / superseded), firstDeployed, lastDeployed
    • chartName, chartVersion, optional appVersion
    • digest, configDigest, optional ociDigest

Proposed UX (mockup)

Kustomization details: add a “History” tab

Render newest-first.

Row content

  • Outcome badge: derived from lastReconciledStatus (Succeeded / Failed / Other)
  • Time: lastReconciled (and optionally range firstReconciled → lastReconciled when different)
  • Duration: lastReconciledDuration
  • Reconciliations count: totalReconciliations
  • Revision: metadata.revision (clickable when source is GitRepository + SHA present, similar to existing revision rendering)
  • Digest: digest (shortened, copy button)

Example:

Reconciliation history (last 5 snapshots stored by controller)

[✓ Succeeded]  2026-02-08 10:24:12Z   duration: 12.4s   reconciliations: 397
Revision: main@sha1:b070466
Digest:   sha256:d8fc4a3a7b06…

[✗ HealthCheckFailed]  2026-02-08 09:59:01Z   duration: 2m10s   reconciliations: 396
Revision: main@sha1:a8c1d2e
Digest:   sha256:91ad0c2f0f88…

HelmRelease details: add a “History” tab

Prefer HelmRelease.status.history (CR-based) for an MVP (no Helm storage access required).

Row content

  • Status badge: from status (deployed / superseded / etc.)
  • Revision: version
  • Updated: lastDeployed
  • Chart: ${chartName}@${chartVersion}
  • App Version: appVersion (if present)
  • Values/Config fingerprint: configDigest (shortened, copy button)

Example:

Release history (last ~5 snapshots stored by controller)

[✓ deployed]   rev: 42   2026-02-08 10:12:09Z
Chart: tailscale-operator@1.2.3   App: 0.9.1
Config digest: sha256:1a2b3c4d…

[• superseded] rev: 41   2026-02-07 18:44:31Z
Chart: tailscale-operator@1.2.2   App: 0.9.0

Implementation notes

  • Add a small reusable component (e.g. HistoryTimeline or HistoryList) that supports two schemas:
    • Kustomization-style: firstReconciled/lastReconciled/lastReconciledStatus/totalReconciliations/metadata.revision
    • HelmRelease-style: firstDeployed/lastDeployed/status/version/chartVersion/appVersion/configDigest
  • Reset/avoid stale UI state when navigating between resources (see flux-operator PR #532).
  • Mark as Experimental (feature flag in config, env var, or hidden behind an “Experimental” toggle).

Acceptance criteria

  • Kustomization details show a History tab when status.history exists, otherwise show “No history available”.
  • HelmRelease details show a History tab when status.history exists, otherwise show “No history available”.
  • Entries render newest-first and are readable on small screens (table or timeline is fine).
  • Revision/digest fields are truncated but copyable; Kustomization revision is clickable for Git sources when possible.
  • Feature is clearly labeled Experimental and can be disabled.

Out of scope (for the first iteration)

  • Correlating history entries with Events/logs
  • Showing full diffs between digests
  • Anything that requires extra cluster permissions beyond reading the CR

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