diff --git a/README.md b/README.md index 9f1843577..af5e2f9e4 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ - [Getting Properties from Files in Artifactory](#getting-properties-from-files-in-artifactory) - [Publishing Build Info to Artifactory](#publishing-build-info-to-artifactory) - [Fetching Build Info from Artifactory](#fetching-build-info-from-artifactory) + - [Fetching Build Runs from Artifactory](#fetching-build-runs-from-artifactory) - [Promoting Published Builds in Artifactory](#promoting-published-builds-in-artifactory) - [Promoting a Docker Image in Artifactory](#promoting-a-docker-image-in-artifactory) - [Triggering Build Scanning with JFrog Xray](#triggering-build-scanning-with-jfrog-xray) @@ -715,6 +716,17 @@ buildInfoParams.ProjectKey = "my-project-key" rtManager.GetBuildInfo(buildInfoParams) ``` +#### Fetching Build Runs from Artifactory + +```go +buildInfoParams := services.NewBuildInfoParams{} +buildInfoParams.BuildName = "buildName" +// Optional Artifactory project key +buildInfoParams.ProjectKey = "my-project-key" + +rtManager.GetBuildRuns(buildInfoParams) +``` + #### Promoting Published Builds in Artifactory ```go diff --git a/artifactory/emptymanager.go b/artifactory/emptymanager.go index 6764ca3df..410018caf 100644 --- a/artifactory/emptymanager.go +++ b/artifactory/emptymanager.go @@ -64,6 +64,7 @@ type ArtifactoryServicesManager interface { Ping() ([]byte, error) GetConfig() config.Config GetBuildInfo(params services.BuildInfoParams) (*buildinfo.PublishedBuildInfo, bool, error) + GetBuildRuns(params services.BuildInfoParams) (*buildinfo.BuildRuns, bool, error) CreateAPIKey() (string, error) RegenerateAPIKey() (string, error) GetAPIKey() (string, error) @@ -295,6 +296,10 @@ func (esm *EmptyArtifactoryServicesManager) GetBuildInfo(services.BuildInfoParam panic("Failed: Method is not implemented") } +func (esm *EmptyArtifactoryServicesManager) GetBuildRuns(services.BuildInfoParams) (*buildinfo.BuildRuns, bool, error) { + panic("Failed: Method is not implemented") +} + func (esm *EmptyArtifactoryServicesManager) CreateAPIKey() (string, error) { panic("Failed: Method is not implemented") } diff --git a/artifactory/manager.go b/artifactory/manager.go index 3125fbb55..4ca3e7cfe 100644 --- a/artifactory/manager.go +++ b/artifactory/manager.go @@ -374,6 +374,11 @@ func (sm *ArtifactoryServicesManagerImp) GetBuildInfo(params services.BuildInfoP return buildInfoService.GetBuildInfo(params) } +func (sm *ArtifactoryServicesManagerImp) GetBuildRuns(params services.BuildInfoParams) (*buildinfo.BuildRuns, bool, error) { + buildInfoService := services.NewBuildInfoService(sm.config.GetServiceDetails(), sm.client) + return buildInfoService.GetBuildRuns(params) +} + func (sm *ArtifactoryServicesManagerImp) CreateAPIKey() (string, error) { securityService := services.NewSecurityService(sm.client) securityService.ArtDetails = sm.config.GetServiceDetails() diff --git a/artifactory/services/buildinfo.go b/artifactory/services/buildinfo.go index bd50040ed..71f8643f6 100644 --- a/artifactory/services/buildinfo.go +++ b/artifactory/services/buildinfo.go @@ -53,6 +53,13 @@ func (bis *BuildInfoService) GetBuildInfo(params BuildInfoParams) (pbi *buildinf return utils.GetBuildInfo(params.BuildName, params.BuildNumber, params.ProjectKey, bis) } +// Returns the build runs for the requested build info name. +// If build info was not found (404), returns found=false (with error nil). +// For any other response that isn't 200, an error is returned. +func (bis *BuildInfoService) GetBuildRuns(params BuildInfoParams) (runs *buildinfo.BuildRuns, found bool, err error) { + return utils.GetBuildRuns(params.BuildName, params.ProjectKey, bis) +} + func (bis *BuildInfoService) PublishBuildInfo(build *buildinfo.BuildInfo, projectKey string) (*clientutils.Sha256Summary, error) { summary := clientutils.NewSha256Summary() content, err := json.Marshal(build) diff --git a/artifactory/services/utils/artifactoryutils.go b/artifactory/services/utils/artifactoryutils.go index 50bcbef7b..8ddac2af9 100644 --- a/artifactory/services/utils/artifactoryutils.go +++ b/artifactory/services/utils/artifactoryutils.go @@ -562,9 +562,38 @@ func GetBuildInfo(buildName, buildNumber, projectKey string, flags CommonConf) ( return nil, false, err } - // Get build-info json from Artifactory. - httpClientsDetails := flags.GetArtifactoryDetails().CreateHttpClientDetails() restApi := path.Join("api/build/", name, number) + body, found, err := sendGetBuildInfo(restApi, projectKey, flags) + if err != nil || !found { + return nil, found, err + } + + // Build BuildInfo struct from json. + publishedBuildInfo := &buildinfo.PublishedBuildInfo{} + if err = json.Unmarshal(body, publishedBuildInfo); err != nil { + return nil, true, err + } + + return publishedBuildInfo, true, nil +} + +func GetBuildRuns(buildName, projectKey string, flags CommonConf) (runs *buildinfo.BuildRuns, found bool, err error) { + restApi := path.Join("api/build/", buildName) + body, found, err := sendGetBuildInfo(restApi, projectKey, flags) + if err != nil || !found { + return nil, found, err + } + + buildRuns := &buildinfo.BuildRuns{} + if err = json.Unmarshal(body, buildRuns); err != nil { + return nil, true, err + } + + return buildRuns, true, nil +} + +func sendGetBuildInfo(restApi, projectKey string, flags CommonConf) (body []byte, found bool, err error) { + httpClientsDetails := flags.GetArtifactoryDetails().CreateHttpClientDetails() queryParams := make(map[string]string) if projectKey != "" { @@ -578,6 +607,7 @@ func GetBuildInfo(buildName, buildNumber, projectKey string, flags CommonConf) ( httpClient := flags.GetJfrogHttpClient() log.Debug("Getting build-info from:", requestFullUrl) + resp, body, _, err := httpClient.SendGet(requestFullUrl, true, &httpClientsDetails) if err != nil { return nil, false, err @@ -589,14 +619,7 @@ func GetBuildInfo(buildName, buildNumber, projectKey string, flags CommonConf) ( if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK); err != nil { return nil, false, err } - - // Build BuildInfo struct from json. - publishedBuildInfo := &buildinfo.PublishedBuildInfo{} - if err = json.Unmarshal(body, publishedBuildInfo); err != nil { - return nil, true, err - } - - return publishedBuildInfo, true, nil + return body, true, nil } // Recursively, aggregate all transitive builds of the input buildName and buildNumber. diff --git a/go.mod b/go.mod index f63292663..9368cd44f 100644 --- a/go.mod +++ b/go.mod @@ -58,6 +58,6 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20240909072259-13bf8722d051 +replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20250203111011-4ff16d3d42be // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.7.6-0.20240909061051-2d36ae4bd05a diff --git a/go.sum b/go.sum index e1e7ce3ac..fe2622133 100644 --- a/go.sum +++ b/go.sum @@ -57,8 +57,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI= github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw= -github.com/jfrog/build-info-go v1.10.8 h1:8D4wtvKzLS1hzfDWtfH4OliZLtLCgL62tXCnGWDXuac= -github.com/jfrog/build-info-go v1.10.8/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= +github.com/jfrog/build-info-go v1.8.9-0.20250203111011-4ff16d3d42be h1:sCn4prpANCdmYBAUEBed10qGJUjY8XUElfEM3Xi2OqE= +github.com/jfrog/build-info-go v1.8.9-0.20250203111011-4ff16d3d42be/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s= github.com/jfrog/gofrog v1.7.6/go.mod h1:ntr1txqNOZtHplmaNd7rS4f8jpA5Apx8em70oYEe7+4= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= diff --git a/tests/artifactorybuilds_test.go b/tests/artifactorybuilds_test.go new file mode 100644 index 000000000..8b5484e11 --- /dev/null +++ b/tests/artifactorybuilds_test.go @@ -0,0 +1,26 @@ +package tests + +import ( + "fmt" + "github.com/jfrog/jfrog-client-go/artifactory/services" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetBuildRuns(t *testing.T) { + initArtifactoryTest(t) + + // Create a build + buildName := fmt.Sprintf("%s-%s", "build-run", getRunId()) + err := createDummyBuild(buildName) + assert.NoError(t, err) + + runs, found, err := testBuildInfoService.GetBuildRuns(services.BuildInfoParams{BuildName: buildName}) + assert.NoError(t, err) + assert.True(t, found) + assert.NotEmpty(t, runs.Uri) + assert.NotEmpty(t, runs.BuildsNumbers) + assert.Equal(t, "/"+buildNumber, runs.BuildsNumbers[0].Uri) + assert.NotEmpty(t, runs.BuildsNumbers[0].Started) +}