1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-18 05:18:24 +02:00

ABAP environment: add tag support (#3376)

This commit is contained in:
Daniel Mieg 2021-12-20 17:58:58 +01:00 committed by GitHub
parent fdeffa6ebf
commit 2bb6c21337
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 179 additions and 76 deletions

View File

@ -67,31 +67,29 @@ func runAbapEnvironmentCloneGitRepo(config *abapEnvironmentCloneGitRepoOptions,
log.Entry().Infof("Start cloning %v repositories", len(repositories))
for _, repo := range repositories {
commitString := ""
if repo.CommitID != "" {
commitString = ", commit '" + repo.CommitID + "'"
}
logString := repo.GetCloneLogString()
errorString := "Clone of " + logString + " failed on the ABAP system"
log.Entry().Info("-------------------------")
log.Entry().Info("Start cloning " + repo.Name + ", branch " + repo.Branch + commitString)
log.Entry().Info("Start cloning " + logString)
log.Entry().Info("-------------------------")
// Triggering the Clone of the repository into the ABAP Environment system
uriConnectionDetails, errorTriggerClone := triggerClone(repo, connectionDetails, client)
if errorTriggerClone != nil {
return errors.Wrapf(errorTriggerClone, "Clone of '%s', branch '%s'%s failed on the ABAP System", repo.Name, repo.Branch, commitString)
return errors.Wrapf(errorTriggerClone, errorString)
}
// Polling the status of the repository import on the ABAP Environment system
status, errorPollEntity := abaputils.PollEntity(repo.Name, uriConnectionDetails, client, com.GetPollIntervall())
if errorPollEntity != nil {
return errors.Wrapf(errorPollEntity, "Clone of '%s', branch '%s'%s failed on the ABAP System", repo.Name, repo.Branch, commitString)
return errors.Wrapf(errorPollEntity, errorString)
}
if status == "E" {
return errors.New("Clone of '" + repo.Name + "', branch '" + repo.Branch + "'" + commitString + " failed on the ABAP System")
return errors.New("Clone of " + logString + " failed on the ABAP System")
}
log.Entry().Info(repo.Name + ", branch " + repo.Branch + commitString + " was cloned successfully")
log.Entry().Info("The " + logString + " was cloned successfully")
}
log.Entry().Info("-------------------------")
log.Entry().Info("All repositories were cloned successfully")
@ -122,16 +120,14 @@ func triggerClone(repo abaputils.Repository, cloneConnectionDetails abaputils.Co
return uriConnectionDetails, errors.New("An empty string was passed for the parameter 'repositoryName'")
}
commitQuery, commitString := abaputils.GetCommitStrings(repo.CommitID)
jsonBody := []byte(`{"sc_name":"` + repo.Name + `", "branch_name":"` + repo.Branch + `"` + commitQuery + `}`)
jsonBody := []byte(repo.GetCloneRequestBody())
resp, err = abaputils.GetHTTPResponse("POST", cloneConnectionDetails, jsonBody, client)
if err != nil {
err = abaputils.HandleHTTPError(resp, err, "Could not clone the Repository / Software Component "+repo.Name+", branch "+repo.Branch+commitString, uriConnectionDetails)
err = abaputils.HandleHTTPError(resp, err, "Could not clone the "+repo.GetCloneLogString(), uriConnectionDetails)
return uriConnectionDetails, err
}
defer resp.Body.Close()
log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", repo.Name).WithField("branchName", repo.Branch).WithField("commitID", repo.CommitID).Info("Triggered Clone of Repository / Software Component")
log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", repo.Name).WithField("branchName", repo.Branch).WithField("commitID", repo.CommitID).WithField("Tag", repo.Tag).Info("Triggered Clone of Repository / Software Component")
// Parse Response
var body abaputils.CloneEntity
@ -143,7 +139,7 @@ func triggerClone(repo abaputils.Repository, cloneConnectionDetails abaputils.Co
json.Unmarshal(bodyText, &abapResp)
json.Unmarshal(*abapResp["d"], &body)
if reflect.DeepEqual(abaputils.CloneEntity{}, body) {
log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", repo.Name).WithField("branchName", repo.Branch).WithField("commitID", repo.CommitID).Error("Could not Clone the Repository / Software Component")
log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", repo.Name).WithField("branchName", repo.Branch).WithField("commitID", repo.CommitID).WithField("Tag", repo.Tag).Error("Could not Clone the Repository / Software Component")
err := errors.New("Request to ABAP System not successful")
return uriConnectionDetails, err
}

View File

@ -112,7 +112,7 @@ repositories:
err := runAbapEnvironmentCloneGitRepo(&config, &autils, client)
if assert.Error(t, err, "Expected error") {
assert.Equal(t, "Clone of '"+config.RepositoryName+"', branch '"+config.BranchName+"' failed on the ABAP System: Request to ABAP System not successful", err.Error(), "Expected different error message")
assert.Equal(t, "Clone of repository / software component 'testRepo1', branch 'testBranch1' failed on the ABAP system: Request to ABAP System not successful", err.Error(), "Expected different error message")
}
})
@ -173,7 +173,7 @@ repositories:
err := runAbapEnvironmentCloneGitRepo(&config, &autils, client)
if assert.Error(t, err, "Expected error") {
assert.Equal(t, "Clone of '/DMO/REPO_A', branch 'branchA', commit 'ABCD1234' failed on the ABAP System", err.Error(), "Expected different error message")
assert.Equal(t, "Clone of repository / software component '/DMO/REPO_A', branch 'branchA', commit 'ABCD1234' failed on the ABAP System", err.Error(), "Expected different error message")
}
})
@ -209,7 +209,7 @@ repositories:
err := runAbapEnvironmentCloneGitRepo(&config, &autils, client)
if assert.Error(t, err, "Expected error") {
assert.Equal(t, "Clone of '"+config.RepositoryName+"', branch '"+config.BranchName+"' failed on the ABAP System: Request to ABAP System not successful", err.Error(), "Expected different error message")
assert.Equal(t, "Clone of repository / software component 'testRepo1', branch 'testBranch1' failed on the ABAP system: Request to ABAP System not successful", err.Error(), "Expected different error message")
}
})
@ -244,7 +244,7 @@ repositories:
err := runAbapEnvironmentCloneGitRepo(&config, &autils, client)
if assert.Error(t, err, "Expected error") {
assert.Equal(t, "Clone of '"+config.RepositoryName+"', branch '"+config.BranchName+"' failed on the ABAP System: Request to ABAP System not successful", err.Error(), "Expected different error message")
assert.Equal(t, "Clone of repository / software component 'testRepo1', branch 'testBranch1' failed on the ABAP system: Request to ABAP System not successful", err.Error(), "Expected different error message")
}
})

View File

@ -62,21 +62,18 @@ func runAbapEnvironmentPullGitRepo(options *abapEnvironmentPullGitRepoOptions, c
repositories := []abaputils.Repository{}
err = checkPullRepositoryConfiguration(*options)
if err == nil {
repositories, err = abaputils.GetRepositories(&abaputils.RepositoriesConfig{RepositoryNames: options.RepositoryNames, Repositories: options.Repositories})
handleIgnoreCommit(repositories, options.IgnoreCommit)
}
if err == nil {
err = pullRepositories(repositories, connectionDetails, client, pollIntervall)
}
if err != nil {
return fmt.Errorf("Something failed during the pull of the repositories: %w", err)
return err
}
repositories, err = abaputils.GetRepositories(&abaputils.RepositoriesConfig{RepositoryNames: options.RepositoryNames, Repositories: options.Repositories})
handleIgnoreCommit(repositories, options.IgnoreCommit)
if err != nil {
return err
}
err = pullRepositories(repositories, connectionDetails, client, pollIntervall)
return err
}
func pullRepositories(repositories []abaputils.Repository, pullConnectionDetails abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, pollIntervall time.Duration) (err error) {
@ -95,22 +92,25 @@ func pullRepositories(repositories []abaputils.Repository, pullConnectionDetails
func handlePull(repo abaputils.Repository, pullConnectionDetails abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, pollIntervall time.Duration) (err error) {
startPullLogs(repo)
logString := repo.GetPullLogString()
errorString := "Pull of the " + logString + " failed on the ABAP system"
_, commitString := abaputils.GetCommitStrings(repo.CommitID)
log.Entry().Info("-------------------------")
log.Entry().Info("Start pulling the " + logString)
log.Entry().Info("-------------------------")
uriConnectionDetails, err := triggerPull(repo, pullConnectionDetails, client)
if err != nil {
return errors.Wrapf(err, "Pull of '%s'%s failed on the ABAP System", repo.Name, commitString)
return errors.Wrapf(err, errorString)
}
// Polling the status of the repository import on the ABAP Environment system
status, errorPollEntity := abaputils.PollEntity(repo.Name, uriConnectionDetails, client, pollIntervall)
if errorPollEntity != nil {
return errors.Wrapf(errorPollEntity, "Pull of '%s'%s failed on the ABAP System", repo.Name, commitString)
return errors.Wrapf(errorPollEntity, errorString)
}
if status == "E" {
return errors.New("Pull of '" + repo.Name + "'" + commitString + " failed on the ABAP System")
return errors.New(errorString)
}
log.Entry().Info(repo.Name + " was pulled successfully")
return err
@ -138,15 +138,15 @@ func triggerPull(repo abaputils.Repository, pullConnectionDetails abaputils.Conn
if repo.Name == "" {
return uriConnectionDetails, errors.New("An empty string was passed for the parameter 'repositoryName'")
}
commitQuery, commitString := abaputils.GetCommitStrings(repo.CommitID)
jsonBody := []byte(`{"sc_name":"` + repo.Name + `"` + commitQuery + `}`)
jsonBody := []byte(repo.GetPullRequestBody())
resp, err = abaputils.GetHTTPResponse("POST", pullConnectionDetails, jsonBody, client)
if err != nil {
err = abaputils.HandleHTTPError(resp, err, "Could not pull the Repository / Software Component '"+repo.Name+"'"+commitString, uriConnectionDetails)
err = abaputils.HandleHTTPError(resp, err, "Could not pull the "+repo.GetPullLogString(), uriConnectionDetails)
return uriConnectionDetails, err
}
defer resp.Body.Close()
log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", repo.Name).WithField("commitID", repo.CommitID).Debug("Triggered Pull of Repository / Software Component")
log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", repo.Name).WithField("commitID", repo.CommitID).WithField("Tag", repo.Tag).Debug("Triggered Pull of repository / software component")
// Parse Response
var body abaputils.PullEntity
@ -158,7 +158,7 @@ func triggerPull(repo abaputils.Repository, pullConnectionDetails abaputils.Conn
json.Unmarshal(bodyText, &abapResp)
json.Unmarshal(*abapResp["d"], &body)
if reflect.DeepEqual(abaputils.PullEntity{}, body) {
log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", repo.Name).WithField("commitID", repo.CommitID).Error("Could not pull the Repository / Software Component")
log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", repo.Name).WithField("commitID", repo.CommitID).WithField("Tag", repo.Tag).Error("Could not pull the repository / software component")
err := errors.New("Request to ABAP System not successful")
return uriConnectionDetails, err
}
@ -178,13 +178,6 @@ func checkPullRepositoryConfiguration(options abapEnvironmentPullGitRepoOptions)
return nil
}
func startPullLogs(repo abaputils.Repository) {
_, commitString := abaputils.GetCommitStrings(repo.CommitID)
log.Entry().Info("-------------------------")
log.Entry().Info("Start pulling '" + repo.Name + "'" + commitString)
log.Entry().Info("-------------------------")
}
func finishPullLogs() {
log.Entry().Info("-------------------------")
log.Entry().Info("All repositories were pulled successfully")

View File

@ -48,7 +48,7 @@ func TestPullStep(t *testing.T) {
})
t.Run("Run Step Failure", func(t *testing.T) {
expectedErrorMessage := "Something failed during the pull of the repositories: Checking configuration failed: You have not specified any repository configuration to be pulled into the ABAP Environment System. Please make sure that you specified the repositories that should be pulled either in a dedicated file or via the parameter 'repositoryNames'. For more information please read the User documentation"
expectedErrorMessage := "Checking configuration failed: You have not specified any repository configuration to be pulled into the ABAP Environment System. Please make sure that you specified the repositories that should be pulled either in a dedicated file or via the parameter 'repositoryNames'. For more information please read the User documentation"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
@ -179,7 +179,7 @@ repositories:
err := runAbapEnvironmentPullGitRepo(&config, &autils, client)
if assert.Error(t, err, "Expected error") {
assert.Equal(t, "Something failed during the pull of the repositories: Pull of '/DMO/REPO_A', commit 'ABCD1234' failed on the ABAP System", err.Error(), "Expected different error message")
assert.Equal(t, "Pull of the repository / software component '/DMO/REPO_A', commit 'ABCD1234' failed on the ABAP system", err.Error(), "Expected different error message")
}
})
@ -238,12 +238,12 @@ repositories:
err := runAbapEnvironmentPullGitRepo(&config, &autils, client)
if assert.Error(t, err, "Expected error") {
assert.Equal(t, "Something failed during the pull of the repositories: Pull of '/DMO/REPO_A' failed on the ABAP System", err.Error(), "Expected different error message")
assert.Equal(t, "Pull of the repository / software component '/DMO/REPO_A', tag 'v-1.0.1-build-0001' failed on the ABAP system", err.Error(), "Expected different error message")
}
})
t.Run("Failure case: pull repos from empty file config", func(t *testing.T) {
expectedErrorMessage := "Something failed during the pull of the repositories: Error in config file repositoriesTest.yml, AddonDescriptor doesn't contain any repositories"
expectedErrorMessage := "Error in config file repositoriesTest.yml, AddonDescriptor doesn't contain any repositories"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
@ -291,7 +291,7 @@ repositories:
})
t.Run("Failure case: pull repos from wrong file config", func(t *testing.T) {
expectedErrorMessage := "Something failed during the pull of the repositories: Could not unmarshal repositoriesTest.yml"
expectedErrorMessage := "Could not unmarshal repositoriesTest.yml"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()

View File

@ -49,5 +49,5 @@ stages:
```yaml
repositories:
- name: '/DMO/SWC'
branch: 'master'
branch: 'main'
```

View File

@ -54,15 +54,18 @@ and the configuration file `repositories.yml` would look like this:
```yaml
repositories:
- name: '/DMO/GIT_REPOSITORY'
branch: 'master'
- name: '/DMO/SOFTWARE_COMPONENT'
- name: '/DMO/REPO'
branch: 'main'
- name: '/DMO/REPO_COMMIT'
branch: 'feature'
commitID: 'cd87a3cac2bc946b7629580e58598c3db56a26f8'
- name: '/DMO/REPO_TAG'
branch: 'release'
tag: 'myTag'
```
Using such a configuration file is the recommended approach. Please note that you need to use the YAML data structure as in the example above when using the `repositories.yml` config file.
If you want to pull a specific commit, the `commitID` can be specified optionally for a repository.
If you want to clone a specific commit, either a `commitID` or a `tag` can be specified. If both are specified, the `tag` will be ignored.
## Example: Configuration in the Jenkinsfile

View File

@ -46,14 +46,17 @@ The associated config file, e.g. `repositories.yml` could look as follows:
```yaml
repositories:
- name: '/DMO/GIT_REPOSITORY'
branch: 'master'
- name: '/DMO/GIT_REPO'
branch: 'master'
branch: 'main'
- name: '/DMO/GIT_REPO_COMMIT'
branch: 'feature'
commitID: 'cd87a3cac2bc946b7629580e58598c3db56a26f8'
- name: '/DMO/GIT_REPO_TAG'
branch: 'realease'
tag: 'myTag'
```
It is optional to provide a branch. However, if you also want to use this file for the abapEnvironmentCheckoutBranch step it is recommended to follow the above structure.
If you want to pull a specific commit, the `commitID` can be specified optionally for a repository.
If you want to pull a specific commit, either a `commitID` or a `tag` can be specified. If both are specified, the `tag` will be ignored.
If you want to read the host and credentials from the cloud foundry service key of the respective instance, the configuration could look as follows:

View File

@ -143,13 +143,52 @@ func GetRepositories(config *RepositoriesConfig) ([]Repository, error) {
return repositories, nil
}
//GetCommitStrings for getting the commit_id property for the http request and a string for logging output
func GetCommitStrings(commitID string) (commitQuery string, commitString string) {
if commitID != "" {
commitQuery = `, "commit_id":"` + commitID + `"`
commitString = ", commit '" + commitID + "'"
func (repo *Repository) GetRequestBodyForCommitOrTag() (requestBodyString string) {
if repo.CommitID != "" {
requestBodyString = `, "commit_id":"` + repo.CommitID + `"`
} else if repo.Tag != "" {
requestBodyString = `, "tag_name":"` + repo.Tag + `"`
}
return commitQuery, commitString
return requestBodyString
}
func (repo *Repository) GetLogStringForCommitOrTag() (logString string) {
if repo.CommitID != "" {
logString = ", commit '" + repo.CommitID + "'"
} else if repo.Tag != "" {
logString = ", tag '" + repo.Tag + "'"
}
return logString
}
func (repo *Repository) GetCloneRequestBody() (body string) {
if repo.CommitID != "" && repo.Tag != "" {
log.Entry().WithField("Tag", repo.Tag).WithField("Commit ID", repo.CommitID).Info("The commit ID takes precedence over the tag")
}
requestBodyString := repo.GetRequestBodyForCommitOrTag()
body = `{"sc_name":"` + repo.Name + `", "branch_name":"` + repo.Branch + `"` + requestBodyString + `}`
return body
}
func (repo *Repository) GetCloneLogString() (logString string) {
commitOrTag := repo.GetLogStringForCommitOrTag()
logString = "repository / software component '" + repo.Name + "', branch '" + repo.Branch + "'" + commitOrTag
return logString
}
func (repo *Repository) GetPullRequestBody() (body string) {
if repo.CommitID != "" && repo.Tag != "" {
log.Entry().WithField("Tag", repo.Tag).WithField("Commit ID", repo.CommitID).Info("The commit ID takes precedence over the tag")
}
requestBodyString := repo.GetRequestBodyForCommitOrTag()
body = `{"sc_name":"` + repo.Name + `"` + requestBodyString + `}`
return body
}
func (repo *Repository) GetPullLogString() (logString string) {
commitOrTag := repo.GetLogStringForCommitOrTag()
logString = "repository / software component '" + repo.Name + "'" + commitOrTag
return logString
}
/****************************************

View File

@ -216,15 +216,84 @@ repositories:
})
}
func TestGetCommitStrings(t *testing.T) {
t.Run("CommitID available", func(t *testing.T) {
commitQuery, commitString := GetCommitStrings("ABCD1234")
assert.Equal(t, `, "commit_id":"ABCD1234"`, commitQuery, "Expected different query")
assert.Equal(t, `, commit 'ABCD1234'`, commitString, "Expected different string")
func TestCreateLogStrings(t *testing.T) {
t.Run("Clone LogString Tag and Commit", func(t *testing.T) {
repo := Repository{
Name: "/DMO/REPO",
Branch: "main",
CommitID: "1234567",
Tag: "myTag",
}
logString := repo.GetCloneLogString()
assert.Equal(t, "repository / software component '/DMO/REPO', branch 'main', commit '1234567'", logString, "Expected different string")
})
t.Run("CommitID available", func(t *testing.T) {
commitQuery, commitString := GetCommitStrings("")
assert.Equal(t, ``, commitQuery, "Expected empty query")
assert.Equal(t, ``, commitString, "Expected empty string")
t.Run("Clone LogString Tag", func(t *testing.T) {
repo := Repository{
Name: "/DMO/REPO",
Branch: "main",
Tag: "myTag",
}
logString := repo.GetCloneLogString()
assert.Equal(t, "repository / software component '/DMO/REPO', branch 'main', tag 'myTag'", logString, "Expected different string")
})
t.Run("Pull LogString Tag and Commit", func(t *testing.T) {
repo := Repository{
Name: "/DMO/REPO",
Branch: "main",
CommitID: "1234567",
Tag: "myTag",
}
logString := repo.GetPullLogString()
assert.Equal(t, "repository / software component '/DMO/REPO', commit '1234567'", logString, "Expected different string")
})
t.Run("Pull LogString Tag", func(t *testing.T) {
repo := Repository{
Name: "/DMO/REPO",
Branch: "main",
Tag: "myTag",
}
logString := repo.GetPullLogString()
assert.Equal(t, "repository / software component '/DMO/REPO', tag 'myTag'", logString, "Expected different string")
})
}
func TestCreateRequestBodies(t *testing.T) {
t.Run("Clone Body Tag and Commit", func(t *testing.T) {
repo := Repository{
Name: "/DMO/REPO",
Branch: "main",
CommitID: "1234567",
Tag: "myTag",
}
body := repo.GetCloneRequestBody()
assert.Equal(t, `{"sc_name":"/DMO/REPO", "branch_name":"main", "commit_id":"1234567"}`, body, "Expected different body")
})
t.Run("Clone Body Tag", func(t *testing.T) {
repo := Repository{
Name: "/DMO/REPO",
Branch: "main",
Tag: "myTag",
}
body := repo.GetCloneRequestBody()
assert.Equal(t, `{"sc_name":"/DMO/REPO", "branch_name":"main", "tag_name":"myTag"}`, body, "Expected different body")
})
t.Run("Pull Body Tag and Commit", func(t *testing.T) {
repo := Repository{
Name: "/DMO/REPO",
Branch: "main",
CommitID: "1234567",
Tag: "myTag",
}
body := repo.GetPullRequestBody()
assert.Equal(t, `{"sc_name":"/DMO/REPO", "commit_id":"1234567"}`, body, "Expected different body")
})
t.Run("Pull Body Tag", func(t *testing.T) {
repo := Repository{
Name: "/DMO/REPO",
Branch: "main",
Tag: "myTag",
}
body := repo.GetPullRequestBody()
assert.Equal(t, `{"sc_name":"/DMO/REPO", "tag_name":"myTag"}`, body, "Expected different body")
})
}