28 Commits

Author SHA1 Message Date
benvin f169d82c2c Merge pull request 'ci: use container-rpmbuilder image' (#4) from benvin/rpmbuilder-image into main
Reviewed-on: #4
2026-10-05 21:34:23 +11:00
unkin-agent 5c899b12b5 ci: use container-rpmbuilder image
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
2026-10-05 14:39:44 +11:00
benvin b81b49d006 Merge pull request 'Report fact records dropped from the estate table' (#3) from benvin/report-dropped-fact-records into main
Reviewed-on: #3
2026-09-12 20:33:58 +10:00
unkin-agent 04ec9e6d41 carry dropped fact records through the failure path and count them
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Report the accumulated warnings on stderr when the estate load fails, and fold
the dropped-record tally into the error. Count records rather than warning
messages in --explain, by carrying the count on the Warn hook.
2026-09-12 20:27:55 +10:00
unkin-agent 88bbc2f441 check the stderr writes errcheck now sees
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
2026-09-12 20:12:12 +10:00
unkin-agent 86e4958bcb report fact records dropped from the estate table
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline was successful
catalog-impact built its PuppetDB client without a Warn hook, so a host whose
fact records all failed to decode vanished from the estate table with no
warning on any output path.

- wire catalog-impact's Warn hook into NodeWarnings
- default an unset Warn to stderr so a dropped record is never silent
- thread stderr through run() instead of writing os.Stderr directly
- count dropped fact records in the explain resolution-incomplete line
2026-09-12 20:09:52 +10:00
benvin bdc8f51994 Merge pull request 'add the catalog-impact binary' (#2) from benvin/catalog-impact into main
Reviewed-on: #2
2026-09-12 18:19:04 +10:00
benvin bd1ed2efb2 Merge pull request 'Add repo scaffold and the catalog-diff CLI' (#1) from benvin/scaffold-catalog-diff into main
Reviewed-on: #1
2026-09-12 18:18:20 +10:00
unkin-agent a5f27348ae merge benvin/scaffold-catalog-diff into benvin/catalog-impact
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Move FactsByName onto the renamed puppetdb client and share the facts
query and record decoding with the single-node fetch.
2026-09-12 18:02:00 +10:00
unkin-agent ae948c7f04 track the opening quote and scan interpolations as code
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
A differently quoted substring inside a ${...} interpolation ended the
outer string early and truncated the argument list, dropping every name
after it. One shared walker now backs every source scan.

Lowercase the recovered prefix of an unresolved reference, and every
class name as it is added, so a mixed-case interpolated name still
widens.

Report fact records with no certname instead of dropping them, and
assert stripSource keeps newline positions rather than just length.
2026-09-12 17:54:03 +10:00
unkin-agent 3f14554fae read facts from PuppetDB's query API
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
- rename internal/pdbmux to internal/puppetdb
- fetch facts with one GET /pdb/query/v4/facts AST query per node
- drop the per-node fallback route and its two response shapes
- rename --pdb to --puppetdb, CATALOG_DIFF_PDB to CATALOG_DIFF_PUPPETDB and
  pdb_url to puppetdb_url
- describe the fact source generically in the README and AGENTS.md
2026-09-12 17:49:57 +10:00
unkin-agent 5cbe4c8713 stop serving another node's factset
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Also strip a leading BOM and stop reporting a certname mismatch as a parse error.
2026-09-12 17:35:09 +10:00
unkin-agent f34dacc818 merge benvin/scaffold-catalog-diff into benvin/catalog-impact
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
2026-09-12 17:25:54 +10:00
unkin-agent 496f258cb0 make the catalog fixture synthetic
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
The capture carried a production certname, real role and class names and
internal paths into a public repo.

- replace hostnames, class names and paths with fake equivalents
- keep the shape under test: catalog envelope, string version, null
  code_id, resources with and without parameters and file/line, the
  exported and sensitive_parameters cases
- document the range of --retry and --timeout
2026-09-12 17:19:28 +10:00
unkin-agent 7f2c6f16c8 accept both factset shapes and skip undecodable facts
Real PuppetDB answers /factsets/<certname> with an array; the fallback
decoded a bare object, so it only worked against pdbmux's own divergent
response.

- decode an array of factsets, picking the requested certname
- keep accepting a single bare factset object
- drop and report a fact record that will not decode instead of failing
  the whole fetch
- fail only when nothing in the response decodes
2026-09-12 17:19:28 +10:00
unkin-agent 6e4ee54203 validate flag ranges and make exitError printable when empty
A negative --retry skipped the compile loop, leaving a nil error inside
exitError that panicked when printed.

- reject a negative or oversized --retry and a non-positive --timeout as
  usage errors (exit 3)
- print an exit code when exitError carries no inner error
- cap the backoff shift so a large --retry cannot overflow
- cancel the sibling compile on the first failure, and do not report that
  cancellation as the cause
- report a context cancellation during the retry backoff instead of the
  stale compile error
2026-09-12 17:19:28 +10:00
unkin-agent c4d3ed24a9 report unresolved class references instead of resolving to silence
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
- walk the classes holding an unresolved reference when tracing any class
  it could have named, so a dropped edge cannot lose hosts
- list unresolved references in --explain, in unresolved_references in
  --json and on stderr, and flag summary.resolution_incomplete
- name an ordering reference as such in the --explain chain
2026-09-12 17:19:02 +10:00
unkin-agent 1c1df7f953 strip source quote-aware and resolve dynamic class references
- strip # comments with quote-state tracking so a hash in a string no
  longer truncates the line
- skip heredoc bodies in every @(EOT) form so documentation text is not
  indexed as a class reference
- take every literal name out of a selector, following a bare variable
  through the assignments in its own file
- record a class reference that stays unresolved against its file, with
  any literal prefix, instead of dropping it
- read a class name case insensitively in a title or type reference
- tag each edge as a declaration or an ordering reference
2026-09-12 17:18:56 +10:00
unkin-agent 1aea8e8dbf assert line 0 with a file counts as a real source location
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
2026-09-12 17:00:41 +10:00
unkin-agent a76480d454 unwrap the catalog response and classify failures correctly
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
- unwrap the {"catalog": ...} envelope, still accepting a bare catalog
- report an environment-less response as a protocol mismatch, not an ENC problem
- make Resource.Line a pointer and Resource.Params() map absent onto empty
- render a missing manifest location as "(source unknown)"
- retry compile failures caused by the compiler's PuppetDB query
- stop retrying manifest errors the compiler returns as HTTP 500
- add a trimmed real-server response fixture and tests for each shape
2026-09-12 16:58:59 +10:00
unkin-agent 6551ab9f13 ship every cmd binary in the release
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Take the binary list from cmd/ in the Makefile, the RPM packaging and the
release pipeline so a new tool ships without a pipeline edit.
2026-09-12 16:46:51 +10:00
unkin-agent 2e2562018f index every name in an include list
include/contain/require take a list of names; parse the argument list so
the second and later names are indexed too.
2026-09-12 16:46:51 +10:00
unkin-agent 9ff9edefa8 report changed files that reach no host
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
A hieradata file for a role with no members produces an empty host list, which
is indistinguishable from a mapping failure.

- list files that mapped cleanly but selected nobody in --explain
2026-09-12 16:26:29 +10:00
unkin-agent 9919676836 catch four more class reference forms
ci/woodpecker/pr/pre-commit Pipeline was canceled
ci/woodpecker/pr/build Pipeline was canceled
ci/woodpecker/pr/test Pipeline was canceled
A params.pp is only ever reached by inherits and $class::var, so changing one
resolved to no hosts at all.

- index inherits, $class::var reads and create_resources()
- match a defined type declared part-way along a line
2026-09-12 16:22:27 +10:00
unkin-agent 8093933500 add the catalog-impact binary
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Work out which hosts a puppet-prod change can affect, so a catalog test can
fan out over exactly those hosts instead of the whole estate.

- add cmd/catalog-impact and internal/impact
- map hieradata paths onto fact selectors from the hiera hierarchy
- trace manifest classes back to role classes through include, contain,
  class {} and hiera_include, to a fixed point
- fetch the estate fact table from pdbmux in one query via FactsByName
- widen to all hosts, loudly, for any path that matches no rule
- ship the binary and its completions in the RPM
2026-09-12 16:15:00 +10:00
unkin-agent dcbd810c34 keep stderr quiet when the diff exits with differences
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
2026-09-12 15:55:34 +10:00
unkin-agent 53007a9257 add repo scaffold and the catalog-diff CLI
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was canceled
ci/woodpecker/pr/test Pipeline was canceled
Compile a host's catalog in a base and a test environment over the
puppetserver API, then diff the two.

- add catalog-diff CLI with cobra flags, config precedence and exit codes
- add puppetserver mTLS client for POST /puppet/v4/catalog
- add pdbmux fact client
- add catalog normalisation, diff engine and text/JSON renderers
- add Makefile, nfpm RPM packaging and woodpecker pipelines
2026-09-12 15:54:25 +10:00
gitadmin 59c4d9a405 Initial commit 2026-09-12 15:35:49 +10:00