Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version-file: go.mod
- name: Cache
uses: actions/cache@v2
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
cache-dependency-path: go.sum
- name: Test
run: go test -v ./... -coverprofile=coverage.out -covermode=atomic -bench=./...
36 changes: 30 additions & 6 deletions clireporter/prefixedwriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package clireporter

import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"hash/fnv"
Expand All @@ -28,9 +29,11 @@ func newLogger(w io.Writer) *logger {
}

func (l *logger) SetSeparator(separator string) { l.separator = separator }

func (l *logger) Write(t *taskrunner.Task, msg string) {
l.writers[t].Write([]byte(msg))
}

func (l *logger) Writef(t *taskrunner.Task, format string, v ...interface{}) {
l.Write(t, fmt.Sprintf(format, v...))
}
Expand Down Expand Up @@ -76,6 +79,20 @@ var colors = []color.Attribute{

var defaultPadding = 16

// isLikelyJSON checks if the input appears to be JSON by looking at the first non-whitespace character.
func isLikelyJSON(data []byte) bool {
// Trim whitespace to get the first meaningful character.
trimmed := strings.TrimSpace(string(data))
if len(trimmed) == 0 {
return false
}

first := trimmed[0]
// JSON objects start with {, arrays with [, strings with ", and we'll be conservative
// and only format these as JSON. Standalone numbers, booleans, null shouldn't be reformatted.
return first == '{' || first == '[' || first == '"'
}

func (w *PrefixedWriter) Write(p []byte) (n int, err error) {
separator := w.Separator
if separator == "" {
Expand All @@ -90,13 +107,20 @@ func (w *PrefixedWriter) Write(p []byte) (n int, err error) {
// change.
// The writer expects us to return the original length of p.
origLen := len(p)
var jsonObj interface{}
err = json.Unmarshal([]byte(p), &jsonObj)
if err == nil {
jsonData, err := json.MarshalIndent(jsonObj, "", " ")

// Only attempt JSON parsing if the input looks like JSON (objects, arrays, strings).
if isLikelyJSON(p) {
// Use json.Decoder with UseNumber() to preserve large integer precision.
decoder := json.NewDecoder(bytes.NewReader(p))
decoder.UseNumber()
var jsonObj any
err = decoder.Decode(&jsonObj)
if err == nil {
// Treat output as indented JSON
p = jsonData
jsonData, err := json.MarshalIndent(jsonObj, "", " ")
if err == nil {
// Treat output as indented JSON
p = jsonData
}
}
}

Expand Down