Skip to content

Commit d6b1c70

Browse files
authored
Git Integration POST Request (#1272)
* added git integration post request * added function to XscService interface * added SendGitIntegrationEvent to xsc inner service * after cr
1 parent 8966184 commit d6b1c70

File tree

6 files changed

+153
-7
lines changed

6 files changed

+153
-7
lines changed

tests/xscanalyticsevent_test.go

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ package tests
44

55
import (
66
"encoding/json"
7-
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
8-
"github.com/jfrog/jfrog-client-go/xsc/services"
9-
"github.com/jfrog/jfrog-client-go/xsc/services/utils"
10-
"github.com/stretchr/testify/assert"
11-
"github.com/stretchr/testify/require"
127
"net/http"
138
"net/http/httptest"
149
"strings"
1510
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
15+
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
16+
"github.com/jfrog/jfrog-client-go/xsc/services"
17+
"github.com/jfrog/jfrog-client-go/xsc/services/utils"
1618
)
1719

1820
const TestMultiScanId = "3472b4e2-bddc-11ee-a9c9-acde48001122"
@@ -137,3 +139,91 @@ func createXscMockServerForGeneralEvent(t *testing.T) (mockServer *httptest.Serv
137139
analyticsService.XrayDetails = xrayDetails
138140
return
139141
}
142+
143+
func TestXscSendGitIntegrationEvent(t *testing.T) {
144+
initXscTest(t, services.LogErrorMinXscVersion, utils.MinXrayVersionGitIntegrationEvent)
145+
146+
testCases := []struct {
147+
name string
148+
xrayVersion string
149+
expectError bool
150+
errorMsg string
151+
}{
152+
{
153+
name: "Xray version below minimum",
154+
xrayVersion: "3.134.0",
155+
expectError: true,
156+
errorMsg: "git integration event requires minimum Xray version",
157+
},
158+
{
159+
name: "Xray version at minimum",
160+
xrayVersion: "3.135.0",
161+
expectError: false,
162+
},
163+
{
164+
name: "Xray version above minimum",
165+
xrayVersion: "3.136.0",
166+
expectError: false,
167+
},
168+
}
169+
170+
for _, tc := range testCases {
171+
t.Run(tc.name, func(t *testing.T) {
172+
mockServer, analyticsService := createXscMockServerForGitIntegrationEvent(t)
173+
defer mockServer.Close()
174+
175+
event := services.GitIntegrationEvent{
176+
EventType: "Source Code SBOM Results Upload",
177+
GitProvider: "github",
178+
GitOwner: "jfrog",
179+
GitRepository: "jfrog-cli-security",
180+
GitBranch: "main",
181+
EventStatus: "completed",
182+
}
183+
184+
err := analyticsService.SendGitIntegrationEvent(event, tc.xrayVersion)
185+
186+
if tc.expectError {
187+
assert.Error(t, err)
188+
assert.Contains(t, err.Error(), tc.errorMsg)
189+
} else {
190+
assert.NoError(t, err)
191+
}
192+
})
193+
}
194+
}
195+
196+
func createXscMockServerForGitIntegrationEvent(t *testing.T) (mockServer *httptest.Server, analyticsService *services.AnalyticsEventService) {
197+
mockServer = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
198+
switch {
199+
case strings.Contains(r.RequestURI, "/xray/api/v1/xsc/git_integration_event") && r.Method == http.MethodPost:
200+
// Validate request body
201+
var receivedEvent services.GitIntegrationEvent
202+
err := json.NewDecoder(r.Body).Decode(&receivedEvent)
203+
assert.NoError(t, err)
204+
205+
// Validate required fields
206+
assert.NotEmpty(t, receivedEvent.EventType)
207+
assert.NotEmpty(t, receivedEvent.GitProvider)
208+
assert.NotEmpty(t, receivedEvent.GitOwner)
209+
assert.NotEmpty(t, receivedEvent.GitRepository)
210+
assert.NotEmpty(t, receivedEvent.GitBranch)
211+
assert.NotEmpty(t, receivedEvent.EventStatus)
212+
213+
w.WriteHeader(http.StatusCreated)
214+
default:
215+
assert.Fail(t, "received an unexpected request: "+r.Method+" "+r.RequestURI)
216+
}
217+
}))
218+
219+
xrayDetails := GetXrayDetails()
220+
xrayDetails.SetUrl(mockServer.URL + "/xray")
221+
xrayDetails.SetAccessToken("")
222+
223+
client, err := jfroghttpclient.JfrogClientBuilder().Build()
224+
assert.NoError(t, err)
225+
226+
analyticsService = services.NewAnalyticsEventService(client)
227+
analyticsService.XrayDetails = xrayDetails
228+
return
229+
}

xray/services/xsc/xsc.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ func (xs *XscInnerService) AddAnalyticsGeneralEvent(event services.XscAnalyticsG
3232
return eventService.AddGeneralEvent(event, xrayVersion)
3333
}
3434

35+
func (xs *XscInnerService) SendGitIntegrationEvent(event services.GitIntegrationEvent, xrayVersion string) error {
36+
eventService := services.NewAnalyticsEventService(xs.client)
37+
eventService.XrayDetails = xs.XrayDetails
38+
eventService.ScopeProjectKey = xs.ScopeProjectKey
39+
return eventService.SendGitIntegrationEvent(event, xrayVersion)
40+
}
41+
3542
func (xs *XscInnerService) SendXscLogErrorRequest(errorLog *services.ExternalErrorLog) error {
3643
logErrorService := services.NewLogErrorEventService(xs.client)
3744
logErrorService.XrayDetails = xs.XrayDetails

xsc/manager.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,9 @@ func (sm *XscServicesManager) GetConfigProfileByUrl(_ string) (*services.ConfigP
8787
// Empty implementation required for alignment with interface, implemented only at the new service inside the Xray service
8888
return nil, nil
8989
}
90+
91+
// SendGitIntegrationEvent sends a git integration event to xray
92+
func (sm *XscServicesManager) SendGitIntegrationEvent(event services.GitIntegrationEvent, xrayVersion string) error {
93+
// Empty implementation required for alignment with interface, implemented only at the new service inside the Xray service
94+
return nil
95+
}

xsc/service.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ type XscService interface {
1919
GetConfigProfileByName(profileName string) (*services.ConfigProfile, error)
2020
// GetConfigProfileByUrl returns the configuration profile related to the provided repository url.
2121
GetConfigProfileByUrl(profileUrl string) (*services.ConfigProfile, error)
22+
// SendGitIntegrationEvent sends a git integration event to xray
23+
SendGitIntegrationEvent(event services.GitIntegrationEvent, xrayVersion string) error
2224
}

xsc/services/analytics.go

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
const (
1717
AnalyticsMetricsMinXscVersion = "1.7.1"
1818
xscEventApi = "event"
19+
gitIntegrationEventApi = "git_integration_event"
1920
xscDeprecatedEventApiSuffix = "api/v1/" + xscEventApi
2021
)
2122

@@ -38,7 +39,11 @@ func (vs *AnalyticsEventService) getAnalyticsEndPoint() string {
3839
return utils.AddTrailingSlashIfNeeded(vs.XscDetails.GetUrl()) + xscDeprecatedEventApiSuffix
3940
}
4041

41-
func (vs *AnalyticsEventService) sendPostRequest(requestContent []byte) (resp *http.Response, body []byte, err error) {
42+
func (vs *AnalyticsEventService) getGitEventEndPoint() string {
43+
return utils.AddTrailingSlashIfNeeded(vs.XrayDetails.GetUrl()) + xscutils.XscInXraySuffix + gitIntegrationEventApi
44+
}
45+
46+
func (vs *AnalyticsEventService) sendAddGeneralEventPostRequest(requestContent []byte) (resp *http.Response, body []byte, err error) {
4247
var httpClientDetails httputils.HttpClientDetails
4348
if vs.XrayDetails != nil {
4449
httpClientDetails = vs.XrayDetails.CreateHttpClientDetails()
@@ -50,6 +55,12 @@ func (vs *AnalyticsEventService) sendPostRequest(requestContent []byte) (resp *h
5055
return
5156
}
5257

58+
func (vs *AnalyticsEventService) sendGitIntegrationPostRequest(requestContent []byte) (resp *http.Response, body []byte, err error) {
59+
var httpClientDetails = vs.XrayDetails.CreateHttpClientDetails()
60+
resp, body, err = vs.client.SendPost(utils.AppendScopedProjectKeyParam(vs.getGitEventEndPoint(), vs.ScopeProjectKey), requestContent, &httpClientDetails)
61+
return
62+
}
63+
5364
func (vs *AnalyticsEventService) sendPutRequest(requestContent []byte) (resp *http.Response, body []byte, err error) {
5465
var httpClientDetails httputils.HttpClientDetails
5566
if vs.XrayDetails != nil {
@@ -88,7 +99,7 @@ func (vs *AnalyticsEventService) AddGeneralEvent(event XscAnalyticsGeneralEvent,
8899
return "", errorutils.CheckError(err)
89100
}
90101
}
91-
resp, body, err := vs.sendPostRequest(requestContent)
102+
resp, body, err := vs.sendAddGeneralEventPostRequest(requestContent)
92103
if err != nil {
93104
return "", err
94105
}
@@ -100,6 +111,25 @@ func (vs *AnalyticsEventService) AddGeneralEvent(event XscAnalyticsGeneralEvent,
100111
return response.MultiScanId, errorutils.CheckError(err)
101112
}
102113

114+
// SendGitIntegrationEvent sends a POST request to the /git_integration_event endpoint
115+
func (vs *AnalyticsEventService) SendGitIntegrationEvent(event GitIntegrationEvent, xrayVersion string) error {
116+
if err := utils.ValidateMinimumVersion(utils.Xray, xrayVersion, xscutils.MinXrayVersionGitIntegrationEvent); err != nil {
117+
return fmt.Errorf("git integration event version error %s: %w", xscutils.MinXrayVersionGitIntegrationEvent, err)
118+
}
119+
requestBody, err := json.Marshal(event)
120+
if err != nil {
121+
return errorutils.CheckError(err)
122+
}
123+
resp, body, err := vs.sendGitIntegrationPostRequest(requestBody)
124+
if err != nil {
125+
return errorutils.CheckError(err)
126+
}
127+
if err = errorutils.CheckResponseStatus(resp, http.StatusCreated); err != nil {
128+
return errorutils.CheckError(errorutils.GenerateResponseError(resp.Status, utils.IndentJson(body)))
129+
}
130+
return nil
131+
}
132+
103133
// UpdateGeneralEvent update finalized analytics metrics info of an existing event.
104134
func (vs *AnalyticsEventService) UpdateGeneralEvent(event XscAnalyticsGeneralEventFinalize) error {
105135
requestContent, err := json.Marshal(event)
@@ -201,6 +231,16 @@ type PullRequestContext struct {
201231
PullRequestTitle string `json:"pull_request_title,omitempty"`
202232
}
203233

234+
type GitIntegrationEvent struct {
235+
EventType string `json:"event_type"`
236+
GitProvider string `json:"git_provider"`
237+
GitOwner string `json:"git_owner"`
238+
GitRepository string `json:"git_repository"`
239+
GitBranch string `json:"git_branch"`
240+
EventStatus string `json:"event_status"`
241+
FailureReason string `json:"failure_reason,omitempty"`
242+
}
243+
204244
type XscAnalyticsGeneralEventFinalize struct {
205245
XscAnalyticsBasicGeneralEvent
206246
MultiScanId string `json:"multi_scan_id,omitempty"`

xsc/services/utils/utils.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const (
1515
XscInXraySuffix = apiV1Suffix + xscSuffix
1616
MinXrayVersionXscTransitionToXray = "3.107.13"
1717
MinXrayVersionNewGitInfoContext = "3.117.0"
18+
MinXrayVersionGitIntegrationEvent = "3.135.0"
1819
)
1920

2021
// From Xray version 3.107.13, XSC is transitioning to Xray as inner service. This function will return compatible URL.

0 commit comments

Comments
 (0)