Skip to content

Commit f6ec84d

Browse files
authored
feat: show annotations in notifications (#289)
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
1 parent 2255ac9 commit f6ec84d

File tree

11 files changed

+413
-208
lines changed

11 files changed

+413
-208
lines changed

app/cli/cmd/workflow_workflow_run_describe.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ func workflowRunDescribeTableOutput(run *action.WorkflowRunItemFull) error {
121121
color = text.FgHiGreen
122122
}
123123
gt.AppendRow(table.Row{"Verified", color.Sprint(run.Verified)})
124+
if len(att.Annotations) > 0 {
125+
gt.AppendRow(table.Row{"Annotations", "------"})
126+
for _, a := range att.Annotations {
127+
gt.AppendRow(table.Row{"", fmt.Sprintf("%s: %s", a.Name, a.Value)})
128+
}
129+
}
124130
gt.Render()
125131

126132
predicateV1Table(att)

app/cli/internal/action/workflow_run_describe.go

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,13 @@ type WorkflowRunItemFull struct {
4343
}
4444

4545
type WorkflowRunAttestationItem struct {
46-
ID string `json:"id"`
47-
CreatedAt *time.Time `json:"createdAt"`
48-
Envelope *dsse.Envelope `json:"envelope"`
49-
statement *in_toto.Statement
50-
Materials []*Material `json:"materials,omitempty"`
51-
EnvVars []*EnvVar `json:"envvars,omitempty"`
46+
ID string `json:"id"`
47+
CreatedAt *time.Time `json:"createdAt"`
48+
Envelope *dsse.Envelope `json:"envelope"`
49+
statement *in_toto.Statement
50+
Materials []*Material `json:"materials,omitempty"`
51+
EnvVars []*EnvVar `json:"envvars,omitempty"`
52+
Annotations []*Annotation `json:"annotations,omitempty"`
5253
}
5354

5455
type Material struct {
@@ -132,12 +133,26 @@ func (action *WorkflowRunDescribe) Run(runID string, verify bool, publicKey stri
132133
materials = append(materials, materialPBToAction(v))
133134
}
134135

136+
keys := make([]string, 0, len(attestation.GetAnnotations()))
137+
for k := range attestation.GetAnnotations() {
138+
keys = append(keys, k)
139+
}
140+
sort.Strings(keys)
141+
142+
annotations := make([]*Annotation, 0, len(attestation.GetAnnotations()))
143+
for _, k := range keys {
144+
annotations = append(annotations, &Annotation{
145+
Name: k, Value: attestation.GetAnnotations()[k],
146+
})
147+
}
148+
135149
item.Attestation = &WorkflowRunAttestationItem{
136150
ID: attestation.Id, CreatedAt: toTimePtr(attestation.CreatedAt.AsTime()),
137-
Envelope: envelope,
138-
statement: statement,
139-
EnvVars: envVars,
140-
Materials: materials,
151+
Envelope: envelope,
152+
statement: statement,
153+
EnvVars: envVars,
154+
Materials: materials,
155+
Annotations: annotations,
141156
}
142157

143158
return item, nil

app/controlplane/api/controlplane/v1/response_messages.pb.go

Lines changed: 187 additions & 167 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/api/controlplane/v1/response_messages.pb.validate.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/api/controlplane/v1/response_messages.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ message AttestationItem {
5757
// denormalized envelope/statement content
5858
repeated EnvVariable env_vars = 4;
5959
repeated Material materials = 5;
60+
map<string, string> annotations = 6;
6061

6162
message EnvVariable {
6263
string name = 1;

app/controlplane/api/gen/frontend/controlplane/v1/response_messages.ts

Lines changed: 113 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/internal/service/attestation.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,10 @@ func bizAttestationToPb(att *biz.Attestation) (*cpAPI.AttestationItem, error) {
311311
}
312312

313313
return &cpAPI.AttestationItem{
314-
Envelope: encodedAttestation,
315-
EnvVars: extractEnvVariables(predicate.GetEnvVars()),
316-
Materials: materials,
314+
Envelope: encodedAttestation,
315+
EnvVars: extractEnvVariables(predicate.GetEnvVars()),
316+
Materials: materials,
317+
Annotations: predicate.GetAnnotations(),
317318
}, nil
318319
}
319320

app/controlplane/plugins/sdk/v1/helpers.go

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"github.com/chainloop-dev/chainloop/internal/attestation/renderer/chainloop"
2424
"github.com/jedib0t/go-pretty/v6/table"
25+
"github.com/muesli/reflow/wrap"
2526
)
2627

2728
type renderer struct {
@@ -102,6 +103,18 @@ func (r *renderer) summaryTable(m *ChainloopMetadata, predicate chainloop.Normal
102103
tw.AppendRow(table.Row{"Finished At", wr.FinishedAt.Format(time.RFC822)})
103104
tw.AppendRow(table.Row{"State", wr.State})
104105
tw.AppendRow(table.Row{"Runner Link", wr.RunURL})
106+
if annotations := predicate.GetAnnotations(); len(annotations) > 0 {
107+
keys := make([]string, 0, len(annotations))
108+
for k := range annotations {
109+
keys = append(keys, k)
110+
}
111+
sort.Strings(keys)
112+
113+
tw.AppendRow(table.Row{"Annotations", "------"})
114+
for _, k := range keys {
115+
tw.AppendRow(table.Row{"", fmt.Sprintf("%s: %s", k, annotations[k])})
116+
}
117+
}
105118

106119
var result = r.render(tw)
107120

@@ -112,23 +125,32 @@ func (r *renderer) summaryTable(m *ChainloopMetadata, predicate chainloop.Normal
112125
mt.SetStyle(table.StyleLight)
113126

114127
mt.SetTitle("Materials")
115-
mt.AppendHeader(table.Row{"Name", "Type", "Value"})
116-
117128
for _, m := range materials {
118-
// Initialize simply with the value
119-
displayValue := m.Value
120-
// Override if there is a hash attached
129+
mt.AppendRow(table.Row{"Name", m.Name})
130+
mt.AppendRow(table.Row{"Type", m.Type})
131+
value := m.Value
132+
// Override the value for the filename of the item uploaded
133+
if m.EmbeddedInline || m.UploadedToCAS {
134+
value = m.Filename
135+
}
136+
mt.AppendRow(table.Row{"Value", wrap.String(value, 100)})
121137
if m.Hash != nil {
122-
name := m.Value
123-
if m.EmbeddedInline || m.UploadedToCAS {
124-
name = m.Filename
138+
mt.AppendRow(table.Row{"Digest", m.Hash.Hex})
139+
}
140+
141+
if annotations := m.Annotations; len(annotations) > 0 {
142+
keys := make([]string, 0, len(annotations))
143+
for k := range annotations {
144+
keys = append(keys, k)
125145
}
146+
sort.Strings(keys)
126147

127-
displayValue = fmt.Sprintf("%s@%s", name, m.Hash)
148+
mt.AppendRow(table.Row{"Annotations", "------"})
149+
for _, k := range keys {
150+
mt.AppendRow(table.Row{"", fmt.Sprintf("%s: %s", k, annotations[k])})
151+
}
128152
}
129-
130-
row := table.Row{m.Name, m.Type, displayValue}
131-
mt.AppendRow(row)
153+
mt.AppendSeparator()
132154
}
133155

134156
result += "\n" + r.render(mt)

app/controlplane/plugins/sdk/v1/testdata/attestations/full.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"payloadType": "application/vnd.in-toto+json",
3-
"payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImNoYWlubG9vcC5kZXYvYXR0ZXN0YXRpb24vdjAuMiIsCiAgInN1YmplY3QiOiBbCiAgICB7CiAgICAgICJuYW1lIjogImNoYWlubG9vcC5kZXYvd29ya2Zsb3cvb25seS1zYm9tIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhMjU2IjogIjMwMzZmMmU1ZDcwOWEyMzgwOGVhYTA1NTcwZjE3MThhZmZmOTJkNGFkMzVlMjMyYzEzODczODM3MmFjOTNkZmIiCiAgICAgIH0KICAgIH0KICBdLAogICJwcmVkaWNhdGUiOiB7CiAgICAibWV0YWRhdGEiOiB7CiAgICAgICJuYW1lIjogIm9ubHktc2JvbSIsCiAgICAgICJwcm9qZWN0IjogImZvbyIsCiAgICAgICJ0ZWFtIjogIiIsCiAgICAgICJpbml0aWFsaXplZEF0IjogIjIwMjMtMDYtMjNUMTM6MDA6MjkuMTgzNjE4OTY2WiIsCiAgICAgICJmaW5pc2hlZEF0IjogIjIwMjMtMDYtMjNUMTU6MDA6NDMuNzA5OTcwNjcrMDI6MDAiLAogICAgICAid29ya2Zsb3dSdW5JRCI6ICJhMTdjYTIxNi0yOWI2LTQxMDctYjNmYy05MjU2ZjdhZjJmZTYiLAogICAgICAid29ya2Zsb3dJRCI6ICI1ZTM0YjM0Zi04ODJjLTQ4YjgtODRjMC00ZjIzOGUxNWE1ZmQiCiAgICB9LAogICAgImVudiI6IHsgIm93bmVyIjogImpvaG4tY0BjaGFpbmxvb3AuZGV2IiwgInByb2plY3QiOiAiY2hhdGdwdCIgfSwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiY2hhaW5sb29wLmRldi9jbGkvZGV2QHNoYTI1NjphOGRkZDczODEzMDAyZjYyZDJkZTExYTQyMDU0YzA2ZmFlMGQwYTg4YjZjODkwNGU3ZGU0NDc1MTk4YzBiMGQzIgogICAgfSwKICAgICJidWlsZFR5cGUiOiAiY2hhaW5sb29wLmRldi93b3JrZmxvd3J1bi92MC4xIiwKICAgICJydW5uZXJUeXBlIjogIlJVTk5FUl9UWVBFX1VOU1BFQ0lGSUVEIiwKICAgICJtYXRlcmlhbHMiOiBbCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTI1NiI6ICIyNjRmNTVhNmZmOWNlYzJmNDc0MmE5ZmFhY2MwMzNiMjlmNjVjMDRkZDQ0ODBlNzFlMjM1NzlkNDg0Mjg4ZDYxIgogICAgICAgIH0sCiAgICAgICAgIm5hbWUiOiAiaW5kZXguZG9ja2VyLmlvL2JpdG5hbWkvbmdpbngiLAogICAgICAgICJhbm5vdGF0aW9ucyI6IHsKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwubmFtZSI6ICJpbWFnZSIsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLnR5cGUiOiAiQ09OVEFJTkVSX0lNQUdFIgogICAgICAgIH0KICAgICAgfSwKICAgICAgewogICAgICAgICJkaWdlc3QiOiB7CiAgICAgICAgICAic2hhMjU2IjogIjE2MTU5YmI4ODFlYjRhYjdlYjVkOGFmYzUzNTBiMGZlZWVkMWUzMWMwYTI2OGUzNTVlNzRmOWNjYmU4ODVlMGMiCiAgICAgICAgfSwKICAgICAgICAibmFtZSI6ICJzYm9tLmN5Y2xvbmVkeC5qc29uIiwKICAgICAgICAiYW5ub3RhdGlvbnMiOiB7CiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLmNhcyI6IHRydWUsCiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLm5hbWUiOiAic2t5bmV0LXNib20iLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIlNCT01fQ1lDTE9ORURYX0pTT04iCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICJzaGEyNTYiOiAiMTYxNTliYjg4MWViNGFiN2ViNWQ4YWZjNTM1MGIwZmVlZWQxZTMxYzBhMjY4ZTM1NWU3NGY5Y2NiZTg4NWUwYyIKICAgICAgICB9LAogICAgICAgICJuYW1lIjogInNib20uY3ljbG9uZWR4Lmpzb24iLAogICAgICAgICJhbm5vdGF0aW9ucyI6IHsKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwuY2FzIjogdHJ1ZSwKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwubmFtZSI6ICJza3luZXQyLXNib20iLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIlNCT01fQ1lDTE9ORURYX0pTT04iCiAgICAgICAgfQogICAgICB9CiAgICBdCiAgfQp9Cg==",
3+
"payload": "ewogICJfdHlwZSI6ICJodHRwczovL2luLXRvdG8uaW8vU3RhdGVtZW50L3YwLjEiLAogICJwcmVkaWNhdGVUeXBlIjogImNoYWlubG9vcC5kZXYvYXR0ZXN0YXRpb24vdjAuMiIsCiAgInN1YmplY3QiOiBbCiAgICB7CiAgICAgICJuYW1lIjogImNoYWlubG9vcC5kZXYvd29ya2Zsb3cvb25seS1zYm9tIiwKICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAic2hhMjU2IjogIjMwMzZmMmU1ZDcwOWEyMzgwOGVhYTA1NTcwZjE3MThhZmZmOTJkNGFkMzVlMjMyYzEzODczODM3MmFjOTNkZmIiCiAgICAgIH0KICAgIH0KICBdLAogICJwcmVkaWNhdGUiOiB7CiAgICAibWV0YWRhdGEiOiB7CiAgICAgICJuYW1lIjogIm9ubHktc2JvbSIsCiAgICAgICJwcm9qZWN0IjogImZvbyIsCiAgICAgICJ0ZWFtIjogIiIsCiAgICAgICJpbml0aWFsaXplZEF0IjogIjIwMjMtMDYtMjNUMTM6MDA6MjkuMTgzNjE4OTY2WiIsCiAgICAgICJmaW5pc2hlZEF0IjogIjIwMjMtMDYtMjNUMTU6MDA6NDMuNzA5OTcwNjcrMDI6MDAiLAogICAgICAid29ya2Zsb3dSdW5JRCI6ICJhMTdjYTIxNi0yOWI2LTQxMDctYjNmYy05MjU2ZjdhZjJmZTYiLAogICAgICAid29ya2Zsb3dJRCI6ICI1ZTM0YjM0Zi04ODJjLTQ4YjgtODRjMC00ZjIzOGUxNWE1ZmQiCiAgICB9LAogICAgImVudiI6IHsgIm93bmVyIjogImpvaG4tY0BjaGFpbmxvb3AuZGV2IiwgInByb2plY3QiOiAiY2hhdGdwdCIgfSwKICAgICJidWlsZGVyIjogewogICAgICAiaWQiOiAiY2hhaW5sb29wLmRldi9jbGkvZGV2QHNoYTI1NjphOGRkZDczODEzMDAyZjYyZDJkZTExYTQyMDU0YzA2ZmFlMGQwYTg4YjZjODkwNGU3ZGU0NDc1MTk4YzBiMGQzIgogICAgfSwKICAgICJidWlsZFR5cGUiOiAiY2hhaW5sb29wLmRldi93b3JrZmxvd3J1bi92MC4xIiwKICAgICJydW5uZXJUeXBlIjogIlJVTk5FUl9UWVBFX1VOU1BFQ0lGSUVEIiwKICAgICJhbm5vdGF0aW9ucyI6IHsKICAgICAgInRvcGxldmVsIjogInRydWUiLAogICAgICAiYnJhbmNoIjogInN0YWJsZSIKICAgIH0sCiAgICAibWF0ZXJpYWxzIjogWwogICAgICB7CiAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICJzaGEyNTYiOiAiMjY0ZjU1YTZmZjljZWMyZjQ3NDJhOWZhYWNjMDMzYjI5ZjY1YzA0ZGQ0NDgwZTcxZTIzNTc5ZDQ4NDI4OGQ2MSIKICAgICAgICB9LAogICAgICAgICJuYW1lIjogImluZGV4LmRvY2tlci5pby9iaXRuYW1pL25naW54IiwKICAgICAgICAiYW5ub3RhdGlvbnMiOiB7CiAgICAgICAgICAiY2hhaW5sb29wLm1hdGVyaWFsLm5hbWUiOiAiaW1hZ2UiLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIkNPTlRBSU5FUl9JTUFHRSIKICAgICAgICB9CiAgICAgIH0sCiAgICAgIHsKICAgICAgICAiZGlnZXN0IjogewogICAgICAgICAgInNoYTI1NiI6ICIxNjE1OWJiODgxZWI0YWI3ZWI1ZDhhZmM1MzUwYjBmZWVlZDFlMzFjMGEyNjhlMzU1ZTc0ZjljY2JlODg1ZTBjIgogICAgICAgIH0sCiAgICAgICAgIm5hbWUiOiAic2JvbS5jeWNsb25lZHguanNvbiIsCiAgICAgICAgImFubm90YXRpb25zIjogewogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5jYXMiOiB0cnVlLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC5uYW1lIjogInNreW5ldC1zYm9tIiwKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwudHlwZSI6ICJTQk9NX0NZQ0xPTkVEWF9KU09OIiwKICAgICAgICAgICJjb21wb25lbnQiOiAibmdpbngiCiAgICAgICAgfQogICAgICB9LAogICAgICB7CiAgICAgICAgImRpZ2VzdCI6IHsKICAgICAgICAgICJzaGEyNTYiOiAiMTYxNTliYjg4MWViNGFiN2ViNWQ4YWZjNTM1MGIwZmVlZWQxZTMxYzBhMjY4ZTM1NWU3NGY5Y2NiZTg4NWUwYyIKICAgICAgICB9LAogICAgICAgICJuYW1lIjogInNib20uY3ljbG9uZWR4Lmpzb24iLAogICAgICAgICJhbm5vdGF0aW9ucyI6IHsKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwuY2FzIjogdHJ1ZSwKICAgICAgICAgICJjaGFpbmxvb3AubWF0ZXJpYWwubmFtZSI6ICJza3luZXQyLXNib20iLAogICAgICAgICAgImNoYWlubG9vcC5tYXRlcmlhbC50eXBlIjogIlNCT01fQ1lDTE9ORURYX0pTT04iCiAgICAgICAgfQogICAgICB9CiAgICBdCiAgfQp9Cg==",
44
"signatures": [
55
{
66
"keyid": "",

app/controlplane/plugins/sdk/v1/testdata/attestations/full.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,24 @@
99
| Finished At | 22 Nov 21 00:10 UTC |
1010
| State | success |
1111
| Runner Link | chainloop.dev/runner |
12+
| Annotations | ------ |
13+
| | branch: stable |
14+
| | toplevel: true |
1215
# Materials
13-
| Name | Type | Value |
14-
| --- | --- | --- |
15-
| image | CONTAINER_IMAGE | index.docker.io/bitnami/nginx@sha256:264f55a6ff9cec2f4742a9faacc033b29f65c04dd4480e71e23579d484288d61 |
16-
| skynet-sbom | SBOM_CYCLONEDX_JSON | sbom.cyclonedx.json@sha256:16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c |
17-
| skynet2-sbom | SBOM_CYCLONEDX_JSON | sbom.cyclonedx.json@sha256:16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c |
16+
| Name | image |
17+
| Type | CONTAINER_IMAGE |
18+
| Value | index.docker.io/bitnami/nginx |
19+
| Digest | 264f55a6ff9cec2f4742a9faacc033b29f65c04dd4480e71e23579d484288d61 |
20+
| Name | skynet-sbom |
21+
| Type | SBOM_CYCLONEDX_JSON |
22+
| Value | sbom.cyclonedx.json |
23+
| Digest | 16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c |
24+
| Annotations | ------ |
25+
| | component: nginx |
26+
| Name | skynet2-sbom |
27+
| Type | SBOM_CYCLONEDX_JSON |
28+
| Value | sbom.cyclonedx.json |
29+
| Digest | 16159bb881eb4ab7eb5d8afc5350b0feeed1e31c0a268e355e74f9ccbe885e0c |
1830
# Environment Variables
1931
| Name | Value |
2032
| --- | --- |

0 commit comments

Comments
 (0)