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
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ func (i *Integration) Execute(_ context.Context, req *sdk.ExecutionRequest) erro
return fmt.Errorf("running validation: %w", err)
}

summary, err := sdk.SummaryTable(req)
// 4000 is the max size of a Slack message
// if the message is larger than that, we will truncate it
summary, err := sdk.SummaryTable(req, sdk.WithMaxSize(4000))
if err != nil {
return fmt.Errorf("error summarizing the request: %w", err)
}
Expand Down
40 changes: 35 additions & 5 deletions app/controlplane/plugins/sdk/v1/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import (
)

type renderer struct {
render func(t table.Writer) string
format string
render func(t table.Writer) string
maxSize int
}

type RenderOpt func(r *renderer) error
Expand All @@ -51,7 +51,13 @@ func WithFormat(format string) RenderOpt {
return fmt.Errorf("unsupported format %s", format)
}

r.format = format
return nil
}
}

func WithMaxSize(max int) RenderOpt {
return func(r *renderer) error {
r.maxSize = max
return nil
}
}
Expand All @@ -60,7 +66,7 @@ func newRenderer(opts ...RenderOpt) (*renderer, error) {
r := &renderer{
render: func(t table.Writer) string {
return t.Render()
}, format: "text",
},
}

for _, opt := range opts {
Expand Down Expand Up @@ -182,11 +188,35 @@ func (r *renderer) summaryTable(m *ChainloopMetadata, predicate chainloop.Normal
result += "\n" + r.render(mt)
}

result += fmt.Sprintf("\n\nGet Full Attestation\n\n$ chainloop workflow run describe --id %s -o statement", wr.ID)
footer := fmt.Sprintf("\n\nGet Full Attestation\n\n$ chainloop workflow run describe --id %s -o statement", wr.ID)

// Truncate the text if it's too long to be displayed, the footer will be kept
if r.maxSize > 0 {
result = truncateText(result, r.maxSize-len(footer))
}

result += footer

return result, nil
}

// Truncate returns the first n runes of s.
func truncateText(s string, n int) string {
truncatedPrefix := "... (truncated)"
n -= len(truncatedPrefix)

if len(s) <= n {
return s
}
for i := range s {
if n == 0 {
return s[:i] + truncatedPrefix
}
n--
}
return s
}

func SummaryTable(req *ExecutionRequest, opts ...RenderOpt) (string, error) {
renderer, err := newRenderer(opts...)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions app/controlplane/plugins/sdk/v1/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ func (s *helperTestSuite) TestSummaryTable() {
inputPath: "testdata/attestations/full.json",
outputPath: "testdata/attestations/full.txt",
},
{
name: "truncated text",
inputPath: "testdata/attestations/full.json",
renderOpts: []RenderOpt{WithMaxSize(2000)},
outputPath: "testdata/attestations/truncated.txt",
},
{
name: "full markdown",
inputPath: "testdata/attestations/full.json",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
┌─────────────────────────────────────┐
│ Workflow │
├──────────────┬──────────────────────┤
│ ID │ deadbeef │
│ Name │ test-workflow │
│ Team │ test-team │
│ Project │ test-project │
├──────────────┼──────────────────────┤
│ Workflow Run │ │
├──────────────┼──────────────────────┤
│ ID │ beefdead │
│ Started At │ 22 Nov 21 00:00 UTC │
│ Finished At │ 22 Nov 21 00:10 UTC │
│ State │ success │
│ Runner Link │ chainloop.dev/runner │
│ Annotations │ ------ │
│ │ branch: stable │
│ │ toplevel: true │
└──────────────┴──────────────────────┘
┌────────────────────────────────────────────────────────────────────────────────┐
│ Materials │
├─────────────┬──────────────────────────────────────────────────────────────────┤
│ Name │ image │
│ Type │ CONTAINER_IMAGE │
│ Value │ index.docker.io/bitnami/nginx │
│ Digest │ 264f55a6ff9cec2f4742a9faacc033b29f65c04dd4480e71e23579d484288d61 │
├─────────────┼──────────────────────────────────────────────────────────────────┤
│ Name │ skynet-sbom │
│ Type │ SBOM_CYCLONEDX_JSON │
│ Value │ sbom.cyclonedx.json │
│ Digest │ 16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c │
│ Annotations │ ------ │
│ │ component: nginx ... (truncated)

Get Full Attestation

$ chainloop workflow run describe --id beefdead -o statement