feat(diff): add dash0 diff command - #256
Draft
mmanciop wants to merge 3 commits into
Draft
Conversation
mmanciop
added a commit
that referenced
this pull request
Aug 17, 2026
New experimental `dash0 diff -f <file|directory> [--since <ref>]` command
previews what `apply` would do without ever creating, updating, or deleting
anything:
- Fetches each document's current state from Dash0 (per-kind, non-mutating)
to accurately distinguish create from update, unlike `apply --dry-run`,
which is local-only and can't tell the two apart.
- All-or-nothing fetch gate: any document fetch failure (other than a plain
"not found") aborts the whole plan before anything is printed.
- `--since <ref>` reuses apply's identifier-diffing to preview deletions
alongside creates/updates, never deleting anything regardless of
confirmation.
- Three-way exit code (0 clean, 1 differences pending, 2 error), modeled on
`kubectl diff` — a deliberate, narrow exception to this CLI's uniform 0/1
convention.
- Human-mode unified-diff report and agent-mode JSON output matching
`apply --dry-run`'s {path, changes} shape, extended with a "create" op.
Supporting changes:
- Move apply --since's git-diffing plan (deletionPlan) into
internal/git as the exported SincePlan/ComputeSincePlan, so diff can
reuse it without depending on internal/apply.
- Move apply's document validation (validateDocuments) and PrometheusRule
CRD parsing into internal/asset as ValidateDocuments/ParsePrometheusRuleCRD,
for the same reason.
- Fix a real cobra Traverse bug in cmd/dash0/main.go: a boolean persistent
flag preceding the subcommand (e.g. `dash0 --experimental diff ...`, the
form used throughout this CLI's docs) was misresolved to the root command
because Traverse's flag lookup doesn't see PersistentFlags() until cobra's
own lazy merge runs during Execute. This silently broke diff's exit code
(always falling back to 1 instead of 2 on a genuine error) for that
invocation order.
- Deprecate `apply --dry-run` in favor of `dash0 diff`, with a runtime
stderr warning and updated help text.
References #256.
mmanciop
force-pushed
the
feat/diff-command
branch
from
August 17, 2026 15:23
05afc15 to
028a3ac
Compare
mmanciop
marked this pull request as draft
August 17, 2026 15:34
Replace the naive textual YAML comparison in internal/asset/diff.go
(HasDifference/PrintDiff) with dash0-api-client-go/yaml's new
Equivalent/Normalize functions, so dash0 diff (and apply/dashboards
update, which share PrintDiff) stop misreporting drift from purely
cosmetic differences: key/slice ordering, duration-string formatting
("2m" vs "2m0s"), int-vs-float representation, and API-populated
defaults absent from the local document.
Adds a per-kind semanticCompareConfig table (preserved annotation keys,
extra ignored fields, and -- for CheckRule specifically -- the
AnnotationsRoot/AnnotationsUnfiltered options the flat, non-CRD-shaped
PrometheusAlertRule type needs) and wires it into both the equivalence
check and the rendered diff, which is now built from normalized YAML
instead of the raw stripped YAML.
Depends on dash0hq/dash0-api-client-go#32 (not yet merged/released;
developed against the existing local `replace` directive in go.mod,
matching this repo's established pattern for in-flight client-library
changes).
dash0hq/dash0-api-client-go#32 regenerates generated.go against the current upstream OpenAPI spec, which drops SamplingMode's bare Adaptive/Disabled aliases in favor of the type-prefixed SamplingModeAdaptive/SamplingModeDisabled (already generated side-by-side since v1.17.0, per that repo's api_compatibility_exceptions.txt). Needed to keep this repo building against the local `replace` directive while that PR is in flight.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
dash0 diff -f <file|directory> [--since <ref>]command previews whatapplywould do (creates, updates, and — with--since— deletions), without ever mutating anything.apply --dry-run, which is local-only and cannot tell the two apart.--since <ref>reusesapply --since's identifier-diffing to preview deletions alongside creates/updates, never deleting anything.0clean,1differences pending,2error), modeled onkubectl diff— a deliberate, narrow exception to this CLI's uniform 0/1 convention.apply --dry-run's{path, changes}shape, extended with a"create"op.apply --dry-runis now deprecated in favor ofdash0 diff, with a runtime stderr warning and updated help text.Semantic comparison engine
The comparison behind
diff(andapply/dashboards update's diff rendering, since they shareinternal/asset.PrintDiff) is semantic, not textual. It's backed by a new shared engine indash0hq/dash0-api-client-go#32— ported fromterraform-provider-dash0's existinginternal/converter(used across all 8 of its resource types today), rather than reimplementing the same logic separately.This closes real gaps a naive text diff has: key/slice reordering, duration-string formatting (
"2m"vs"2m0s"), int-vs-float representation differences between YAML and JSON, API-populated defaults absent from the local document, and (for check rules specifically) the default annotation values the Dash0 JSON → Prometheus YAML conversion omits by default. None of these are reported as changes anymore, and the printed diff itself is now built from normalized YAML so it isn't cluttered by them either.Note: this PR currently depends on
dash0-api-client-go#32, which is open but not yet merged/released — developed against this repo's existing localreplacedirective ingo.mod(an established pattern here for in-flight client-library changes). Thereplacedirective will be removed andgo.modbumped to a real released version before this is ready to merge.Supporting changes
apply --since's git-diffing plan (deletionPlan) intointernal/gitas the exportedSincePlan/ComputeSincePlan, sodiffcan reuse it without depending oninternal/apply.apply's document validation (validateDocuments) and PrometheusRule CRD parsing intointernal/assetasValidateDocuments/ParsePrometheusRuleCRD, for the same reason.Traversebug incmd/dash0/main.go: a boolean persistent flag preceding the subcommand (e.g.dash0 --experimental diff ..., the form used throughout this CLI's own docs) was misresolved to the root command, becauseTraverse's flag lookup doesn't seePersistentFlags()until cobra's own lazy merge runs duringExecute. This silently brokediff's exit code (always falling back to1instead of2on a genuine error) for that invocation order. Fixed by merging persistent flags into the root command's own flag set before the pre-flightTraversecall; regression test included (TestTraverseTargetCommand/TestTraverseTargetCommand_ReproducesBugWithoutFix).Why this is stacked
This PR targets
refactor/shared-document-model(#255), which extracted the shared document model bothapplyanddiffneed.Test plan
go build ./...go vet ./...go test ./...go test -tags=integration ./...make lintmake skill-validatemake chlog-validatedash0 --experimental diff -f <fixture>for create/update/clean/error cases, exit codes 0/1/2 confirmed with both-X-before and-X-after subcommand ordering.sharingannotation key check rules use, custom check-rule labels, and notification channels'spec.routing.assets.