apply, diff & prune

pngr apply -f stack.yaml reconciles the active org to match the file.

the pipeline

Every apply runs five steps:

  1. Parse + interpolate. Load the YAML, expand ${ENV_VAR}, validate against the v1 schema.
  2. Resolve refs. Verify every monitor/channel name a rule references exists in the same file. A missing reference fails the whole apply with one error listing every unresolved name.
  3. Diff vs current state. The server returns the current org snapshot; the client computes create | update | delete | no-op per resource. Updates are field-level — only changed fields are sent, so untouched fields stay untouched.
  4. Preview + confirm. Print the changeset as a kubectl-style summary and wait for confirmation.
  5. Execute. Apply in dependency order — channels, then monitors, then rules — so a rule can reference resources the same apply just created.

diff and dry-run

Preview without mutating anything:

pngr apply --dry-run -f stack.yaml   # full diff; exits non-zero if there would be changes
pngr diff -f stack.yaml              # alias with tighter output, pre-commit friendly

--dry-run exits 0 when there are no changes and non-zero when there would be — so it doubles as a CI guard ("the PR must include the apply preview" / "main must be in sync").

On the /stack page, preview changes is the browser equivalent: it runs the dry-run and renders the changeset with a create / update / delete / no-op chip per resource before you confirm.

confirming and CI

In an interactive run, apply waits for you to confirm the changeset. In CI, skip the prompt:

pngr apply -f stack.yaml -y          # --yes; no prompt

prune

By default apply is additive — a resource that exists in the org but not in the file is left alone (no-op). Deletion is opt-in:

pngr apply -f stack.yaml --prune                 # delete everything not in the file
pngr apply -f stack.yaml --prune=monitors,rules  # only the listed kinds
warning

Destructive-by-default is the classic IaC footgun, so pngr refuses it. --prune is the only way to delete via apply. Pruning a monitor cascades to its incidents (per the soft-delete policy); pruning a channel that a rule still references fails the apply with a clear error rather than leaving a dangling reference.

failure behavior

There's no transactional rollback in v1. If a resource fails mid-apply, you get a partial-success report: the resources that applied stay applied, and the failed ones are listed with their error. Re-running after fixing the cause is safe — apply is idempotent against the current state.

drift

Each apply is stateless — it diffs the file against the live org and nothing else. If a teammate edited a monitor in the UI between two applies, the next apply reverts that edit, because the file is the source of truth. Both the UI edit and the apply override show up in the audit log, so it's never a silent overwrite. Running pngr diff (the dry-run above) before each apply is the recommended way to catch drift early.