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
24 changes: 16 additions & 8 deletions cmd/kosli/getTrail.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,17 @@ func (o *getTrailOptions) printTrailAsMarkdown(raw string, out io.Writer, page i
if err != nil {
return err
}
sha := mdCell(commitInfo["sha1"])
sha := mdCell(stringOrNA(commitInfo["sha1"]))
if commitURL, ok := commitInfo["url"].(string); ok && commitURL != "" {
sha = fmt.Sprintf("[%s](%s)", sha, commitURL)
}
b.WriteString("\n### Git commit\n\n")
b.WriteString("| | |\n")
b.WriteString("| --- | --- |\n")
fmt.Fprintf(&b, "| Sha1 | %s |\n", sha)
fmt.Fprintf(&b, "| Author | %s |\n", mdCell(commitInfo["author"]))
fmt.Fprintf(&b, "| Author | %s |\n", mdCell(stringOrNA(commitInfo["author"])))
fmt.Fprintf(&b, "| Timestamp | %s |\n", mdCell(commitTimestamp))
fmt.Fprintf(&b, "| Message | %s |\n", mdCell(firstLine(commitInfo["message"])))
fmt.Fprintf(&b, "| Message | %s |\n", mdCell(stringOrNA(firstLine(commitInfo["message"]))))
Comment thread
tooky marked this conversation as resolved.
Resolved
}

writeAttestationStatuses(&b, trail["compliance_status"], trailURL)
Expand Down Expand Up @@ -368,17 +368,17 @@ func printTrailAsTable(raw string, out io.Writer, page int) error {
rows = append(rows, fmt.Sprintf("Last modified at:\t%s", lastModifiedAt))
if commitInfo, ok := trail["git_commit_info"].(map[string]any); ok {
rows = append(rows, "Git commit:\t")
rows = append(rows, fmt.Sprintf(" Sha1:\t%s", commitInfo["sha1"].(string)))
rows = append(rows, fmt.Sprintf(" Author:\t%s", commitInfo["author"].(string)))
commitTimestamp, err := formattedTimestamp(commitInfo["timestamp"].(float64), false)
rows = append(rows, fmt.Sprintf(" Sha1:\t%s", stringOrNA(commitInfo["sha1"])))
rows = append(rows, fmt.Sprintf(" Author:\t%s", stringOrNA(commitInfo["author"])))
Comment thread
tooky marked this conversation as resolved.
Resolved
commitTimestamp, err := formattedTimestamp(commitInfo["timestamp"], false)
if err != nil {
return err
}
rows = append(rows, fmt.Sprintf(" Timestamp:\t%s", commitTimestamp))
if url, ok := commitInfo["url"]; ok {
if url, ok := commitInfo["url"].(string); ok && url != "" {
rows = append(rows, fmt.Sprintf(" url:\t%s", url))
}
rows = append(rows, fmt.Sprintf(" message:\t%s", prefixEachLine(commitInfo["message"].(string), "\t")))
rows = append(rows, fmt.Sprintf(" message:\t%s", prefixEachLine(stringOrNA(commitInfo["message"]), "\t")))
}
rows = append(rows, "Events:\n")

Expand Down Expand Up @@ -508,3 +508,11 @@ func eventFields(event any) (trailEventFields, error) {
attestationRef: eventAttestationRef,
}, nil
}

// stringOrNA renders an optional string field, since commit info may carry only a sha1.
func stringOrNA(v any) string {
if s, ok := v.(string); ok && s != "" {
return s
}
return "N/A"
Comment thread
tooky marked this conversation as resolved.
Resolved
}
19 changes: 19 additions & 0 deletions cmd/kosli/getTrail_markdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,22 @@ func TestPrintTrailAsMarkdownEnvironmentLinks(t *testing.T) {
"artifact 'artifact' stopped running in ['prod-aws'](https://app.kosli.com/my-org/environments/prod-aws/)",
"without a snapshot index the link falls back to the environment page")
}

func TestPrintTrailAsMarkdownPartialCommitInfo(t *testing.T) {
t.Setenv("KOSLI_TESTS", "true")
global = &GlobalOpts{Host: "http://localhost:8001", Org: "docs-cmd-test-user-shared"}
o := &getTrailOptions{flowName: "get-trail"}
raw := `{"name": "t1", "compliance_state": "INCOMPLETE", "last_modified_at": 1452902400,
"git_commit_info": {"sha1": "abc1234def"}, "events": []}`

var buf bytes.Buffer
require.NoError(t, o.printTrailAsMarkdown(raw, &buf, 0))
require.Contains(t, buf.String(), "| Author | N/A |")
require.Contains(t, buf.String(), "| Message | N/A |")

missingSha := `{"name": "t1", "compliance_state": "INCOMPLETE", "last_modified_at": 1452902400,
"git_commit_info": {"author": "Jane <jane@example.com>"}, "events": []}`
buf.Reset()
require.NoError(t, o.printTrailAsMarkdown(missingSha, &buf, 0))
require.Contains(t, buf.String(), "| Sha1 | N/A |")
}
58 changes: 58 additions & 0 deletions cmd/kosli/getTrail_table_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"bytes"
"testing"

"github.com/stretchr/testify/require"
)

// TestPrintTrailAsTableCommitInfo checks that the table renderer tolerates
// commit info with only some of its fields, which the API accepts for trails.
func TestPrintTrailAsTableCommitInfo(t *testing.T) {
t.Setenv("KOSLI_TESTS", "true") // makes formattedTimestamp use a fixed time

for _, tc := range []struct {
name string
commitInfo string
want []string
notWant []string
}{
{
name: "only sha1",
commitInfo: `{"sha1": "abc1234def"}`,
want: []string{`Sha1:\s+abc1234def`, `Author:\s+N/A`, `Timestamp:\s+N/A`, `message:\s+N/A`},
Comment thread
tooky marked this conversation as resolved.
Resolved
},
{
name: "sha1 and branch",
commitInfo: `{"sha1": "abc1234def", "branch": "main"}`,
want: []string{"abc1234def", `Author:\s+N/A`, `Timestamp:\s+N/A`, `message:\s+N/A`},
},
{
// the server returns absent commit fields as explicit nulls
name: "only sha1 with null fields",
commitInfo: `{"sha1": "abc1234def", "message": null, "author": null, "branch": null, "timestamp": null, "url": null}`,
want: []string{`Sha1:\s+abc1234def`, `Author:\s+N/A`, `Timestamp:\s+N/A`, `message:\s+N/A`},
notWant: []string{"%!", "url:"},
},
{
name: "full commit info",
commitInfo: `{"sha1": "abc1234def", "author": "Jane <jane@example.com>", "timestamp": 1452902400, "url": "https://example.com/c/abc1234def", "message": "first line\nsecond line", "branch": "main"}`,
want: []string{"abc1234def", `Jane <jane@example\.com>`, `Timestamp:\s+Sat, 16 Jan 2016`, `url:\s+https://example\.com/c/abc1234def`, `message:\s+first line\n\s+second line`},
},
} {
t.Run(tc.name, func(t *testing.T) {
raw := `{"name": "t1", "description": "d", "compliance_state": "INCOMPLETE",
"last_modified_at": 1452902400, "git_commit_info": ` + tc.commitInfo + `, "events": []}`

var buf bytes.Buffer
require.NoError(t, printTrailAsTable(raw, &buf, 0))
for _, w := range tc.want {
require.Regexp(t, w, buf.String())
}
for _, nw := range tc.notWant {
require.NotContains(t, buf.String(), nw)
}
})
}
}
Loading