Render, validate and diff Kubernetes manifests from a Flux CD GitOps repository, without a cluster. Point it at a cluster directory and it does what Flux would do on reconcile: builds every Kustomization, templates every HelmRelease, and gives you the resulting manifests to check, diff and post to a merge request.
The idea comes from flux-local. This is an independent Go implementation with a persistent Helm render cache, parallel processing of clusters and a native unified diff.
# every Kustomization builds, every HelmRelease templates
flux-tools test clusters/prod --enable-helm
# rendered manifests, one file per cluster
flux-tools build clusters/prod --enable-helmgo install github.com/alexandervidyaev/flux-tools/cmd/flux-tools@latestBinaries for linux/darwin, amd64/arm64 are on the releases page. A Docker image with every external tool inside:
docker run --rm -v "$PWD:/app" ghcr.io/alexandervidyaev/flux-tools:latest test clusters/prodThe binary itself needs kustomize, helm and git in PATH. kubeconform and yq only for the commands that wrap them.
flux-tools makes no assumptions about how the repository is organised.
- A directory with
flux-system/is a cluster, wherever it sits. The repository root is read from the flux-system Kustomization thatflux bootstrapwrote, sospec.pathresolves exactly as Flux resolves it. - No
flux-system/in git (flux-operator)? Name the entry directories, or mark them and pass--cluster-marker. - A directory without
kustomization.yamlis built the way kustomize-controller builds it, from a generated one.
flux-tools build clusters/ # every cluster under clusters/
flux-tools build operator/clusters/dev # flux-operator layoutDetails, including which GitRepository counts as "this repository", in docs/repository-layout.md.
A repository with thirty clusters is rendered thirty ways at once, not one after another. Every fan-out sits on one worker pool, so the behaviour and the flag are the same everywhere: -j bounds the workers, and the aggregation happens after the pool rather than under a mutex.
| Command | What is parallelised | Flag | Default |
|---|---|---|---|
build |
clusters | -j |
one worker per cluster, 0 for unbounded |
test |
clusters | --sequential forces one at a time |
10 workers, or one per cluster when there are fewer |
diff |
clusters | -j |
one worker per cluster |
helm-pull |
chart downloads, and cluster discovery before them | -j |
3 downloads, discovery capped at 10 |
yq |
files | -j |
one worker per CPU |
post-comment |
comments posted to the merge request | --workers |
3 |
Two caches make the repeat runs cheap on top of that: helm template output is cached across runs, keyed by a hash of every input, and kustomize build output is cached within a run, so a path rendered during discovery is not rendered again during the build.
helm-pull --verbose drops chart discovery to one worker, because interleaved output from several clusters is unreadable.
flux-tools test clusters/prod --enable-helm --junit-report report.xml
flux-tools build clusters/prod --enable-helm --skip-kind HelmRelease --output sliced --output-dir ./incoming
flux-tools kubeconform ./incoming -summary -ignore-missing-schemas --codequality-report gl-codequality.json
flux-tools diff ./current ./incoming -o ./diffs/ # ./current: the same build on the target branch
flux-tools post-comment ./diffs/ # summary + one comment per cluster in the GitLab MRThe full walkthrough, with caching between pipelines and the diff baseline for a new environment, is in docs/ci-pipeline.md.
| Command | What it does |
|---|---|
test |
Validate every Kustomization and HelmRelease of one or more clusters |
build |
Render every object of the given clusters at once, to YAML, JSON or a kubectl-slice compatible tree |
helm-pull |
Pre-download the charts the clusters use |
kubeconform |
Validate rendered manifests against JSON schemas, and turn the result into a GitLab Code Quality report |
yq |
Run yq over every rendered file in parallel, writing to cleaned/ instead of over the input |
diff |
Compare two build results, native unified diff, per-cluster reports |
post-comment |
Publish the diff to a GitLab merge request |
Every flag and default: docs/commands.md.
- Repository layout: entry directory, repository root, local and remote sources
- Command reference
- CI pipeline: the full flow, diff against the target branch
- Configuration: caches and environment variables
- Supported Flux features
- AGENTS.md: architecture and contribution rules
- CHANGELOG.md
post-commentfor GitHub pull requests.- A single
flux-tools cicommand: render, validate, slice and diff in one pass.