Pretty-Printing JSON in CI Logs — Readability Without Leaks
CI pipelines that dump raw JSON logs are unreadable; pretty-printing everything risks leaking secrets. Safe formatting practices for build logs and debug output.
By Vertex Solutions Editorial
A failed deploy printed 4,000 lines of minified JSON — one line, no breaks. The engineer missed "error": "invalid_client" buried at column 9,000. Next pipeline added jq '.' everywhere. The following week, a public GitHub Actions log showed a full OAuth token in a pretty-printed response body.
Readable logs help until they become readable leaks.
Quick answer
A failed deploy printed 4,000 lines of minified JSON — one line, no breaks. The engineer missed "error": "invalid_client" buried at column 9,000. Next pipeline added jq '.' everywhere. The following week, a public GitHub Actions log showed a full OAuth token in a pretty-printed response body.
Why CI JSON is painful
Build systems capture:
- API health check responses
- Terraform plan JSON
- Test report aggregates
- npm audit output
- Deployment webhook payloads
Tools emit compact JSON by default. Humans scrolling GitHub Actions or GitLab CI need indentation — but pipelines also run in shared, sometimes public environments.
Pretty-print mechanics
jq (shell pipelines)
curl -s https://api.example.com/status | jq '.'
Select fields instead of full dump:
jq '{status: .status, version: .version}'
Node / JavaScript
console.log(JSON.stringify(payload, null, 2));
Use the JSON Formatter locally to prototype output shape before wiring CI — pair with JSON Validator on fixtures.
Python
import json
print(json.dumps(data, indent=2, sort_keys=True))
For formatting philosophy and common mistakes, see JSON Formatting Guide and Common JSON Formatting Errors.
Safe pretty-print rules
1. Redact before indent
Maintain a denylist of keys:
authorization, token, api_key, password, secret, cookie
Replace values with [REDACTED] recursively. Tools like jq support walking with filters; custom scripts should handle nested objects.
2. Truncate large arrays
Log items[0:3] and "... 47 more" instead of full inventory dumps. Size caps prevent log platform rate limits too.
3. Pretty-print artifacts, not streams
Write full formatted JSON to CI artifacts (downloadable, access-controlled). Keep console to summary lines:
Test report: 142 passed, 3 failed — see artifacts/report.json
4. Separate public vs private workflows
Fork PRs on public repos run with restricted secrets. Don't pretty-print env files in PR logs — even redaction can miss novel key names.
5. Fail on parse errors
jq empty < response.json || exit 1
Invalid JSON in a "success" step hides integration breakage.
JSON vs JSONL in pipelines
| Format | CI console | Log aggregator | | --- | --- | --- | | Pretty JSON | Human debugging | Poor per-line search | | Compact JSON | One line OK | Better for grep | | JSONL | One event per line | Ideal for Datadog/Splunk |
For streaming build events, JSONL wins. For one-shot API failure inspection, pretty JSON wins — redacted.
Read JSON vs JSONL when choosing export formats for test output.
Structured logging without full dumps
Instead of printing entire webhook bodies:
{
"event": "deploy_failed",
"status": 422,
"error_code": "INVALID_IMAGE",
"request_id": "req_abc123"
}
One line, grep-friendly, no secrets. Save full body to artifact if engineers need depth.
Local vs CI parity
Developers pretty-print locally with browser tools and formatters. CI should use the same jq filters checked into repo (scripts/format-healthcheck.sh) so "works on my machine" matches pipeline output.
Troubleshooting
Should I pretty-print all JSON in CI logs? Not unconditionally. Pretty-printing large API responses or config dumps bloats logs, slows pipelines, and may print secrets. Pretty-print small debug artifacts; summarize or redact large payloads.
How do I pretty-print JSON in a shell script? Pipe to jq with '.' for formatting: cat response.json | jq '.'. In Node, JSON.stringify(obj, null, 2). Ensure jq failures don't mask the original error.
Can CI logs expose API keys in JSON? Yes. Environment variables, OAuth responses, and error bodies often contain tokens. Redact known key names (authorization, api_key, password) before logging. Never echo full process.env in public CI.
Limitations
Browser-based workflows for pretty-printing json in ci logs depend on file size, browser memory, and how the source file was created. Very large files, password-protected inputs, or unusual encodings may fail without a desktop alternative. Always keep an original copy before batch processing.
When not to use this approach
Skip browser-only processing when compliance requires audit logs, when files exceed practical browser limits, or when you need features your browser tool does not expose (bookmarks, form fields, digital signatures). In those cases, use dedicated desktop software or an approved enterprise pipeline.
Related tools
Conclusion
Pretty-print JSON in CI to read failures faster — not to dump entire authenticated responses to shared logs.
Redact, truncate, artifact the rest. Validate JSON before formatting. When the token would have appeared on line 47 of a indented block, you'll be glad you masked it on line 1.
GitHub Actions vs GitLab CI patterns
GitHub Actions public repos: assume logs are world-readable. Use ::add-mask:: for secrets and never echo ${{ secrets.* }} in debug steps. GitLab CI job artifacts for JSON reports with expire_in: 7 days and restricted visibility.
Fork PR workflows should not receive production secrets — mock API responses in CI fixtures instead of live authenticated calls that would pretty-print real tokens.
jq recipes for CI
Extract error code only:
jq -r '.error.code // "UNKNOWN"' response.json
Validate array length before full print:
count=$(jq '.items | length' data.json)
if [ "$count" -gt 50 ]; then jq '.items[:10]' data.json; else jq '.' data.json; fi
On-call handoff
When paging engineers at 3 AM, attach redacted pretty JSON artifact — not raw Slack paste of 8k lines. Train on-call to use artifact download links in incident tickets.
Putting this into practice this week
Pick one workflow from this article and run it on a real task today — not a hypothetical. If the guide covers PDF export, export one document you already need for work. If it covers image naming, rename one messy folder. Knowledge retained from doing beats knowledge retained from reading.
Questions to ask before you delegate
When handing a process to a teammate or virtual assistant, ask: "What would break if you skipped step three?" If they can't answer, the process isn't documented enough. Add the missing step to your internal wiki with a link to this guide and the relevant tool page.
How this connects to the broader site
Utility-first sites win when guides and tools reinforce each other. Bookmark the tool URL alongside this article. Share the article link when onboarding someone who'll use the tool weekly — context reduces support messages asking the same formatting question twice.
Common "it worked yesterday" causes
Software updates change export defaults. Browser updates change PDF print behavior. CDN cache serves old image after you uploaded new asset. When workflows break without code changes, check version changelogs before blaming user error. First troubleshooting step: reproduce in clean browser profile with extensions disabled.
When to escalate to a specialist
Tax, legal, medical, and enterprise security topics in adjacent guides sometimes require professional advice. Articles like this explain operational literacy — not professional services. Escalate when stakes exceed convenience (court filing, audit response, M&A data room, HIPAA-covered PHI).
Frequently Asked Questions
Common questions answered to help you get the most from this tool.