Flux Manifest Preview (fmp)

fmp is a CLI tool designed to render and diff the manifests produced by Flux GitOps repositories. It bridges the gap between local development and the cluster by showing exactly what Flux would apply.
π Key Features
fmp understands common Flux repository patterns instead of treating YAML as flat files:
- π’ GitOps Awareness: Discover and follow Flux
Kustomization.spec.path and resolve external GitRepository sources.
- π¦ Helm Integration: Render
HelmRelease resources through the Helm SDK, including support for post-renderers and commonMetadata.
- π Intelligent Diffing: Compare local worktree changes against
HEAD or other revisions with noisy field normalization.
- π Secret Support: Decrypt SOPS-encrypted resources on the fly when requested.
- π§Ή Clean Output: Filter generated fields (like timestamps or random hashes) for deterministic and readable diffs.
[!NOTE]
Status: This project is under active development. While it is useful for day-to-day validation and review, expect some rough edges as the workflow is refined.
πΎ Install
From source:
go install ./cmd/fmp
Directly via Go:
go install github.com/tobiash/flux-manifest-preview/cmd/fmp@latest
π οΈ Requirements
git: For git-aware diffing and external repository resolution.
helm: For registry/cache configuration when rendering Helm charts.
β‘ Quick Start
The core workflow is designed to be git-aware. Run this inside a Flux git worktree to see what would change if you committed your current work:
fmp diff
This compares the rendered output of HEAD against your current dirty worktree.
π οΈ Usage & Commands
π Diffing Changes
Compare the rendered output of different git refs or local paths:
fmp diff # Diff HEAD vs Worktree
fmp diff HEAD~1 # Diff 1 commit back vs Worktree
fmp diff main feature-branch # Diff two branches
fmp diff ./before ./after # Diff two local paths
fmp diff git:HEAD path:/tmp # Mix git refs and local paths
π Rendering Manifests
Render a repository or a specific path to standard output:
fmp render <path>
fmp render --output json <path>
π§ͺ Validation & Discovery
Ensure your Flux resources are well-formed and discoverable:
fmp test <path> # Validate that KS/HR can be rendered
fmp get ks <path> # List discovered Kustomizations
fmp get hr <path> # List discovered HelmReleases
Tools for automation and handling non-deterministic output:
fmp ci # CI-optimized diff mode
fmp detect-permadiffs <path> # Detect noisy fields and generate filters
βοΈ Configuration
fmp auto-discovers configuration from .fmp.yaml, .fmp.yml, or .github/fmp.yaml.
Example .fmp.yaml:
paths:
- clusters/kube
recursive: true
helm: true
resolve-git: true
sort: true
exclude-crds: true
filters:
- kind: FieldNormalizer
match:
kind: Secret
fieldPaths:
- path: [data, tls.crt]
action: replace
placeholder: "<<auto-generated>>"
Note: In diff mode, configuration is loaded from the current worktree so that local config changes take immediate effect.
π GitHub Action
Use fmp in your CI/CD pipelines to review PRs automatically.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for git-aware diffing
- uses: tobiash/flux-manifest-preview@main
with:
repo: .
base-ref: origin/main
resolve-git: true
| Input |
Description |
Default |
repo |
Path to the repo checkout (must be a git worktree) |
. |
base-ref |
Git ref to diff against |
origin/main |
base-sha |
Exact SHA to diff against (overrides base-ref) |
|
paths |
Directories to render (newline-separated) |
|
recursive |
Recursively discover paths |
false |
helm |
Enable Helm rendering |
true |
resolve-git |
Clone external GitRepository sources |
false |
sort |
Sort output for deterministic diffs |
false |
exclude-crds |
Strip CRDs from output |
false |
helm-release |
Filter diff to a specific HelmRelease |
|
config |
Explicit path to .fmp.yaml |
auto-discovered |
filter-file |
KIO filter definition file |
|
filter-yaml |
Raw KIO filters YAML |
|
write-summary |
Write a step summary |
true |
comment |
Post/update a sticky PR comment |
false |
comment-mode |
When to comment (changes, always, failure) |
changes |
max-inline-diff-bytes |
Max diff bytes to inline |
50000 |
export-dir |
Export rendered manifests directory |
|
export-changed-only |
Only export changed manifests |
false |
fail-on-warning |
Fail the step on warnings |
false |
fail-on-error |
Fail the step on errors |
true |
Outputs
| Output |
Description |
status |
Overall status: clean, changed, warning, error |
changed |
Whether manifest changes were detected |
warnings-count |
Number of warnings |
errors-count |
Number of errors |
resources-added |
Added resources |
resources-modified |
Modified resources |
resources-deleted |
Deleted resources |
resources-total |
Total changed resources |
diff-bytes |
Size of the full diff |
diff-truncated |
Whether the inline diff was truncated |
diff-file |
Path to the full diff file |
summary-file |
Path to the summary markdown |
comment-file |
Path to the comment markdown |
report-file |
Path to the structured JSON report |
export-dir |
Directory where manifests were exported |
Examples
Opt-in sticky PR comment:
- uses: tobiash/flux-manifest-preview@main
with:
repo: .
base-ref: origin/main
comment: true
comment-mode: changes
Export for downstream validation:
- uses: tobiash/flux-manifest-preview@main
with:
repo: .
base-ref: origin/main
export-dir: ./rendered
export-changed-only: true
- name: Validate with kubeconform
run: kubeconform ./rendered/*.yaml
Note: sops-decrypt is intentionally unsupported in the GitHub Action to avoid leaking decrypted content into logs, summaries, comments, or artifacts.
π§ͺ Development
Run the test suite and linter:
go test ./...
go vet ./...