Skip to content

Commit 19b83fb

Browse files
committed
Add GitHub Actions summary for the create evidence command
1 parent 1ad5b11 commit 19b83fb

18 files changed

+757
-79
lines changed

evidence/create/create_base.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import (
44
"encoding/json"
55
"errors"
66
"fmt"
7+
evidenceUtils "github.com/jfrog/jfrog-cli-artifactory/evidence/utils"
78
"os"
89
"strings"
910

10-
"github.com/jfrog/jfrog-cli-artifactory/evidence/sign"
11+
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/commandsummary"
1112

1213
"github.com/jfrog/gofrog/log"
1314
"github.com/jfrog/jfrog-cli-artifactory/evidence/cryptox"
1415
"github.com/jfrog/jfrog-cli-artifactory/evidence/dsse"
1516
"github.com/jfrog/jfrog-cli-artifactory/evidence/intoto"
1617
"github.com/jfrog/jfrog-cli-artifactory/evidence/model"
18+
"github.com/jfrog/jfrog-cli-artifactory/evidence/sign"
1719
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
1820
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
1921
"github.com/jfrog/jfrog-client-go/artifactory"
@@ -30,6 +32,8 @@ type createEvidenceBase struct {
3032
keyId string
3133
providerId string
3234
flagType FlagType
35+
displayName string
36+
subjectType commandsummary.SubjectType
3337
}
3438

3539
const EvdDefaultUser = "JFrog CLI"
@@ -147,10 +151,10 @@ func (c *createEvidenceBase) setMarkdown(statement *intoto.Statement) error {
147151
return nil
148152
}
149153

150-
func (c *createEvidenceBase) uploadEvidence(evidencePayload []byte, repoPath string) error {
154+
func (c *createEvidenceBase) uploadEvidence(evidencePayload []byte, repoPath string) (*model.CreateResponse, error) {
151155
evidenceManager, err := utils.CreateEvidenceServiceManager(c.serverDetails, false)
152156
if err != nil {
153-
return err
157+
return nil, err
154158
}
155159

156160
evidenceDetails := evidenceService.EvidenceDetails{
@@ -162,20 +166,33 @@ func (c *createEvidenceBase) uploadEvidence(evidencePayload []byte, repoPath str
162166
clientlog.Debug("Uploading evidence for subject:", repoPath)
163167
body, err := evidenceManager.UploadEvidence(evidenceDetails)
164168
if err != nil {
165-
return err
169+
return nil, err
166170
}
167171

168172
createResponse := &model.CreateResponse{}
169173
err = json.Unmarshal(body, createResponse)
170174
if err != nil {
171-
return err
175+
return nil, err
172176
}
173177
if createResponse.Verified {
174178
clientlog.Info("Evidence successfully created and verified")
179+
} else {
180+
clientlog.Info("Evidence successfully created but not verified due to missing/invalid public key")
181+
}
182+
return createResponse, nil
183+
}
184+
185+
func (c *createEvidenceBase) recordEvidenceSummary(summaryData commandsummary.EvidenceSummaryData) error {
186+
if !evidenceUtils.IsRunningUnderGitHubAction() {
175187
return nil
176188
}
177-
clientlog.Info("Evidence successfully created but not verified due to missing/invalid public key")
178-
return nil
189+
190+
evidenceSummary, err := commandsummary.NewEvidenceSummary()
191+
if err != nil {
192+
return err
193+
}
194+
195+
return evidenceSummary.Record(summaryData)
179196
}
180197

181198
func (c *createEvidenceBase) createArtifactoryClient() (artifactory.ArtifactoryServicesManager, error) {

evidence/create/create_base_test.go

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ import (
1010

1111
"github.com/jfrog/jfrog-cli-artifactory/evidence/dsse"
1212
"github.com/jfrog/jfrog-cli-artifactory/evidence/intoto"
13+
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/commandsummary"
1314
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
15+
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
1416
"github.com/jfrog/jfrog-client-go/evidence/services"
1517
"github.com/jfrog/jfrog-client-go/utils/errorutils"
18+
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
1619
clientlog "github.com/jfrog/jfrog-client-go/utils/log"
1720
"github.com/stretchr/testify/assert"
1821
)
@@ -166,3 +169,157 @@ func TestCreateAndSignEnvelope(t *testing.T) {
166169
})
167170
}
168171
}
172+
func TestCreateEvidenceBase_RecordEvidenceSummaryIfInGitHubActions_NotInGitHub(t *testing.T) {
173+
assert.NoError(t, os.Unsetenv("GITHUB_ACTIONS"))
174+
175+
base := &createEvidenceBase{
176+
predicateType: "https://slsa.dev/provenance/v1",
177+
providerId: "test-provider",
178+
}
179+
180+
summaryData := commandsummary.EvidenceSummaryData{
181+
Subject: "/test/subject",
182+
Verified: true,
183+
PredicateType: base.predicateType,
184+
}
185+
err := base.recordEvidenceSummary(summaryData)
186+
assert.NoError(t, err)
187+
}
188+
189+
func TestCreateEvidenceBase_RecordEvidenceSummaryIfInGitHubActions_GitHubCommiter(t *testing.T) {
190+
tempDir, err := fileutils.CreateTempDir()
191+
assert.NoError(t, err)
192+
defer func() {
193+
assert.NoError(t, fileutils.RemoveTempDir(tempDir))
194+
}()
195+
196+
assert.NoError(t, os.Setenv("GITHUB_ACTIONS", "true"))
197+
assert.NoError(t, os.Setenv(coreutils.SummaryOutputDirPathEnv, tempDir))
198+
defer func() {
199+
assert.NoError(t, os.Unsetenv("GITHUB_ACTIONS"))
200+
assert.NoError(t, os.Unsetenv(coreutils.SummaryOutputDirPathEnv))
201+
}()
202+
203+
base := &createEvidenceBase{
204+
predicateType: "https://slsa.dev/provenance/v1",
205+
providerId: "test-provider",
206+
flagType: "gh-commiter",
207+
}
208+
209+
summaryData := commandsummary.EvidenceSummaryData{
210+
Subject: "/test/subject",
211+
Verified: true,
212+
PredicateType: base.predicateType,
213+
}
214+
err = base.recordEvidenceSummary(summaryData)
215+
assert.NoError(t, err)
216+
}
217+
218+
func TestCreateEvidenceBase_RecordEvidenceSummaryIfInGitHubActions_Success(t *testing.T) {
219+
tempDir, err := fileutils.CreateTempDir()
220+
assert.NoError(t, err)
221+
defer func() {
222+
assert.NoError(t, fileutils.RemoveTempDir(tempDir))
223+
}()
224+
225+
assert.NoError(t, os.Setenv("GITHUB_ACTIONS", "true"))
226+
assert.NoError(t, os.Setenv(coreutils.SummaryOutputDirPathEnv, tempDir))
227+
defer func() {
228+
assert.NoError(t, os.Unsetenv("GITHUB_ACTIONS"))
229+
assert.NoError(t, os.Unsetenv(coreutils.SummaryOutputDirPathEnv))
230+
}()
231+
232+
base := &createEvidenceBase{
233+
predicateType: "https://slsa.dev/provenance/v1",
234+
providerId: "test-provider",
235+
flagType: "other",
236+
}
237+
238+
summaryData := commandsummary.EvidenceSummaryData{
239+
Subject: "/docker-cosign-test/hello-world",
240+
Verified: true,
241+
PredicateType: base.predicateType,
242+
}
243+
err = base.recordEvidenceSummary(summaryData)
244+
assert.NoError(t, err)
245+
}
246+
247+
func TestCreateEvidenceBase_RecordEvidenceSummaryIfInGitHubActions_NoSummaryEnv(t *testing.T) {
248+
assert.NoError(t, os.Setenv("GITHUB_ACTIONS", "true"))
249+
assert.NoError(t, os.Unsetenv(coreutils.SummaryOutputDirPathEnv))
250+
defer func() {
251+
assert.NoError(t, os.Unsetenv("GITHUB_ACTIONS"))
252+
}()
253+
254+
base := &createEvidenceBase{
255+
predicateType: "https://slsa.dev/provenance/v1",
256+
providerId: "test-provider",
257+
flagType: "other",
258+
}
259+
260+
summaryData := commandsummary.EvidenceSummaryData{
261+
Subject: "/test/subject",
262+
Verified: true,
263+
PredicateType: base.predicateType,
264+
}
265+
err := base.recordEvidenceSummary(summaryData)
266+
assert.Error(t, err)
267+
}
268+
269+
func TestCreateEvidenceBase_RecordEvidenceSummaryIfInGitHubActions_Verified(t *testing.T) {
270+
tempDir, err := fileutils.CreateTempDir()
271+
assert.NoError(t, err)
272+
defer func() {
273+
assert.NoError(t, fileutils.RemoveTempDir(tempDir))
274+
}()
275+
276+
assert.NoError(t, os.Setenv("GITHUB_ACTIONS", "true"))
277+
assert.NoError(t, os.Setenv(coreutils.SummaryOutputDirPathEnv, tempDir))
278+
defer func() {
279+
assert.NoError(t, os.Unsetenv("GITHUB_ACTIONS"))
280+
assert.NoError(t, os.Unsetenv(coreutils.SummaryOutputDirPathEnv))
281+
}()
282+
283+
base := &createEvidenceBase{
284+
predicateType: "https://slsa.dev/provenance/v1",
285+
providerId: "test-provider",
286+
flagType: "other",
287+
}
288+
289+
summaryData := commandsummary.EvidenceSummaryData{
290+
Subject: "/docker-cosign-test/hello-world",
291+
Verified: true,
292+
PredicateType: base.predicateType,
293+
}
294+
err = base.recordEvidenceSummary(summaryData)
295+
assert.NoError(t, err)
296+
}
297+
298+
func TestCreateEvidenceBase_RecordEvidenceSummaryIfInGitHubActions_NotVerified(t *testing.T) {
299+
tempDir, err := fileutils.CreateTempDir()
300+
assert.NoError(t, err)
301+
defer func() {
302+
assert.NoError(t, fileutils.RemoveTempDir(tempDir))
303+
}()
304+
305+
assert.NoError(t, os.Setenv("GITHUB_ACTIONS", "true"))
306+
assert.NoError(t, os.Setenv(coreutils.SummaryOutputDirPathEnv, tempDir))
307+
defer func() {
308+
assert.NoError(t, os.Unsetenv("GITHUB_ACTIONS"))
309+
assert.NoError(t, os.Unsetenv(coreutils.SummaryOutputDirPathEnv))
310+
}()
311+
312+
base := &createEvidenceBase{
313+
predicateType: "",
314+
providerId: "test-provider",
315+
flagType: "other",
316+
}
317+
318+
summaryData := commandsummary.EvidenceSummaryData{
319+
Subject: "/test-repo/artifact",
320+
Verified: false,
321+
PredicateType: base.predicateType,
322+
}
323+
err = base.recordEvidenceSummary(summaryData)
324+
assert.NoError(t, err)
325+
}

evidence/create/create_build.go

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package create
33
import (
44
"errors"
55
"fmt"
6+
"github.com/jfrog/jfrog-cli-artifactory/evidence/model"
7+
8+
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/commandsummary"
69

710
"github.com/jfrog/jfrog-cli-artifactory/evidence"
811
"github.com/jfrog/jfrog-cli-artifactory/evidence/utils"
@@ -51,28 +54,31 @@ func (c *createEvidenceBuild) Run() error {
5154
log.Error("failed to create Artifactory client", err)
5255
return err
5356
}
54-
subject, sha256, err := c.buildBuildInfoSubjectPath(artifactoryClient)
57+
58+
timestamp, err := getBuildLatestTimestamp(c.buildName, c.buildNumber, c.project, artifactoryClient)
59+
if err != nil {
60+
return err
61+
}
62+
63+
subject, sha256, err := c.buildBuildInfoSubjectPath(artifactoryClient, timestamp)
5564
if err != nil {
5665
return err
5766
}
5867
envelope, err := c.createEnvelope(subject, sha256)
5968
if err != nil {
6069
return err
6170
}
62-
err = c.uploadEvidence(envelope, subject)
71+
72+
response, err := c.uploadEvidence(envelope, subject)
6373
if err != nil {
6474
return err
6575
}
76+
c.recordSummary(subject, sha256, response, timestamp)
6677

6778
return nil
6879
}
6980

70-
func (c *createEvidenceBuild) buildBuildInfoSubjectPath(artifactoryClient artifactory.ArtifactoryServicesManager) (string, string, error) {
71-
timestamp, err := getBuildLatestTimestamp(c.buildName, c.buildNumber, c.project, artifactoryClient)
72-
if err != nil {
73-
return "", "", err
74-
}
75-
81+
func (c *createEvidenceBuild) buildBuildInfoSubjectPath(artifactoryClient artifactory.ArtifactoryServicesManager, timestamp string) (string, string, error) {
7682
repoKey := utils.BuildBuildInfoRepoKey(c.project)
7783
buildInfoPath := buildBuildInfoPath(repoKey, c.buildName, c.buildNumber, timestamp)
7884
buildInfoChecksum, err := getBuildInfoPathChecksum(buildInfoPath, artifactoryClient)
@@ -82,6 +88,28 @@ func (c *createEvidenceBuild) buildBuildInfoSubjectPath(artifactoryClient artifa
8288
return buildInfoPath, buildInfoChecksum, nil
8389
}
8490

91+
func (c *createEvidenceBuild) recordSummary(subject string, sha256 string, response *model.CreateResponse, timestamp string) {
92+
displayName := fmt.Sprintf("%s %s", c.buildName, c.buildNumber)
93+
commandSummary := commandsummary.EvidenceSummaryData{
94+
Subject: subject,
95+
SubjectSha256: sha256,
96+
PredicateType: c.predicateType,
97+
PredicateSlug: response.PredicateSlug,
98+
Verified: response.Verified,
99+
DisplayName: displayName,
100+
SubjectType: commandsummary.SubjectTypeBuild,
101+
BuildName: c.buildName,
102+
BuildNumber: c.buildNumber,
103+
BuildTimestamp: timestamp,
104+
RepoKey: utils.BuildBuildInfoRepoKey(c.project),
105+
}
106+
107+
err := c.recordEvidenceSummary(commandSummary)
108+
if err != nil {
109+
log.Warn("Failed to record evidence summary:", err.Error())
110+
}
111+
}
112+
85113
func getBuildLatestTimestamp(name string, number string, project string, artifactoryClient artifactory.ArtifactoryServicesManager) (string, error) {
86114
buildInfo := services.BuildInfoParams{
87115
BuildName: name,

0 commit comments

Comments
 (0)