Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
RobiNino committed Mar 18, 2024
2 parents 14a4407 + e5506e7 commit 1aca291
Show file tree
Hide file tree
Showing 39 changed files with 1,916 additions and 241 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ jobs:
- name: artifactory tests
run: go test -v github.com/jfrog/jfrog-client-go/tests --timeout 0 --test.${{ matrix.suite }} --ci.runId=${{ runner.os }}-${{ matrix.suite }}

JFrog-Client-Go-Ds-Xr-Tests:
JFrog-Client-Go-Ds-Xr-MPU-Tests:
needs: Pretest
name: ${{ matrix.suite }} ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
suite: [ distribution, xray ]
suite: [ distribution, xray, mpu ]
os: [ ubuntu, windows, macos ]
runs-on: ${{ matrix.os }}-latest
steps:
Expand Down
151 changes: 125 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
- [Deleting a Group](#deleting-a-group)
- [Generating Full System Export](#generating-full-system-export)
- [Getting Info of a Folder in Artifactory](#getting-info-of-a-folder-in-artifactory)
- [Getting Info of a File in Artifactory](#getting-info-of-a-file-in-artifactory)
- [Getting a listing of files and folders within a folder in Artifactory](#getting-a-listing-of-files-and-folders-within-a-folder-in-artifactory)
- [Getting Storage Summary Info of Artifactory](#getting-storage-summary-info-of-artifactory)
- [Triggering Storage Info Recalculation in Artifactory](#triggering-storage-info-recalculation-in-artifactory)
Expand Down Expand Up @@ -202,13 +203,17 @@
- [Creating Lifecycle Service Config](#creating-lifeCycle-service-config)
- [Creating New Lifecycle Service Manager](#creating-new-lifeCycle-service-manager)
- [Using Lifecycle Services](#using-lifeCycle-services)
- [Creating a Release Bundle From AQL](#creating-a-release-bundle-from-aql)
- [Creating a Release Bundle From Artifacts](#creating-a-release-bundle-from-artifacts)
- [Creating a Release Bundle From Published Builds](#creating-a-release-bundle-from-published-builds)
- [Creating a Release Bundle From Release Bundles](#creating-a-release-bundle-from-release-bundles)
- [Promoting a Release Bundle](#promoting-a-release-bundle)
- [Get Release Bundle Creation Status](#get-release-bundle-creation-status)
- [Get Release Bundle Promotion Status](#get-release-bundle-promotion-status)
- [Get Release Bundle Promotions](#get-release-bundle-promotions)
- [Distribute Release Bundle](#distribute-release-bundle)
- [Delete Release Bundle](#delete-release-bundle)
- [Delete Release Bundle Version](#delete-release-bundle-version)
- [Delete Release Bundle Version Promotion](#delete-release-bundle-version-promotion)
- [Remote Delete Release Bundle](#remote-delete-release-bundle)

## General
Expand Down Expand Up @@ -254,14 +259,15 @@ content of this repository is deleted.

#### Test Types

| Type | Description | Prerequisites |
| -------------------- | ------------------ | ----------------------------- |
| `-test.artifactory` | Artifactory tests | Artifactory Pro |
| `-test.distribution` | Distribution tests | Artifactory with Distribution |
| `-test.xray` | Xray tests | Artifactory with Xray |
| `-test.pipelines` | Pipelines tests | JFrog Pipelines |
| `-test.access` | Access tests | Artifactory Pro |
| `-test.repositories` | Access tests | Artifactory Pro |
| Type | Description | Prerequisites |
| -------------------- | ---------------------- | ------------------------------- |
| `-test.artifactory` | Artifactory tests | Artifactory Pro |
| `-test.distribution` | Distribution tests | Artifactory with Distribution |
| `-test.xray` | Xray tests | Artifactory with Xray |
| `-test.pipelines` | Pipelines tests | JFrog Pipelines |
| `-test.access` | Access tests | Artifactory Pro |
| `-test.repositories` | Repositories tests | Artifactory Pro |
| `-test.mpu` | Multipart upload tests | Artifactory Pro with S3 storage |

#### Connection Details

Expand Down Expand Up @@ -400,6 +406,12 @@ params.Symlink = false
params.Exclusions = "(.*)a.zip"
// Retries default value: 3
params.Retries = 5
// The maximum number of parts that can be concurrently uploaded per file during a multi-part upload. Set to 0 to disable multi-part upload.
// SplitCount default value: 5
params.SplitCount = 10
// The minimum file size in MiB required to attempt a multi-part upload.
// MinSplitSize default value: 200
params.MinSplitSize = 100
// 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 @@ -1346,6 +1358,12 @@ err := serviceManager.Export(params)
serviceManager.FolderInfo("repo/path/")
```

#### Getting Info of a File in Artifactory

```go
serviceManager.FileInfo("repo/path/file")
```

#### Getting a listing of files and folders within a folder in Artifactory

```go
Expand Down Expand Up @@ -2230,7 +2248,6 @@ xscVersion, err := scanService.IsXscEnabled()
multiScanId, err := scanService.SendScanGitInfoContext(details)
```
## Pipelines APIs
### Creating Pipelines Service Manager
Expand Down Expand Up @@ -2419,6 +2436,42 @@ lifecycleManager, err := lifecycle.New(serviceConfig)
### Using Lifecycle Services
#### Creating a Release Bundle From AQL
```go
rbDetails := ReleaseBundleDetails{"rbName", "rbVersion"}
queryParams := CommonOptionalQueryParams{}
queryParams.ProjectKey = "project"
queryParams.Async = true

// The GPG/RSA key-pair name given in Artifactory.
signingKeyName = "key-pair"

aqlQuery := `items.find({"repo": "my-repo","path": ".","name": "a2.in"})`
serviceManager.CreateReleaseBundleFromAql(rbDetails, queryParams, signingKeyName, aqlQuery)
```
#### Creating a Release Bundle From Artifacts
```go
rbDetails := ReleaseBundleDetails{"rbName", "rbVersion"}
queryParams := CommonOptionalQueryParams{}
queryParams.ProjectKey = "project"
queryParams.Async = true

// The GPG/RSA key-pair name given in Artifactory.
signingKeyName = "key-pair"

artifacts := CreateFromArtifacts{Artifacts: []ArtifactSource{
{
Path: "repo/path/file",
Sha256: "3e3deb6628658a48cf0d280a2210211f9d977ec2e10a4619b95d5fb85cb10450",
},
}}

serviceManager.CreateReleaseBundleFromArtifacts(rbDetails, queryParams, signingKeyName, artifacts)
```
#### Creating a Release Bundle From Published Builds
```go
Expand Down Expand Up @@ -2501,45 +2554,91 @@ projectKey := "default"
resp, err := serviceManager.GetReleaseBundlePromotionStatus(rbDetails, projectKey, createdMillis, sync)
```
#### Get Release Bundle Promotions
```go
rbDetails := ReleaseBundleDetails{"rbName", "rbVersion"}

optionalQueryParams := lifecycle.GetPromotionsOptionalQueryParams{
Include: "MSG",
Offset: 1,
Limit: 10,
FilterBy: "DEV",
OrderBy: "created",
OrderAsc: true,
ProjectKey: "default",
}

resp, err := serviceManager.GetReleaseBundleVersionPromotions(rbDetails, optionalQueryParams)
```
#### Get Release Bundle Specification
```go
rbDetails := ReleaseBundleDetails{"rbName", "rbVersion"}
resp, err := serviceManager.GetReleaseBundleSpecification(rbDetails)
```
#### Distribute Release Bundle
```go
rbDetails := ReleaseBundleDetails{"rbName", "rbVersion"}
pathMappings := []services.PathMapping{
{
Pattern: "(*)/(*)",
Target: "{1}/target/{2}",
},
}

rules := &distribution.DistributionCommonParams{
SiteName: "*",
CityName: "*",
CountryCodes: []string{"*"},
SiteName: "*",
CityName: "*",
CountryCodes: []string{"*"},
}
dsParams := DistributeReleaseBundleParams{
Sync: true,
AutoCreateRepo: true,
MaxWaitMinutes: 60,
PathMappings: pathMappings,
DistributionRules: []*dmUtils.DistributionCommonParams{
rules,
},
}
params := distribution.NewDistributeReleaseBundleParams("rbName", "rbVersion")
params.DistributionRules = append(params.DistributionRules, rules)

autoCreateRepo := true
resp, err := serviceManager.DistributeReleaseBundle(rbDetails, dsParams)
```
pathMapping := services.PathMapping{
Pattern: "(*)/(*)",
Target: "{1}/target/{2}",
}
#### Delete Release Bundle Version
```go
rbDetails := ReleaseBundleDetails{"rbName", "rbVersion"}
queryParams := CommonOptionalQueryParams{}
queryParams.ProjectKey = "project"
queryParams.Async = true

resp, err := serviceManager.DistributeReleaseBundle(params, autoCreateRepo, pathMapping)
resp, err := serviceManager.DeleteReleaseBundleVersion(rbDetails, queryParams)
```
#### Delete Release Bundle
#### Delete Release Bundle Version Promotion
```go
rbDetails := ReleaseBundleDetails{"rbName", "rbVersion"}

queryParams := CommonOptionalQueryParams{}
queryParams.ProjectKey = "project"
queryParams.Async = true

resp, err := serviceManager.DeleteReleaseBundle(rbDetails, queryParams)
created := "1708612052952"
resp, err := serviceManager.DeleteReleaseBundleVersionPromotion(rbDetails, queryParams, created)
```
#### Remote Delete Release Bundle
```go
rules := &distribution.DistributionCommonParams{
SiteName: "*",
CityName: "*",
CountryCodes: []string{"*"},
SiteName: "*",
CityName: "*",
CountryCodes: []string{"*"},
}
params := distribution.NewDistributeReleaseBundleParams("rbName", "rbVersion")
params.DistributionRules = append(params.DistributionRules, rules)
Expand Down
5 changes: 5 additions & 0 deletions artifactory/emptymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ type ArtifactoryServicesManager interface {
TriggerFederatedRepositoryFullSyncMirror(repoKey string, mirrorUrl string) error
Export(params services.ExportParams) error
FolderInfo(relativePath string) (*utils.FolderInfo, error)
FileInfo(relativePath string) (*utils.FileInfo, error)
FileList(relativePath string, optionalParams utils.FileListParams) (*utils.FileListResponse, error)
GetStorageInfo() (*utils.StorageInfo, error)
CalculateStorageInfo() error
Expand Down Expand Up @@ -448,6 +449,10 @@ func (esm *EmptyArtifactoryServicesManager) FolderInfo(string) (*utils.FolderInf
panic("Failed: Method is not implemented")
}

func (esm *EmptyArtifactoryServicesManager) FileInfo(string) (*utils.FileInfo, error) {
panic("Failed: Method is not implemented")
}

func (esm *EmptyArtifactoryServicesManager) FileList(string, utils.FileListParams) (*utils.FileListResponse, error) {
panic("Failed: Method is not implemented")
}
Expand Down
7 changes: 7 additions & 0 deletions artifactory/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@ func (sm *ArtifactoryServicesManagerImp) initUploadService() *services.UploadSer
uploadService.ArtDetails = sm.config.GetServiceDetails()
uploadService.DryRun = sm.config.IsDryRun()
uploadService.Progress = sm.progress
httpClientDetails := uploadService.ArtDetails.CreateHttpClientDetails()
uploadService.MultipartUpload = utils.NewMultipartUpload(sm.client, &httpClientDetails, uploadService.ArtDetails.GetUrl())
return uploadService
}

Expand Down Expand Up @@ -584,6 +586,11 @@ func (sm *ArtifactoryServicesManagerImp) FolderInfo(relativePath string) (*utils
return storageService.FolderInfo(relativePath)
}

func (sm *ArtifactoryServicesManagerImp) FileInfo(relativePath string) (*utils.FileInfo, error) {
storageService := services.NewStorageService(sm.config.GetServiceDetails(), sm.client)
return storageService.FileInfo(relativePath)
}

func (sm *ArtifactoryServicesManagerImp) FileList(relativePath string, optionalParams utils.FileListParams) (*utils.FileListResponse, error) {
storageService := services.NewStorageService(sm.config.GetServiceDetails(), sm.client)
return storageService.FileList(relativePath, optionalParams)
Expand Down
2 changes: 2 additions & 0 deletions artifactory/services/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ func (ds *DeleteService) createFileHandlerFunc(result *utils.Result) fileDeleteH
}
log.Info(logMsgPrefix+"Deleting", resultItem.GetItemRelativePath())
if ds.DryRun {
// Mock success count on dry run
result.SuccessCount[threadId]++
return nil
}
httpClientsDetails := ds.GetArtifactoryDetails().CreateHttpClientDetails()
Expand Down
16 changes: 4 additions & 12 deletions artifactory/services/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,19 +440,11 @@ func createLocalSymlink(localPath, localFileName, symlinkArtifact string, symlin
if !fileutils.IsPathExists(symlinkArtifact, false) {
return errorutils.CheckErrorf("symlink validation failed, target doesn't exist: " + symlinkArtifact)
}
file, err := os.Open(symlinkArtifact)
if err = errorutils.CheckError(err); err != nil {
return err
}
defer func() {
err = errors.Join(err, errorutils.CheckError(file.Close()))
}()
checksumInfo, err := biutils.CalcChecksums(file, biutils.SHA1)
if err = errorutils.CheckError(err); err != nil {
return err
var checksums map[biutils.Algorithm]string
if checksums, err = biutils.GetFileChecksums(symlinkArtifact, biutils.SHA1); err != nil {
return errorutils.CheckError(err)
}
sha1 := checksumInfo[biutils.SHA1]
if sha1 != symlinkContentChecksum {
if checksums[biutils.SHA1] != symlinkContentChecksum {
return errorutils.CheckErrorf("symlink validation failed for target: " + symlinkArtifact)
}
}
Expand Down
8 changes: 4 additions & 4 deletions artifactory/services/fspatterns/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,15 @@ func GetRootPath(pattern, target, archiveTarget string, patternType utils.Patter

// When handling symlink we want to simulate the creation of empty file
func CreateSymlinkFileDetails() (*fileutils.FileDetails, error) {
checksumInfo, err := biutils.CalcChecksums(bytes.NewBuffer([]byte(fileutils.SymlinkFileContent)))
checksums, err := biutils.CalcChecksums(bytes.NewBuffer([]byte(fileutils.SymlinkFileContent)))
if err != nil {
return nil, errorutils.CheckError(err)
}

details := new(fileutils.FileDetails)
details.Checksum.Md5 = checksumInfo[biutils.MD5]
details.Checksum.Sha1 = checksumInfo[biutils.SHA1]
details.Checksum.Sha256 = checksumInfo[biutils.SHA256]
details.Checksum.Md5 = checksums[biutils.MD5]
details.Checksum.Sha1 = checksums[biutils.SHA1]
details.Checksum.Sha256 = checksums[biutils.SHA256]
details.Size = int64(0)
return details, nil
}
31 changes: 25 additions & 6 deletions artifactory/services/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,46 @@ func (s *StorageService) GetJfrogHttpClient() *jfroghttpclient.JfrogHttpClient {
return s.client
}

func (s *StorageService) FileInfo(relativePath string) (*utils.FileInfo, error) {
body, err := s.getPathInfo(relativePath)
if err != nil {
return nil, err
}

result := &utils.FileInfo{}
err = json.Unmarshal(body, result)
return result, errorutils.CheckError(err)
}

func (s *StorageService) FolderInfo(relativePath string) (*utils.FolderInfo, error) {
body, err := s.getPathInfo(relativePath)
if err != nil {
return nil, err
}

result := &utils.FolderInfo{}
err = json.Unmarshal(body, result)
return result, errorutils.CheckError(err)
}

func (s *StorageService) getPathInfo(relativePath string) ([]byte, error) {
client := s.GetJfrogHttpClient()
restAPI := path.Join(StorageRestApi, path.Clean(relativePath))
folderUrl, err := clientutils.BuildUrl(s.GetArtifactoryDetails().GetUrl(), restAPI, make(map[string]string))
fullUrl, err := clientutils.BuildUrl(s.GetArtifactoryDetails().GetUrl(), restAPI, make(map[string]string))
if err != nil {
return nil, err
}

httpClientsDetails := s.GetArtifactoryDetails().CreateHttpClientDetails()
resp, body, _, err := client.SendGet(folderUrl, true, &httpClientsDetails)
resp, body, _, err := client.SendGet(fullUrl, true, &httpClientsDetails)
if err != nil {
return nil, err
}
if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK); err != nil {
return nil, err
}
log.Debug("Artifactory response:", resp.Status)

result := &utils.FolderInfo{}
err = json.Unmarshal(body, result)
return result, errorutils.CheckError(err)
return body, err
}

func (s *StorageService) FileList(relativePath string, optionalParams utils.FileListParams) (*utils.FileListResponse, error) {
Expand Down
Loading

0 comments on commit 1aca291

Please sign in to comment.