Skip to content

Commit

Permalink
Merge branch 'dev' into fix/watch-field
Browse files Browse the repository at this point in the history
  • Loading branch information
attiasas authored May 6, 2024
2 parents ebf5b85 + d12abb9 commit 3bfe932
Show file tree
Hide file tree
Showing 30 changed files with 990 additions and 80 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
strategy:
fail-fast: false
matrix:
suite: [ distribution, xray, mpu ]
suite: [ distribution, xray, xsc, mpu ]
os: [ ubuntu, windows, macos ]
runs-on: ${{ matrix.os }}-latest
steps:
Expand All @@ -114,7 +114,7 @@ jobs:
restore-keys: ${{ runner.os }}-go-

- name: ${{ matrix.suite }} tests
run: go test -v github.com/jfrog/jfrog-client-go/tests --timeout 0 --test.${{ matrix.suite }} --rt.url=${{ secrets.PLATFORM_URL }}/artifactory --ds.url=${{ secrets.PLATFORM_URL }}/distribution --xr.url=${{ secrets.PLATFORM_URL }}/xray --access.url=${{ secrets.PLATFORM_URL }}/access --rt.user=${{ secrets.PLATFORM_USER }} --rt.password=${{ secrets.PLATFORM_PASSWORD }} --access.token=${{ secrets.PLATFORM_ADMIN_TOKEN }} --ci.runId=${{ runner.os }}-${{ matrix.suite }}
run: go test -v github.com/jfrog/jfrog-client-go/tests --timeout 0 --test.${{ matrix.suite }} --rt.url=${{ secrets.PLATFORM_URL }}/artifactory --ds.url=${{ secrets.PLATFORM_URL }}/distribution --xr.url=${{ secrets.PLATFORM_URL }}/xray --xsc.url=${{ secrets.PLATFORM_URL }}/xsc --access.url=${{ secrets.PLATFORM_URL }}/access --rt.user=${{ secrets.PLATFORM_USER }} --rt.password=${{ secrets.PLATFORM_PASSWORD }} --access.token=${{ secrets.PLATFORM_ADMIN_TOKEN }} --ci.runId=${{ runner.os }}-${{ matrix.suite }}

JFrog-Client-Go-Pipelines-Tests:
needs: Pretest
Expand Down
108 changes: 98 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,17 @@
- [Delete Violations Report](#delete-violations-report)
- [Get Artifact Summary](#get-artifact-summary)
- [Get Entitlement info](#get-entitlement-info)
- [Using XSC Service](#using-xsc-service)
- [Check if xsc is enabled](#check-if-xsc-is-enabled)
- [Send git info details to xsc](#send-git-info-details-to-xsc)
- [XSC APIs](#xsc-apis)
- [Creating XSC Service Manager](#creating-xray-service-manager)
- [Creating XSC Details](#creating-xsc-details)
- [Creating XSC Service Config](#creating-xsc-service-config)
- [Creating New XSC Service Manager](#creating-new-xsc-service-manager)
- [Using XSC Services](#using-xsc-services)
- [Fetching XSC's Version](#fetching-xscs-version)
- [Report XSC analytics metrics](#report-xsc-analytics-metrics)
- [Add analytics general event](#add-analytics-general-event)
- [Update analytics general event](#update-analytics-general-event)
- [Get analytics general event](#get-analytics-general-event)
- [Pipelines APIs](#pipelines-apis)
- [Creating Pipelines Service Manager](#creating-pipelines-service-manager)
- [Creating Pipelines Details](#creating-pipelines-details)
Expand Down Expand Up @@ -215,6 +223,7 @@
- [Delete Release Bundle Version](#delete-release-bundle-version)
- [Delete Release Bundle Version Promotion](#delete-release-bundle-version-promotion)
- [Export Release Bundle](#export-release-bundle)
- [Import Release Bundle](#import-release-bundle)
- [Remote Delete Release Bundle](#remote-delete-release-bundle)

## General
Expand Down Expand Up @@ -265,6 +274,7 @@ content of this repository is deleted.
| `-test.artifactory` | Artifactory tests | Artifactory Pro |
| `-test.distribution` | Distribution tests | Artifactory with Distribution |
| `-test.xray` | Xray tests | Artifactory with Xray |
| `-test.xsc` | Xsc tests | Xray with Xsc |
| `-test.pipelines` | Pipelines tests | JFrog Pipelines |
| `-test.access` | Access tests | Artifactory Pro |
| `-test.repositories` | Repositories tests | Artifactory Pro |
Expand All @@ -277,6 +287,7 @@ content of this repository is deleted.
| `-rt.url` | [Default: http://localhost:8081/artifactory] Artifactory URL. |
| `-ds.url` | [Optional] JFrog Distribution URL. |
| `-xr.url` | [Optional] JFrog Xray URL. |
| `-xsc.url` | [Optional] JFrog Xsc URL. |
| `-pipe.url` | [Optional] JFrog Pipelines URL. |
| `-access.url` | [Optional] JFrog Access URL. |
| `-rt.user` | [Default: admin] Artifactory username. |
Expand Down Expand Up @@ -413,6 +424,8 @@ params.SplitCount = 10
// The minimum file size in MiB required to attempt a multi-part upload.
// MinSplitSize default value: 200
params.MinSplitSize = 100
// The upload chunk size in MiB that can be concurrently uploaded during a multi-part upload.
params.ChunkSize = 5
// The min file size in bytes for "checksum deploy".
// "Checksum deploy" is the action of calculating the file checksum locally, before
// the upload, and skipping the actual file transfer if the file already
Expand Down Expand Up @@ -2233,20 +2246,88 @@ artifactSummary, err := xrayManager.ArtifactSummary(artifactSummaryRequest)
isEntitled, err := xrayManager.IsEntitled(featureId)
```
### Using XSC Service
#### Check if xsc is enabled
## XSC APIs
### Creating XSC Service Manager
#### Creating XSC Details
```go
xscDetails := auth.NewXscDetails()
xscDetails.SetUrl("http://localhost:8081/xsc")
xscDetails.SetSshKeyPath("path/to/.ssh/")
xscDetails.SetApiKey("apikey")
xscDetails.SetUser("user")
xscDetails.SetPassword("password")
xscDetails.SetAccessToken("accesstoken")
// if client certificates are required
xscDetails.SetClientCertPath("path/to/.cer")
xscDetails.SetClientCertKeyPath("path/to/.key")
```
#### Creating XSC Service Config
```go
serviceConfig, err := config.NewConfigBuilder().
SetServiceDetails(xscDetails).
SetCertificatesPath(certPath).
// Optionally overwrite the default HTTP retries, which is set to 3.
SetHttpRetries(8).
Build()
```
#### Creating New XSC Service Manager
```go
// Will try to get XSC version. If route is not available, user is not entitled for XSC.
xscVersion, err := scanService.IsXscEnabled()
xscManager, err := xsc.New(serviceConfig)
```
#### Send git info details to xsc
### Using XSC Services
#### Fetching XSC's Version
```go
version, err := xscManager.GetVersion()
```
#### Report XSC analytics metrics
##### Add analytics general event
Sent XSC a new event which contains analytics data, and get multi-scan id back from XSC.
```go
// Details are the git info details (gitRepoUrl, branchName, commitHash are required fields). Returns multi scan id.
multiScanId, err := scanService.SendScanGitInfoContext(details)
event := services.XscAnalyticsGeneralEvent{
XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventType: services.CliEventType,
Product: services.CliProduct,
ProductVersion: "2.53.1",
IsDefaultConfig: false,
JfrogUser: "gail",
OsPlatform: "mac",
OsArchitecture: "arm64",
AnalyzerManagerVersion: "1.1.1",
EventStatus: services.Started,
}}
msi, err := xscManager.AddAnalyticsGeneralEvent(event)
```
##### Update analytics general event
Sent XSC a finalized analytics metrics event with information matching an existing event's msi.
```go
finalizeEvent := services.XscAnalyticsGeneralEventFinalize{
MultiScanId: msi,
XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventStatus: services.Completed,
TotalFindings: 10,
TotalIgnoredFindings: 5,
TotalScanDuration: "15s",
},
}
err := xscManager.UpdateAnalyticsGeneralEvent(finalizeEvent)
```
##### Get analytics general event
Get a general event from XSC matching the provided msi.
```go
event, err := xscManager.GetAnalyticsGeneralEvent(msi)
```
## Pipelines APIs
Expand Down Expand Up @@ -2627,6 +2708,13 @@ modifictions:= []utils.PathMapping{{
res,err:= serviceManager.ExportReleaseBundle(rbDetails, modifications, queryParams)
```
#### Import Release Bundle Archive
```go
// Imports an exported release bundle archive
res,err:= serviceManager.releaseService.ImportReleaseBundle(filePath)
```
#### Delete Release Bundle Version
```go
Expand Down
5 changes: 5 additions & 0 deletions artifactory/emptymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ type ArtifactoryServicesManager interface {
FileList(relativePath string, optionalParams utils.FileListParams) (*utils.FileListResponse, error)
GetStorageInfo() (*utils.StorageInfo, error)
CalculateStorageInfo() error
ImportReleaseBundle(string) error
}

// By using this struct, you have the option of overriding only some of the ArtifactoryServicesManager
Expand Down Expand Up @@ -465,6 +466,10 @@ func (esm *EmptyArtifactoryServicesManager) CalculateStorageInfo() error {
panic("Failed: Method is not implemented")
}

func (esm *EmptyArtifactoryServicesManager) ImportReleaseBundle(string) error {
panic("Failed: Method is not implemented")
}

// Compile time check of interface implementation.
// Since EmptyArtifactoryServicesManager can be used by tests external to this project, we want this project's tests to fail,
// if EmptyArtifactoryServicesManager stops implementing the ArtifactoryServicesManager interface.
Expand Down
5 changes: 5 additions & 0 deletions artifactory/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,3 +605,8 @@ func (sm *ArtifactoryServicesManagerImp) CalculateStorageInfo() error {
storageService := services.NewStorageService(sm.config.GetServiceDetails(), sm.client)
return storageService.StorageInfoRefresh()
}

func (sm *ArtifactoryServicesManagerImp) ImportReleaseBundle(filePath string) error {
releaseService := services.NewReleaseService(sm.config.GetServiceDetails(), sm.client)
return releaseService.ImportReleaseBundle(filePath)
}
78 changes: 78 additions & 0 deletions artifactory/services/releasebundle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package services

import (
"encoding/json"
"github.com/jfrog/jfrog-client-go/artifactory/services/utils"
"github.com/jfrog/jfrog-client-go/auth"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
utils2 "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"net/http"
)

const (
conflictErrorMessage = "Bundle already exists"
ReleaseBundleImportRestApiEndpoint = "api/release/import/"
octetStream = "application/octet-stream"
)

type releaseService struct {
client *jfroghttpclient.JfrogHttpClient
ArtDetails auth.ServiceDetails
}

type ErrorResponseWithMessage struct {
Errors []ErrorDetail `json:"errors"`
}

type ErrorDetail struct {
Status int `json:"status"`
Message string `json:"message"`
}

func NewReleaseService(artDetails auth.ServiceDetails, client *jfroghttpclient.JfrogHttpClient) *releaseService {
return &releaseService{client: client, ArtDetails: artDetails}
}

func (rs *releaseService) GetJfrogHttpClient() *jfroghttpclient.JfrogHttpClient {
return rs.client
}

func (rs *releaseService) ImportReleaseBundle(filePath string) (err error) {
// Load desired file
content, err := fileutils.ReadFile(filePath)
if err != nil {
return
}
// Upload file
httpClientsDetails := rs.ArtDetails.CreateHttpClientDetails()

url := utils2.AddTrailingSlashIfNeeded(rs.ArtDetails.GetUrl() + ReleaseBundleImportRestApiEndpoint)

utils.SetContentType(octetStream, &httpClientsDetails.Headers)
var resp *http.Response
var body []byte
log.Info("Uploading archive...")
if resp, body, err = rs.client.SendPost(url, content, &httpClientsDetails); err != nil {
return
}
// When a release bundle already exists, the API returns 400.
// Check the error message, and if it's a conflict, don't fail the operation.
if resp.StatusCode == http.StatusBadRequest {
response := ErrorResponseWithMessage{}
if err = json.Unmarshal(body, &response); err != nil {
return
}
if response.Errors[0].Message == conflictErrorMessage {
log.Warn("Bundle already exists, did not upload a new bundle")
return
}
}
if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusAccepted); err != nil {
return
}
log.Info("Release Bundle Imported Successfully")
return
}
7 changes: 5 additions & 2 deletions artifactory/services/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,8 @@ func (us *UploadService) doUpload(artifact UploadData, targetUrlWithProps, logMs
return
}
if shouldTryMultipart {
if err = us.MultipartUpload.UploadFileConcurrently(artifact.Artifact.LocalPath, artifact.Artifact.TargetPath, fileInfo.Size(), details.Checksum.Sha1, us.Progress, uploadParams.SplitCount); err != nil {
if err = us.MultipartUpload.UploadFileConcurrently(artifact.Artifact.LocalPath, artifact.Artifact.TargetPath,
fileInfo.Size(), details.Checksum.Sha1, us.Progress, uploadParams.SplitCount, uploadParams.ChunkSize); err != nil {
return
}
// Once the file is uploaded to the storage, we finalize the multipart upload by performing a checksum deployment to save the file in Artifactory.
Expand Down Expand Up @@ -709,14 +710,16 @@ type UploadParams struct {
MinChecksumDeploy int64
MinSplitSize int64
SplitCount int
ChunkSize int64
ChecksumsCalcEnabled bool
Archive string
// When using the 'archive' option for upload, we can control the target path inside the uploaded archive using placeholders. This operation determines the TargetPathInArchive value.
TargetPathInArchive string
}

func NewUploadParams() UploadParams {
return UploadParams{CommonParams: &utils.CommonParams{}, MinChecksumDeploy: DefaultMinChecksumDeploy, ChecksumsCalcEnabled: true, MinSplitSize: defaultUploadMinSplit, SplitCount: defaultUploadSplitCount}
return UploadParams{CommonParams: &utils.CommonParams{}, MinChecksumDeploy: DefaultMinChecksumDeploy,
ChecksumsCalcEnabled: true, MinSplitSize: defaultUploadMinSplit, SplitCount: defaultUploadSplitCount, ChunkSize: utils.DefaultUploadChunkSize}
}

func DeepCopyUploadParams(params *UploadParams) UploadParams {
Expand Down
Loading

0 comments on commit 3bfe932

Please sign in to comment.