Skip to content

feat: run summary report of terraform plan changes and step errors - #83

Merged
aksmo merged 2 commits into
mainfrom
feat/run-report
Sep 19, 2026
Merged

aksmo merged 2 commits into
mainfrom
feat/run-report

Conversation

@aksmo

@aksmo aksmo commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Add a run summary report (plan changes + step errors)

Problem

When runiac runs as a Docker-based GitHub Action, the only output is the container's stdout, streamed into the job log. To find the terraform plan or the reason a step failed, you have to scroll the entire log — the plan and errors are interleaved with everything else and there's no machine-readable artifact. There's no easy "what changed / what broke" view.

What this PR does

Adds a first-class run summary that runiac produces at the end of a deploy, without changing any existing output or exit behavior.

  • Per-step plan capture — the terraform plugin already parses terraform show -json into grouped resource changes; this now stores them on the step output (StepOutput.PlanResourceChanges).
  • New pkg/reporting package — renders a RunReport (per-step status, error, and plan change counts) into:
    • a Markdown summary that is echoed to stdout at the end of every run (scroll once to the bottom), and
    • summary.json + summary.md written to RUNIAC_OUTPUT_DIR when that env var is set (for CI artifact upload / $GITHUB_STEP_SUMMARY).
  • main.go wiring — collects per-step results in the existing summary loop and calls the reporter. Includes a panic-safe statusString (the existing DeployResult.String() indexes a 4-element array and would panic on Na).
  • CLI convenience (runiac deploy, container-exec mode) — bind-mounts <project>/.runiac/report to /runiac/report and defaults RUNIAC_OUTPUT_DIR to it (unless the caller set one), so the report is available on the host with zero configuration (locally and in CI).

Example (stdout, end of run)

## runiac run summary

❌ **FAIL** — Executed 8/9 steps successfully with 0 test failure(s) across 11 track(s).  Failed: net/vnet/primary/eastus2.

| Track | Step | Region | Status | Changes |
| --- | --- | --- | --- | --- |
| storage | account | primary/eastus2 | ✅ SUCCESS | +2 ~1 -0 |
| net | vnet | primary/eastus2 | ❌ FAIL | — |

### Errors

<details><summary>net / vnet / primary/eastus2</summary>

Error: subnet overlaps existing range

</details>

Backward compatibility (non-breaking)

  • Additive struct field — StepOutput.PlanResourceChanges is new; no existing field changed.
  • Best-effort writer — any IO error is logged and swallowed; reporting never changes a run's outcome or exit code.
  • Opt-in file output — files are only written when RUNIAC_OUTPUT_DIR is set (the CLI sets a default only in container-exec mode, into the gitignored .runiac/); the default library behavior just adds a stdout summary block.
  • Existing logs untouched — the plan/resource log lines and the Executed X/Y … summary line are unchanged; the report is purely additive.
  • CLI mount is additive — one extra bind mount + a defaulted env var (only when unset); explicit RUNIAC_OUTPUT_DIR still wins.

Tests

  • pkg/reporting/report_test.go — change tally (+create ~update -delete, replace, no-op), Markdown rendering (table + collapsible errors; success has no error section), Write (no dir = nothing written; with dir = valid JSON + MD), deterministic step sorting.
  • cmd/runiac/main_test.go — statusString mapping incl. the Na non-panic guard.
  • cmd/cli/cmd/deploy_test.go — defaultReportOutputDir (default injected when unset/whitespace, preserved when caller-provided).
  • Verified: go build ./..., go vet, gofmt, and existing pkg/config / plugins/terraform / cmd/cli tests all pass.

Consuming the report in CI

Set RUNIAC_OUTPUT_DIR (or use the container-exec default at .runiac/report), then append summary.md to $GITHUB_STEP_SUMMARY and upload the directory as an artifact — full logs remain available for deep triage.

Capture terraform plan changes per step and render a run summary as Markdown
(echoed to stdout at the end of a run) plus summary.json/summary.md when
RUNIAC_OUTPUT_DIR is set. Additive and best-effort: file output is opt-in,
writer failures are logged not fatal, and exit codes and existing logs are
unchanged.
…r-exec

Bind-mount <project>/.runiac/report to /runiac/report and default
RUNIAC_OUTPUT_DIR to it unless the caller set one, so the run report is
available on the host without coupling to the tfstate mount.
@github-actions

Copy link
Copy Markdown

Test Results

72 tests   72 ✅  0s ⏱️
16 suites   0 💤
 1 files     0 ❌

Results for commit 3c1954f.

@aksmo
aksmo merged commit e4fc697 into main Sep 19, 2026
7 checks passed
@aksmo
aksmo deleted the feat/run-report branch September 19, 2026 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants