Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Build Runs API #1081

Merged
merged 2 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions artifactory/emptymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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")
}
Expand Down
5 changes: 5 additions & 0 deletions artifactory/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
7 changes: 7 additions & 0 deletions artifactory/services/buildinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
43 changes: 33 additions & 10 deletions artifactory/services/utils/artifactoryutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 != "" {
Expand All @@ -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
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
26 changes: 26 additions & 0 deletions tests/artifactorybuilds_test.go
Original file line number Diff line number Diff line change
@@ -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)
}