## Why
The unit tests stopped compiling after the `--pm` → `-p`/`-i` match-modifier refactor was left uncommitted, there was no RPM/completions distribution story, and invoking the tool without a TTY against an empty pipe silently returned nothing. This makes the project releasable and safe to run from agents/CI.
## Changes
- Make stdin handling robust: replace the fragile `!isTerminal` check with `stdinReader()`, which only reads node names when stdin is a real pipe/redirect carrying data. Terminals, `/dev/null`, and empty/closed pipes now fall through to a normal query, so running without a TTY behaves like an interactive run.
- Repair and expand `main_test.go` to match the current `buildQuery`/`run` signatures; add coverage for the match modifiers, all output modes, config precedence, and the new `stdinReader` logic. `httptest` stubs PuppetDB (no live deps).
- Add nfpm packaging (`packaging/nfpm.yaml`, `scripts/build-rpm.sh`): installs the binary to `/usr/bin/node-lookup` and bundles generated bash/zsh/fish completions under the standard system paths.
- Rework the Makefile to build into `dist/` and add `completions`/`rpm` targets.
- Split PR CI into `build`, `test`, and `pre-commit` workflows and extend `release` to build the RPM and `PUT` it to the artifactapi `rpm-internal` repo. Every step sets a `serviceAccount` and k8s resources.
The project directory has also been relocated under `prodenv`.
Reviewed-on: #13
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
Passing tag both as argument and --tag flag causes ambiguous args error.
💘 Generated with Crush
Assisted-by: Claude Sonnet 4.6 via Crush <crush@charm.land>
Reviewed-on: #12
Change to only tagging with the makefile.
Change the workflow to create the release based on the tag.
Build the binary for multiple os/archs
Reviewed-on: #11
droneci user lacks write access; switch to token-based auth header.
💘 Generated with Crush
Assisted-by: Claude Sonnet 4.6 via Crush <crush@charm.land>
Reviewed-on: #7
tea creates the release before the pipeline runs; POST was failing with
conflict, leaving RELEASE_ID empty and skipping the asset upload.
Now GETs the release by tag, PATCHes its body, then uploads the binary.
💘 Generated with Crush
Assisted-by: Claude Sonnet 4.6 via Crush <crush@charm.land>
Reviewed-on: #6
Capture and print the full Gitea API response before parsing the release
ID, and fail explicitly if the ID is empty so the root cause is visible
in CI logs instead of silently producing a malformed asset upload URL.
💘 Generated with Crush
Assisted-by: Claude Sonnet 4.6 via Crush <crush@charm.land>
Reviewed-on: #5