mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-02-05 13:25:19 +02:00
Add step to prepare the version for an artifact (#1343)
This commit is contained in:
parent
f482f439b0
commit
999197b919
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,6 +18,7 @@ targets/
|
||||
documentation/docs-gen
|
||||
|
||||
consumer-test/**/workspace
|
||||
.pipeline/commonPipelineEnvironment
|
||||
|
||||
*.code-workspace
|
||||
/piper
|
||||
|
351
cmd/artifactPrepareVersion.go
Normal file
351
cmd/artifactPrepareVersion.go
Normal file
@ -0,0 +1,351 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/command"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
"github.com/SAP/jenkins-library/pkg/versioning"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
gitConfig "github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
|
||||
)
|
||||
|
||||
type gitRepository interface {
|
||||
CreateTag(string, plumbing.Hash, *git.CreateTagOptions) (*plumbing.Reference, error)
|
||||
CreateRemote(*gitConfig.RemoteConfig) (*git.Remote, error)
|
||||
DeleteRemote(string) error
|
||||
Push(*git.PushOptions) error
|
||||
Remote(string) (*git.Remote, error)
|
||||
ResolveRevision(plumbing.Revision) (*plumbing.Hash, error)
|
||||
Worktree() (*git.Worktree, error)
|
||||
}
|
||||
|
||||
type gitWorktree interface {
|
||||
Add(string) (plumbing.Hash, error)
|
||||
Checkout(*git.CheckoutOptions) error
|
||||
Commit(string, *git.CommitOptions) (plumbing.Hash, error)
|
||||
}
|
||||
|
||||
func getGitWorktree(repository gitRepository) (gitWorktree, error) {
|
||||
return repository.Worktree()
|
||||
}
|
||||
|
||||
func artifactPrepareVersion(config artifactPrepareVersionOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *artifactPrepareVersionCommonPipelineEnvironment) {
|
||||
c := command.Command{}
|
||||
// reroute command output to logging framework
|
||||
c.Stdout(log.Entry().Writer())
|
||||
c.Stderr(log.Entry().Writer())
|
||||
|
||||
// open local .git repository
|
||||
repository, err := openGit()
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Fatal("git repository required - none available")
|
||||
}
|
||||
|
||||
err = runArtifactPrepareVersion(&config, telemetryData, commonPipelineEnvironment, nil, &c, repository, getGitWorktree)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Fatal("artifactPrepareVersion failed")
|
||||
}
|
||||
log.Entry().Info("SUCCESS")
|
||||
}
|
||||
|
||||
var sshAgentAuth = ssh.NewSSHAgentAuth
|
||||
|
||||
func runArtifactPrepareVersion(config *artifactPrepareVersionOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *artifactPrepareVersionCommonPipelineEnvironment, artifact versioning.Artifact, runner execRunner, repository gitRepository, getWorktree func(gitRepository) (gitWorktree, error)) error {
|
||||
|
||||
telemetryData.Custom1Label = "buildTool"
|
||||
telemetryData.Custom1 = config.BuildTool
|
||||
|
||||
// Options for artifact
|
||||
artifactOpts := versioning.Options{
|
||||
GlobalSettingsFile: config.GlobalSettingsFile,
|
||||
M2Path: config.M2Path,
|
||||
ProjectSettingsFile: config.ProjectSettingsFile,
|
||||
}
|
||||
|
||||
var err error
|
||||
if artifact == nil {
|
||||
artifact, err = versioning.GetArtifact(config.BuildTool, config.FilePath, &artifactOpts, runner)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to retrieve artifact")
|
||||
}
|
||||
}
|
||||
|
||||
versioningType := config.VersioningType
|
||||
|
||||
// support former groovy versioning template and translate into new options
|
||||
if len(config.VersioningTemplate) > 0 {
|
||||
versioningType, _, config.IncludeCommitID = templateCompatibility(config.VersioningTemplate)
|
||||
}
|
||||
|
||||
version, err := artifact.GetVersion()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to retrieve version")
|
||||
}
|
||||
log.Entry().Infof("Version before automatic versioning: %v", version)
|
||||
|
||||
gitCommit, err := getGitCommitID(repository)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gitCommitID := gitCommit.String()
|
||||
|
||||
newVersion := version
|
||||
|
||||
if versioningType == "cloud" {
|
||||
versioningTempl, err := versioningTemplate(artifact.VersioningScheme())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get versioning template for scheme '%v'", artifact.VersioningScheme())
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
newVersion, err = calculateNewVersion(versioningTempl, version, gitCommitID, config.IncludeCommitID, now)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to calculate new version")
|
||||
}
|
||||
|
||||
worktree, err := getWorktree(repository)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to retrieve git worktree")
|
||||
}
|
||||
|
||||
// opening repository does not seem to consider already existing files properly
|
||||
// behavior in case we do not run initializeWorktree:
|
||||
// git.Add(".") will add the complete workspace instead of only changed files
|
||||
err = initializeWorktree(gitCommit, worktree)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// only update version in build descriptor if required in order to save prossing time (e.g. maven case)
|
||||
if newVersion != version {
|
||||
err = artifact.SetVersion(newVersion)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to write version")
|
||||
}
|
||||
}
|
||||
|
||||
//ToDo: what about closure in current Groovy step. Discard the possibility or provide extension mechanism?
|
||||
|
||||
// commit changes and push to repository (including new version tag)
|
||||
gitCommitID, err = pushChanges(config, newVersion, repository, worktree, now)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to push changes for version '%v'", newVersion)
|
||||
}
|
||||
}
|
||||
|
||||
log.Entry().Infof("New version: '%v'", newVersion)
|
||||
|
||||
commonPipelineEnvironment.git.commitID = gitCommitID
|
||||
commonPipelineEnvironment.artifactVersion = newVersion
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func openGit() (gitRepository, error) {
|
||||
workdir, _ := os.Getwd()
|
||||
return git.PlainOpen(workdir)
|
||||
}
|
||||
|
||||
func getGitCommitID(repository gitRepository) (plumbing.Hash, error) {
|
||||
commitID, err := repository.ResolveRevision(plumbing.Revision("HEAD"))
|
||||
if err != nil {
|
||||
return plumbing.Hash{}, errors.Wrap(err, "failed to retrieve git commit ID")
|
||||
}
|
||||
return *commitID, nil
|
||||
}
|
||||
|
||||
func versioningTemplate(scheme string) (string, error) {
|
||||
// generally: timestamp acts as build number providing a proper order
|
||||
switch scheme {
|
||||
case "maven":
|
||||
// according to https://www.mojohaus.org/versions-maven-plugin/version-rules.html
|
||||
return "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}_{{.CommitID}}{{end}}{{end}}", nil
|
||||
case "pep440":
|
||||
// according to https://www.python.org/dev/peps/pep-0440/
|
||||
return "{{.Version}}{{if .Timestamp}}.{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}", nil
|
||||
case "semver2":
|
||||
// according to https://semver.org/spec/v2.0.0.html
|
||||
return "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}", nil
|
||||
}
|
||||
return "", fmt.Errorf("versioning scheme '%v' not supported", scheme)
|
||||
}
|
||||
|
||||
func calculateNewVersion(versioningTemplate, currentVersion, commitID string, includeCommitID bool, t time.Time) (string, error) {
|
||||
tmpl, err := template.New("version").Parse(versioningTemplate)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to create version template: %v", versioningTemplate)
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
versionParts := struct {
|
||||
Version string
|
||||
Timestamp string
|
||||
CommitID string
|
||||
}{
|
||||
Version: currentVersion,
|
||||
Timestamp: t.Format("20060102150405"),
|
||||
}
|
||||
|
||||
if includeCommitID {
|
||||
versionParts.CommitID = commitID
|
||||
}
|
||||
|
||||
err = tmpl.Execute(buf, versionParts)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to execute versioning template: %v", versioningTemplate)
|
||||
}
|
||||
|
||||
newVersion := buf.String()
|
||||
if len(newVersion) == 0 {
|
||||
return "", fmt.Errorf("failed calculate version, new version is '%v'", newVersion)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func initializeWorktree(gitCommit plumbing.Hash, worktree gitWorktree) error {
|
||||
// checkout current revision in order to work on that
|
||||
err := worktree.Checkout(&git.CheckoutOptions{Hash: gitCommit, Keep: true})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to initialize worktree")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func pushChanges(config *artifactPrepareVersionOptions, newVersion string, repository gitRepository, worktree gitWorktree, t time.Time) (string, error) {
|
||||
|
||||
var commitID string
|
||||
|
||||
commit, err := addAndCommit(worktree, newVersion, t)
|
||||
if err != nil {
|
||||
return commit.String(), err
|
||||
}
|
||||
|
||||
commitID = commit.String()
|
||||
|
||||
tag := fmt.Sprintf("%v%v", config.TagPrefix, newVersion)
|
||||
_, err = repository.CreateTag(tag, commit, nil)
|
||||
if err != nil {
|
||||
return commitID, err
|
||||
}
|
||||
|
||||
ref := gitConfig.RefSpec(fmt.Sprintf("refs/tags/%v:refs/tags/%v", tag, tag))
|
||||
|
||||
pushOptions := git.PushOptions{
|
||||
RefSpecs: []gitConfig.RefSpec{gitConfig.RefSpec(ref)},
|
||||
}
|
||||
|
||||
currentRemoteOrigin, err := repository.Remote("origin")
|
||||
if err != nil {
|
||||
return commitID, errors.Wrap(err, "failed to retrieve current remote origin")
|
||||
}
|
||||
var updatedRemoteOrigin *git.Remote
|
||||
|
||||
urls := originUrls(repository)
|
||||
if len(urls) == 0 {
|
||||
return commitID, fmt.Errorf("no remote url maintained")
|
||||
}
|
||||
if strings.HasPrefix(urls[0], "http") {
|
||||
if len(config.Username) == 0 || len(config.Password) == 0 {
|
||||
// handling compatibility: try to use ssh in case no credentials are available
|
||||
log.Entry().Info("git username/password missing - switching to ssh")
|
||||
|
||||
remoteURL := convertHTTPToSSHURL(urls[0])
|
||||
|
||||
// update remote origin url to point to ssh url instead of http(s) url
|
||||
err = repository.DeleteRemote("origin")
|
||||
if err != nil {
|
||||
return commitID, errors.Wrap(err, "failed to update remote origin - remove")
|
||||
}
|
||||
updatedRemoteOrigin, err = repository.CreateRemote(&gitConfig.RemoteConfig{Name: "origin", URLs: []string{remoteURL}})
|
||||
if err != nil {
|
||||
return commitID, errors.Wrap(err, "failed to update remote origin - create")
|
||||
}
|
||||
|
||||
pushOptions.Auth, err = sshAgentAuth("git")
|
||||
if err != nil {
|
||||
return commitID, errors.Wrap(err, "failed to retrieve ssh authentication")
|
||||
}
|
||||
log.Entry().Infof("using remote '%v'", remoteURL)
|
||||
} else {
|
||||
pushOptions.Auth = &http.BasicAuth{Username: config.Username, Password: config.Password}
|
||||
}
|
||||
} else {
|
||||
pushOptions.Auth, err = sshAgentAuth("git")
|
||||
if err != nil {
|
||||
return commitID, errors.Wrap(err, "failed to retrieve ssh authentication")
|
||||
}
|
||||
}
|
||||
|
||||
err = repository.Push(&pushOptions)
|
||||
if err != nil {
|
||||
return commitID, err
|
||||
}
|
||||
|
||||
if updatedRemoteOrigin != currentRemoteOrigin {
|
||||
err = repository.DeleteRemote("origin")
|
||||
if err != nil {
|
||||
return commitID, errors.Wrap(err, "failed to restore remote origin - remove")
|
||||
}
|
||||
_, err := repository.CreateRemote(currentRemoteOrigin.Config())
|
||||
if err != nil {
|
||||
return commitID, errors.Wrap(err, "failed to restore remote origin - create")
|
||||
}
|
||||
}
|
||||
|
||||
return commitID, nil
|
||||
}
|
||||
|
||||
func addAndCommit(worktree gitWorktree, newVersion string, t time.Time) (plumbing.Hash, error) {
|
||||
_, err := worktree.Add(".")
|
||||
if err != nil {
|
||||
return plumbing.Hash{}, errors.Wrap(err, "failed to execute 'git add .'")
|
||||
}
|
||||
|
||||
//maybe more options are required: https://github.com/go-git/go-git/blob/master/_examples/commit/main.go
|
||||
commit, err := worktree.Commit(fmt.Sprintf("update version %v", newVersion), &git.CommitOptions{Author: &object.Signature{Name: "Project Piper", When: t}})
|
||||
if err != nil {
|
||||
return commit, errors.Wrap(err, "failed to commit new version")
|
||||
}
|
||||
return commit, nil
|
||||
}
|
||||
|
||||
func originUrls(repository gitRepository) []string {
|
||||
remote, err := repository.Remote("origin")
|
||||
if err != nil || remote == nil {
|
||||
return []string{}
|
||||
}
|
||||
return remote.Config().URLs
|
||||
}
|
||||
|
||||
func convertHTTPToSSHURL(url string) string {
|
||||
sshURL := strings.Replace(url, "https://", "git@", 1)
|
||||
return strings.Replace(sshURL, "/", ":", 1)
|
||||
}
|
||||
|
||||
func templateCompatibility(groovyTemplate string) (versioningType string, useTimestamp bool, useCommitID bool) {
|
||||
useTimestamp = strings.Contains(groovyTemplate, "${timestamp}")
|
||||
useCommitID = strings.Contains(groovyTemplate, "${commitId")
|
||||
|
||||
versioningType = "library"
|
||||
|
||||
if useTimestamp {
|
||||
versioningType = "cloud"
|
||||
}
|
||||
|
||||
return
|
||||
}
|
261
cmd/artifactPrepareVersion_generated.go
Normal file
261
cmd/artifactPrepareVersion_generated.go
Normal file
@ -0,0 +1,261 @@
|
||||
// Code generated by piper's step-generator. DO NOT EDIT.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/piperenv"
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type artifactPrepareVersionOptions struct {
|
||||
BuildTool string `json:"buildTool,omitempty"`
|
||||
DockerVersionSource string `json:"dockerVersionSource,omitempty"`
|
||||
FilePath string `json:"filePath,omitempty"`
|
||||
GitUserEMail string `json:"gitUserEMail,omitempty"`
|
||||
GitUserName string `json:"gitUserName,omitempty"`
|
||||
GlobalSettingsFile string `json:"globalSettingsFile,omitempty"`
|
||||
IncludeCommitID bool `json:"includeCommitId,omitempty"`
|
||||
M2Path string `json:"m2Path,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
ProjectSettingsFile string `json:"projectSettingsFile,omitempty"`
|
||||
TagPrefix string `json:"tagPrefix,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
VersioningTemplate string `json:"versioningTemplate,omitempty"`
|
||||
VersioningType string `json:"versioningType,omitempty"`
|
||||
}
|
||||
|
||||
type artifactPrepareVersionCommonPipelineEnvironment struct {
|
||||
artifactVersion string
|
||||
git struct {
|
||||
commitID string
|
||||
}
|
||||
}
|
||||
|
||||
func (p *artifactPrepareVersionCommonPipelineEnvironment) persist(path, resourceName string) {
|
||||
content := []struct {
|
||||
category string
|
||||
name string
|
||||
value string
|
||||
}{
|
||||
{category: "", name: "artifactVersion", value: p.artifactVersion},
|
||||
{category: "git", name: "commitId", value: p.git.commitID},
|
||||
}
|
||||
|
||||
errCount := 0
|
||||
for _, param := range content {
|
||||
err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(param.category, param.name), param.value)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Error("Error persisting piper environment.")
|
||||
errCount++
|
||||
}
|
||||
}
|
||||
if errCount > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// ArtifactPrepareVersionCommand Prepares and potentially updates the artifact's version before building the artifact.
|
||||
func ArtifactPrepareVersionCommand() *cobra.Command {
|
||||
metadata := artifactPrepareVersionMetadata()
|
||||
var stepConfig artifactPrepareVersionOptions
|
||||
var startTime time.Time
|
||||
var commonPipelineEnvironment artifactPrepareVersionCommonPipelineEnvironment
|
||||
|
||||
var createArtifactPrepareVersionCmd = &cobra.Command{
|
||||
Use: "artifactPrepareVersion",
|
||||
Short: "Prepares and potentially updates the artifact's version before building the artifact.",
|
||||
Long: `Prepares and potentially updates the artifact's version before building the artifact.
|
||||
|
||||
The continuous delivery process requires that each build is done with a unique version number.
|
||||
|
||||
The version generated using this step will contain:
|
||||
|
||||
* Version (major.minor.patch) from descriptor file in master repository is preserved. Developers should be able to autonomously decide on increasing either part of this version number.
|
||||
* Timestamp
|
||||
* CommitId (by default the long version of the hash)
|
||||
|
||||
Optionally, but enabled by default, the new version is pushed as a new tag into the source code repository (e.g. GitHub).
|
||||
If this option is chosen, git credentials and the repository URL needs to be provided.
|
||||
Since you might not want to configure the git credentials in Jenkins, committing and pushing can be disabled using the ` + "`" + `commitVersion` + "`" + ` parameter as described below.
|
||||
If you require strict reproducibility of your builds, this should be used.`,
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
startTime = time.Now()
|
||||
log.SetStepName("artifactPrepareVersion")
|
||||
log.SetVerbose(GeneralConfig.Verbose)
|
||||
return PrepareConfig(cmd, &metadata, "artifactPrepareVersion", &stepConfig, config.OpenPiperFile)
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
telemetryData := telemetry.CustomData{}
|
||||
telemetryData.ErrorCode = "1"
|
||||
handler := func() {
|
||||
commonPipelineEnvironment.persist(GeneralConfig.EnvRootPath, "commonPipelineEnvironment")
|
||||
telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
|
||||
telemetry.Send(&telemetryData)
|
||||
}
|
||||
log.DeferExitHandler(handler)
|
||||
defer handler()
|
||||
telemetry.Initialize(GeneralConfig.NoTelemetry, "artifactPrepareVersion")
|
||||
artifactPrepareVersion(stepConfig, &telemetryData, &commonPipelineEnvironment)
|
||||
telemetryData.ErrorCode = "0"
|
||||
},
|
||||
}
|
||||
|
||||
addArtifactPrepareVersionFlags(createArtifactPrepareVersionCmd, &stepConfig)
|
||||
return createArtifactPrepareVersionCmd
|
||||
}
|
||||
|
||||
func addArtifactPrepareVersionFlags(cmd *cobra.Command, stepConfig *artifactPrepareVersionOptions) {
|
||||
cmd.Flags().StringVar(&stepConfig.BuildTool, "buildTool", os.Getenv("PIPER_buildTool"), "Defines the tool which is used for building the artifact.")
|
||||
cmd.Flags().StringVar(&stepConfig.DockerVersionSource, "dockerVersionSource", os.Getenv("PIPER_dockerVersionSource"), "For Docker only: Specifies the source to be used for for generating the automatic version. * This can either be the version of the base image - as retrieved from the `FROM` statement within the Dockerfile, e.g. `FROM jenkins:2.46.2` * Alternatively the name of an environment variable defined in the Docker image can be used which contains the version number, e.g. `ENV MY_VERSION 1.2.3`")
|
||||
cmd.Flags().StringVar(&stepConfig.FilePath, "filePath", os.Getenv("PIPER_filePath"), "Defines a custom path to the descriptor file. Build tool specific defaults are used (e.g. maven: pom.xml, npm: package.json, mta: mta.yaml)")
|
||||
cmd.Flags().StringVar(&stepConfig.GitUserEMail, "gitUserEMail", os.Getenv("PIPER_gitUserEMail"), "Allows to overwrite the global git setting 'user.email' available on your Jenkins server.")
|
||||
cmd.Flags().StringVar(&stepConfig.GitUserName, "gitUserName", os.Getenv("PIPER_gitUserName"), "Allows to overwrite the global git setting 'user.name' available on your Jenkins server.")
|
||||
cmd.Flags().StringVar(&stepConfig.GlobalSettingsFile, "globalSettingsFile", os.Getenv("PIPER_globalSettingsFile"), "Maven only - Path to the mvn settings file that should be used as global settings file.")
|
||||
cmd.Flags().BoolVar(&stepConfig.IncludeCommitID, "includeCommitId", true, "Defines if the automatically generated version (versioningType 'cloud') should include the commit id hash .")
|
||||
cmd.Flags().StringVar(&stepConfig.M2Path, "m2Path", os.Getenv("PIPER_m2Path"), "Maven only - Path to the location of the local repository that should be used.")
|
||||
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password/token for git authentication")
|
||||
cmd.Flags().StringVar(&stepConfig.ProjectSettingsFile, "projectSettingsFile", os.Getenv("PIPER_projectSettingsFile"), "Maven only - Path to the mvn settings file that should be used as project settings file.")
|
||||
cmd.Flags().StringVar(&stepConfig.TagPrefix, "tagPrefix", "build_", "Defines the prefix which is used for the git tag which is written during the versioning run.")
|
||||
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User name for git authentication")
|
||||
cmd.Flags().StringVar(&stepConfig.VersioningTemplate, "versioningTemplate", os.Getenv("PIPER_versioningTemplate"), "DEPRECATED: Defines the template for the automatic version which will be created")
|
||||
cmd.Flags().StringVar(&stepConfig.VersioningType, "versioningType", "cloud", "Defines the type of versioning (cloud: fully automatic, library: manual, libraryTag (not available yet): automatic based on latest tag)")
|
||||
|
||||
cmd.MarkFlagRequired("buildTool")
|
||||
}
|
||||
|
||||
// retrieve step metadata
|
||||
func artifactPrepareVersionMetadata() config.StepData {
|
||||
var theMetaData = config.StepData{
|
||||
Metadata: config.StepMetadata{
|
||||
Name: "artifactPrepareVersion",
|
||||
Aliases: []config.Alias{{Name: "artifactSetVersion", Deprecated: false}, {Name: "setVersion", Deprecated: true}},
|
||||
},
|
||||
Spec: config.StepSpec{
|
||||
Inputs: config.StepInputs{
|
||||
Parameters: []config.StepParameters{
|
||||
{
|
||||
Name: "buildTool",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: true,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "dockerVersionSource",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "filePath",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "gitUserEMail",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "gitUserName",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "globalSettingsFile",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "maven/globalSettingsFile"}},
|
||||
},
|
||||
{
|
||||
Name: "includeCommitId",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "bool",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "m2Path",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "maven/m2Path"}},
|
||||
},
|
||||
{
|
||||
Name: "password",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "projectSettingsFile",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "maven/projectSettingsFile"}},
|
||||
},
|
||||
{
|
||||
Name: "tagPrefix",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "username",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "versioningTemplate",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "versioningType",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return theMetaData
|
||||
}
|
16
cmd/artifactPrepareVersion_generated_test.go
Normal file
16
cmd/artifactPrepareVersion_generated_test.go
Normal file
@ -0,0 +1,16 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestArtifactPrepareVersionCommand(t *testing.T) {
|
||||
|
||||
testCmd := ArtifactPrepareVersionCommand()
|
||||
|
||||
// only high level testing performed - details are tested in step generation procudure
|
||||
assert.Equal(t, "artifactPrepareVersion", testCmd.Use, "command name incorrect")
|
||||
|
||||
}
|
598
cmd/artifactPrepareVersion_test.go
Normal file
598
cmd/artifactPrepareVersion_test.go
Normal file
@ -0,0 +1,598 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
gitConfig "github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
|
||||
)
|
||||
|
||||
type artifactVersioningMock struct {
|
||||
originalVersion string
|
||||
newVersion string
|
||||
getVersionError string
|
||||
setVersionError string
|
||||
initCalled bool
|
||||
versioningScheme string
|
||||
}
|
||||
|
||||
func (a *artifactVersioningMock) VersioningScheme() string {
|
||||
return a.versioningScheme
|
||||
}
|
||||
|
||||
func (a *artifactVersioningMock) GetVersion() (string, error) {
|
||||
if len(a.getVersionError) > 0 {
|
||||
return "", fmt.Errorf(a.getVersionError)
|
||||
}
|
||||
return a.originalVersion, nil
|
||||
}
|
||||
|
||||
func (a *artifactVersioningMock) SetVersion(version string) error {
|
||||
if len(a.setVersionError) > 0 {
|
||||
return fmt.Errorf(a.setVersionError)
|
||||
}
|
||||
a.newVersion = version
|
||||
return nil
|
||||
}
|
||||
|
||||
type gitRepositoryMock struct {
|
||||
createRemoteConfigs []*gitConfig.RemoteConfig
|
||||
createRemoteCalls int
|
||||
createRemoteError []string
|
||||
deleteRemoteNames []string
|
||||
deleteRemoteCalls int
|
||||
deleteRemoteError []string
|
||||
pushCalled bool
|
||||
pushOptions *git.PushOptions
|
||||
pushError string
|
||||
remote *git.Remote
|
||||
remoteError string
|
||||
revision string
|
||||
revisionHash plumbing.Hash
|
||||
revisionError string
|
||||
tag string
|
||||
tagHash plumbing.Hash
|
||||
tagError string
|
||||
worktree *git.Worktree
|
||||
worktreeError string
|
||||
}
|
||||
|
||||
func (r *gitRepositoryMock) CreateTag(name string, hash plumbing.Hash, opts *git.CreateTagOptions) (*plumbing.Reference, error) {
|
||||
if len(r.tagError) > 0 {
|
||||
return nil, fmt.Errorf(r.tagError)
|
||||
}
|
||||
r.tag = name
|
||||
r.tagHash = hash
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *gitRepositoryMock) CreateRemote(config *gitConfig.RemoteConfig) (*git.Remote, error) {
|
||||
r.createRemoteCalls++
|
||||
if len(r.createRemoteError) >= r.createRemoteCalls && len(r.createRemoteError[r.createRemoteCalls-1]) > 0 {
|
||||
return nil, fmt.Errorf(r.createRemoteError[r.createRemoteCalls-1])
|
||||
}
|
||||
r.createRemoteConfigs = append(r.createRemoteConfigs, config)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *gitRepositoryMock) DeleteRemote(name string) error {
|
||||
r.deleteRemoteCalls++
|
||||
if len(r.deleteRemoteError) >= r.deleteRemoteCalls && len(r.deleteRemoteError[r.deleteRemoteCalls-1]) > 0 {
|
||||
return fmt.Errorf(r.deleteRemoteError[r.deleteRemoteCalls-1])
|
||||
}
|
||||
r.deleteRemoteNames = append(r.deleteRemoteNames, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *gitRepositoryMock) Push(o *git.PushOptions) error {
|
||||
if len(r.pushError) > 0 {
|
||||
return fmt.Errorf(r.pushError)
|
||||
}
|
||||
r.pushCalled = true
|
||||
r.pushOptions = o
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *gitRepositoryMock) Remote(name string) (*git.Remote, error) {
|
||||
if len(r.remoteError) > 0 {
|
||||
return &git.Remote{}, fmt.Errorf(r.remoteError)
|
||||
}
|
||||
return r.remote, nil
|
||||
}
|
||||
|
||||
func (r *gitRepositoryMock) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, error) {
|
||||
if len(r.revisionError) > 0 {
|
||||
return nil, fmt.Errorf(r.revisionError)
|
||||
}
|
||||
r.revision = rev.String()
|
||||
return &r.revisionHash, nil
|
||||
}
|
||||
|
||||
func (r *gitRepositoryMock) Worktree() (*git.Worktree, error) {
|
||||
if len(r.worktreeError) > 0 {
|
||||
return nil, fmt.Errorf(r.worktreeError)
|
||||
}
|
||||
return r.worktree, nil
|
||||
}
|
||||
|
||||
type gitWorktreeMock struct {
|
||||
addPath string
|
||||
addError string
|
||||
checkoutError string
|
||||
checkoutOpts *git.CheckoutOptions
|
||||
commitHash plumbing.Hash
|
||||
commitMsg string
|
||||
commitOpts *git.CommitOptions
|
||||
commitError string
|
||||
}
|
||||
|
||||
func (w *gitWorktreeMock) Add(path string) (plumbing.Hash, error) {
|
||||
if len(w.addError) > 0 {
|
||||
return plumbing.Hash{}, fmt.Errorf(w.addError)
|
||||
}
|
||||
w.addPath = path
|
||||
return plumbing.Hash{}, nil
|
||||
}
|
||||
func (w *gitWorktreeMock) Checkout(opts *git.CheckoutOptions) error {
|
||||
if len(w.checkoutError) > 0 {
|
||||
return fmt.Errorf(w.checkoutError)
|
||||
}
|
||||
w.checkoutOpts = opts
|
||||
return nil
|
||||
}
|
||||
func (w *gitWorktreeMock) Commit(msg string, opts *git.CommitOptions) (plumbing.Hash, error) {
|
||||
if len(w.commitError) > 0 {
|
||||
return plumbing.Hash{}, fmt.Errorf(w.commitError)
|
||||
}
|
||||
w.commitMsg = msg
|
||||
w.commitOpts = opts
|
||||
return w.commitHash, nil
|
||||
}
|
||||
|
||||
func TestRunArtifactPrepareVersion(t *testing.T) {
|
||||
|
||||
t.Run("success case - cloud", func(t *testing.T) {
|
||||
|
||||
config := artifactPrepareVersionOptions{
|
||||
BuildTool: "maven",
|
||||
IncludeCommitID: true,
|
||||
Password: "****",
|
||||
TagPrefix: "v",
|
||||
Username: "testUser",
|
||||
VersioningType: "cloud",
|
||||
}
|
||||
telemetryData := telemetry.CustomData{}
|
||||
|
||||
cpe := artifactPrepareVersionCommonPipelineEnvironment{}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
originalVersion: "1.2.3",
|
||||
versioningScheme: "maven",
|
||||
}
|
||||
|
||||
worktree := gitWorktreeMock{
|
||||
commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{2, 3, 4}),
|
||||
}
|
||||
|
||||
conf := gitConfig.RemoteConfig{Name: "origin", URLs: []string{"https://my.test.server"}}
|
||||
|
||||
repo := gitRepositoryMock{
|
||||
revisionHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}),
|
||||
remote: git.NewRemote(nil, &conf),
|
||||
}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetryData, &cpe, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil })
|
||||
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Contains(t, versioningMock.newVersion, "1.2.3")
|
||||
assert.Contains(t, versioningMock.newVersion, fmt.Sprintf("_%v", repo.revisionHash.String()))
|
||||
|
||||
assert.Equal(t, "HEAD", repo.revision)
|
||||
assert.Contains(t, repo.tag, "v1.2.3")
|
||||
assert.Equal(t, &git.CheckoutOptions{Hash: repo.revisionHash, Keep: true}, worktree.checkoutOpts)
|
||||
assert.True(t, repo.pushCalled)
|
||||
|
||||
assert.Contains(t, cpe.artifactVersion, "1.2.3")
|
||||
assert.Equal(t, worktree.commitHash.String(), cpe.git.commitID)
|
||||
|
||||
assert.Equal(t, telemetry.CustomData{Custom1Label: "buildTool", Custom1: "maven"}, telemetryData)
|
||||
})
|
||||
|
||||
t.Run("success case - compatibility", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{
|
||||
BuildTool: "maven",
|
||||
VersioningType: "cloud",
|
||||
VersioningTemplate: "${version}",
|
||||
}
|
||||
|
||||
cpe := artifactPrepareVersionCommonPipelineEnvironment{}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
originalVersion: "1.2.3",
|
||||
versioningScheme: "maven",
|
||||
}
|
||||
|
||||
worktree := gitWorktreeMock{}
|
||||
repo := gitRepositoryMock{}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &cpe, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil })
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "1.2.3", cpe.artifactVersion)
|
||||
})
|
||||
|
||||
t.Run("success case - library", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{
|
||||
BuildTool: "maven",
|
||||
VersioningType: "library",
|
||||
}
|
||||
|
||||
cpe := artifactPrepareVersionCommonPipelineEnvironment{}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
originalVersion: "1.2.3",
|
||||
versioningScheme: "maven",
|
||||
}
|
||||
|
||||
worktree := gitWorktreeMock{
|
||||
commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{2, 3, 4}),
|
||||
}
|
||||
repo := gitRepositoryMock{
|
||||
revisionHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}),
|
||||
}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &cpe, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil })
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "1.2.3", cpe.artifactVersion)
|
||||
assert.Equal(t, repo.revisionHash.String(), cpe.git.commitID)
|
||||
})
|
||||
|
||||
t.Run("error - failed to retrive version", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
getVersionError: "getVersion error",
|
||||
}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, nil, &versioningMock, nil, nil, nil)
|
||||
assert.EqualError(t, err, "failed to retrieve version: getVersion error")
|
||||
|
||||
})
|
||||
|
||||
t.Run("error - failed to retrive git commit ID", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
originalVersion: "1.2.3",
|
||||
versioningScheme: "maven",
|
||||
}
|
||||
|
||||
repo := gitRepositoryMock{revisionError: "revision error"}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, nil, &versioningMock, nil, &repo, nil)
|
||||
assert.EqualError(t, err, "failed to retrieve git commit ID: revision error")
|
||||
})
|
||||
|
||||
t.Run("error - versioning template", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{
|
||||
VersioningType: "cloud",
|
||||
}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
originalVersion: "1.2.3",
|
||||
versioningScheme: "notSupported",
|
||||
}
|
||||
|
||||
repo := gitRepositoryMock{}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, nil, &versioningMock, nil, &repo, nil)
|
||||
assert.Contains(t, fmt.Sprint(err), "failed to get versioning template for scheme 'notSupported'")
|
||||
})
|
||||
|
||||
t.Run("error - failed to retrieve git worktree", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{
|
||||
VersioningType: "cloud",
|
||||
}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
originalVersion: "1.2.3",
|
||||
versioningScheme: "maven",
|
||||
}
|
||||
|
||||
repo := gitRepositoryMock{}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, nil, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return nil, fmt.Errorf("worktree error") })
|
||||
assert.EqualError(t, err, "failed to retrieve git worktree: worktree error")
|
||||
})
|
||||
|
||||
t.Run("error - failed to initialize git worktree: ", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{
|
||||
VersioningType: "cloud",
|
||||
}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
originalVersion: "1.2.3",
|
||||
versioningScheme: "maven",
|
||||
}
|
||||
|
||||
worktree := gitWorktreeMock{checkoutError: "checkout error"}
|
||||
repo := gitRepositoryMock{}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, nil, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil })
|
||||
assert.EqualError(t, err, "failed to initialize worktree: checkout error")
|
||||
})
|
||||
|
||||
t.Run("error - failed to set version", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{
|
||||
VersioningType: "cloud",
|
||||
}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
originalVersion: "1.2.3",
|
||||
setVersionError: "setVersion error",
|
||||
versioningScheme: "maven",
|
||||
}
|
||||
|
||||
worktree := gitWorktreeMock{}
|
||||
repo := gitRepositoryMock{}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, nil, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil })
|
||||
assert.EqualError(t, err, "failed to write version: setVersion error")
|
||||
})
|
||||
|
||||
t.Run("error - failed to push changes", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{
|
||||
VersioningType: "cloud",
|
||||
}
|
||||
|
||||
versioningMock := artifactVersioningMock{
|
||||
originalVersion: "1.2.3",
|
||||
versioningScheme: "maven",
|
||||
}
|
||||
|
||||
worktree := gitWorktreeMock{addError: "add error"}
|
||||
repo := gitRepositoryMock{}
|
||||
|
||||
err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, nil, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil })
|
||||
assert.Contains(t, fmt.Sprint(err), "failed to push changes for version '1.2.3")
|
||||
})
|
||||
}
|
||||
|
||||
func TestVersioningTemplate(t *testing.T) {
|
||||
tt := []struct {
|
||||
scheme string
|
||||
expected string
|
||||
expectedErr string
|
||||
}{
|
||||
{scheme: "maven", expected: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}_{{.CommitID}}{{end}}{{end}}"},
|
||||
{scheme: "semver2", expected: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}"},
|
||||
{scheme: "pep440", expected: "{{.Version}}{{if .Timestamp}}.{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}"},
|
||||
{scheme: "notSupported", expected: "", expectedErr: "versioning scheme 'notSupported' not supported"},
|
||||
}
|
||||
|
||||
for _, test := range tt {
|
||||
scheme, err := versioningTemplate(test.scheme)
|
||||
assert.Equal(t, test.expected, scheme)
|
||||
if len(test.expectedErr) == 0 {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.EqualError(t, err, test.expectedErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateNewVersion(t *testing.T) {
|
||||
|
||||
currentVersion := "1.2.3"
|
||||
testTime := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
commitID := plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}).String()
|
||||
|
||||
tt := []struct {
|
||||
versioningTemplate string
|
||||
includeCommitID bool
|
||||
expected string
|
||||
expectedErr string
|
||||
}{
|
||||
{versioningTemplate: "", expectedErr: "failed calculate version, new version is ''"},
|
||||
{versioningTemplate: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}", expected: "1.2.3-20200101000000"},
|
||||
{versioningTemplate: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}", includeCommitID: true, expected: "1.2.3-20200101000000+428ecf70bc22df0ba3dcf194b5ce53e769abab07"},
|
||||
}
|
||||
|
||||
for _, test := range tt {
|
||||
version, err := calculateNewVersion(test.versioningTemplate, currentVersion, commitID, test.includeCommitID, testTime)
|
||||
assert.Equal(t, test.expected, version)
|
||||
if len(test.expectedErr) == 0 {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
assert.EqualError(t, err, test.expectedErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPushChanges(t *testing.T) {
|
||||
|
||||
newVersion := "1.2.3"
|
||||
testTime := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
conf := gitConfig.RemoteConfig{Name: "origin", URLs: []string{"https://my.test.server"}}
|
||||
remote := git.NewRemote(nil, &conf)
|
||||
|
||||
t.Run("success - username/password", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{Username: "testUser", Password: "****"}
|
||||
repo := gitRepositoryMock{remote: remote}
|
||||
worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})}
|
||||
|
||||
commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID)
|
||||
assert.Equal(t, "update version 1.2.3", worktree.commitMsg)
|
||||
assert.Equal(t, &git.CommitOptions{Author: &object.Signature{Name: "Project Piper", When: testTime}}, worktree.commitOpts)
|
||||
assert.Equal(t, "1.2.3", repo.tag)
|
||||
assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", repo.tagHash.String())
|
||||
assert.Equal(t, &git.PushOptions{RefSpecs: []gitConfig.RefSpec{"refs/tags/1.2.3:refs/tags/1.2.3"}, Auth: &http.BasicAuth{Username: config.Username, Password: config.Password}}, repo.pushOptions)
|
||||
})
|
||||
|
||||
t.Run("success - ssh fallback", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{}
|
||||
repo := gitRepositoryMock{remote: remote}
|
||||
worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})}
|
||||
|
||||
originalSSHAgentAuth := sshAgentAuth
|
||||
sshAgentAuth = func(u string) (*ssh.PublicKeysCallback, error) { return &ssh.PublicKeysCallback{}, nil }
|
||||
commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime)
|
||||
sshAgentAuth = originalSSHAgentAuth
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID)
|
||||
assert.Equal(t, "update version 1.2.3", worktree.commitMsg)
|
||||
assert.Equal(t, &git.CommitOptions{Author: &object.Signature{Name: "Project Piper", When: testTime}}, worktree.commitOpts)
|
||||
assert.Equal(t, "1.2.3", repo.tag)
|
||||
assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", repo.tagHash.String())
|
||||
assert.Equal(t, &git.PushOptions{RefSpecs: []gitConfig.RefSpec{"refs/tags/1.2.3:refs/tags/1.2.3"}, Auth: &ssh.PublicKeysCallback{}}, repo.pushOptions)
|
||||
})
|
||||
|
||||
t.Run("success - ssh", func(t *testing.T) {
|
||||
confSSH := gitConfig.RemoteConfig{Name: "origin", URLs: []string{"git@my.test.server"}}
|
||||
remoteSSH := git.NewRemote(nil, &confSSH)
|
||||
|
||||
config := artifactPrepareVersionOptions{}
|
||||
repo := gitRepositoryMock{remote: remoteSSH}
|
||||
worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})}
|
||||
|
||||
originalSSHAgentAuth := sshAgentAuth
|
||||
sshAgentAuth = func(u string) (*ssh.PublicKeysCallback, error) { return &ssh.PublicKeysCallback{}, nil }
|
||||
commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime)
|
||||
sshAgentAuth = originalSSHAgentAuth
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID)
|
||||
assert.Equal(t, &git.PushOptions{RefSpecs: []gitConfig.RefSpec{"refs/tags/1.2.3:refs/tags/1.2.3"}, Auth: &ssh.PublicKeysCallback{}}, repo.pushOptions)
|
||||
})
|
||||
|
||||
t.Run("error - git add", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{}
|
||||
repo := gitRepositoryMock{}
|
||||
worktree := gitWorktreeMock{addError: "add error", commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})}
|
||||
|
||||
commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime)
|
||||
assert.Equal(t, "0000000000000000000000000000000000000000", commitID)
|
||||
assert.EqualError(t, err, "failed to execute 'git add .': add error")
|
||||
})
|
||||
|
||||
t.Run("error - commit", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{}
|
||||
repo := gitRepositoryMock{}
|
||||
worktree := gitWorktreeMock{commitError: "commit error", commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})}
|
||||
|
||||
commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime)
|
||||
assert.Equal(t, "0000000000000000000000000000000000000000", commitID)
|
||||
assert.EqualError(t, err, "failed to commit new version: commit error")
|
||||
})
|
||||
|
||||
t.Run("error - create tag", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{}
|
||||
repo := gitRepositoryMock{tagError: "tag error"}
|
||||
worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})}
|
||||
|
||||
commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime)
|
||||
assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID)
|
||||
assert.EqualError(t, err, "tag error")
|
||||
})
|
||||
|
||||
t.Run("error - no remote url", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{}
|
||||
repo := gitRepositoryMock{}
|
||||
worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})}
|
||||
|
||||
commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime)
|
||||
assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID)
|
||||
assert.EqualError(t, err, "no remote url maintained")
|
||||
})
|
||||
|
||||
t.Run("error - ssh fallback", func(t *testing.T) {
|
||||
|
||||
config := artifactPrepareVersionOptions{}
|
||||
worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})}
|
||||
|
||||
sshSuccess := func(u string) (*ssh.PublicKeysCallback, error) { return nil, nil }
|
||||
sshFailure := func(u string) (*ssh.PublicKeysCallback, error) { return nil, fmt.Errorf("ssh error") }
|
||||
|
||||
tt := []struct {
|
||||
repo gitRepositoryMock
|
||||
sshAgentAuth func(string) (*ssh.PublicKeysCallback, error)
|
||||
expectedError string
|
||||
}{
|
||||
{repo: gitRepositoryMock{remote: remote, deleteRemoteError: []string{"delete error"}}, sshAgentAuth: sshSuccess, expectedError: "failed to update remote origin - remove: delete error"},
|
||||
{repo: gitRepositoryMock{remote: remote, createRemoteError: []string{"update error"}}, sshAgentAuth: sshSuccess, expectedError: "failed to update remote origin - create: update error"},
|
||||
{repo: gitRepositoryMock{remote: remote}, sshAgentAuth: sshFailure, expectedError: "failed to retrieve ssh authentication: ssh error"},
|
||||
{repo: gitRepositoryMock{remote: remote, deleteRemoteError: []string{"", "delete error"}}, sshAgentAuth: sshSuccess, expectedError: "failed to restore remote origin - remove: delete error"},
|
||||
{repo: gitRepositoryMock{remote: remote, createRemoteError: []string{"", "update error"}}, sshAgentAuth: sshSuccess, expectedError: "failed to restore remote origin - create: update error"},
|
||||
}
|
||||
|
||||
originalSSHAgentAuth := sshAgentAuth
|
||||
|
||||
for _, test := range tt {
|
||||
sshAgentAuth = test.sshAgentAuth
|
||||
commitID, err := pushChanges(&config, newVersion, &test.repo, &worktree, testTime)
|
||||
sshAgentAuth = originalSSHAgentAuth
|
||||
|
||||
assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID)
|
||||
assert.EqualError(t, err, test.expectedError)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("error - push", func(t *testing.T) {
|
||||
config := artifactPrepareVersionOptions{Username: "testUser", Password: "****"}
|
||||
repo := gitRepositoryMock{remote: remote, pushError: "push error"}
|
||||
worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})}
|
||||
|
||||
commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime)
|
||||
assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID)
|
||||
assert.EqualError(t, err, "push error")
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplateCompatibility(t *testing.T) {
|
||||
tt := []struct {
|
||||
groovy string
|
||||
versioningType string
|
||||
timestamp bool
|
||||
commitID bool
|
||||
}{
|
||||
{groovy: `${version}`, versioningType: "library", timestamp: false, commitID: false},
|
||||
{groovy: `${version}-${timestamp}`, versioningType: "cloud", timestamp: true, commitID: false},
|
||||
{groovy: `${version}-${timestamp}${commitId?"_"+commitId:""`, versioningType: "cloud", timestamp: true, commitID: true},
|
||||
}
|
||||
|
||||
for _, test := range tt {
|
||||
versioningType, timestamp, commitID := templateCompatibility(test.groovy)
|
||||
assert.Equal(t, test.versioningType, versioningType)
|
||||
assert.Equal(t, test.timestamp, timestamp)
|
||||
assert.Equal(t, test.commitID, commitID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertHTTPToSSHURL(t *testing.T) {
|
||||
tt := []struct {
|
||||
httpURL string
|
||||
expected string
|
||||
}{
|
||||
{httpURL: "https://my.test.server/owner/repo.git", expected: "git@my.test.server:owner/repo.git"},
|
||||
}
|
||||
|
||||
for _, test := range tt {
|
||||
assert.Equal(t, test.expected, convertHTTPToSSHURL(test.httpURL))
|
||||
}
|
||||
}
|
@ -45,6 +45,7 @@ var GeneralConfig GeneralConfigOptions
|
||||
// Execute is the starting point of the piper command line tool
|
||||
func Execute() {
|
||||
|
||||
rootCmd.AddCommand(ArtifactPrepareVersionCommand())
|
||||
rootCmd.AddCommand(ConfigCommand())
|
||||
rootCmd.AddCommand(VersionCommand())
|
||||
rootCmd.AddCommand(DetectExecuteScanCommand())
|
||||
|
2
go.mod
2
go.mod
@ -8,6 +8,7 @@ require (
|
||||
github.com/bmatcuk/doublestar v1.2.2
|
||||
github.com/docker/docker v1.4.2-0.20200114201811-16a3519d870b // indirect
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/go-git/go-git/v5 v5.0.0
|
||||
github.com/google/go-cmp v0.3.1
|
||||
github.com/google/go-containerregistry v0.0.0-20200131185320-aec8da010de2
|
||||
github.com/google/go-github/v28 v28.1.1
|
||||
@ -19,6 +20,5 @@ require (
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/testcontainers/testcontainers-go v0.2.0
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.4
|
||||
)
|
||||
|
47
go.sum
47
go.sum
@ -37,9 +37,15 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
@ -75,6 +81,7 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
|
||||
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@ -104,13 +111,27 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
|
||||
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
|
||||
github.com/go-git/go-git/v5 v5.0.0 h1:k5RWPm4iJwYtfWoxIJy4wJX9ON7ihPeZZYC1fLYDnpg=
|
||||
github.com/go-git/go-git/v5 v5.0.0/go.mod h1:oYD8y9kWsGINPFJoLdaScGCN6dlKg23blmClfZwtUVA=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
@ -191,6 +212,9 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
@ -200,6 +224,8 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
@ -213,6 +239,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
@ -223,6 +251,7 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -237,6 +266,8 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@ -283,6 +314,8 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
@ -319,6 +352,8 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo=
|
||||
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
|
||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
|
||||
@ -334,6 +369,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@ -341,6 +377,8 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -373,6 +411,8 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||
@ -393,6 +433,7 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -405,6 +446,8 @@ golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -462,6 +505,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
@ -474,6 +519,8 @@ gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
89
pkg/versioning/maven.go
Normal file
89
pkg/versioning/maven.go
Normal file
@ -0,0 +1,89 @@
|
||||
package versioning
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/command"
|
||||
"github.com/SAP/jenkins-library/pkg/maven"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type mavenExecRunner interface {
|
||||
Stdout(out io.Writer)
|
||||
Stderr(err io.Writer)
|
||||
RunExecutable(e string, p ...string) error
|
||||
}
|
||||
|
||||
type mavenRunner interface {
|
||||
Execute(*maven.ExecuteOptions, mavenExecRunner) (string, error)
|
||||
Evaluate(string, string, mavenExecRunner) (string, error)
|
||||
}
|
||||
|
||||
// Maven ...
|
||||
type Maven struct {
|
||||
PomPath string
|
||||
Runner mavenRunner
|
||||
ExecRunner mavenExecRunner
|
||||
ProjectSettingsFile string
|
||||
GlobalSettingsFile string
|
||||
M2Path string
|
||||
}
|
||||
|
||||
// InitBuildDescriptor ...
|
||||
func (m *Maven) init() {
|
||||
if len(m.PomPath) == 0 {
|
||||
m.PomPath = "pom.xml"
|
||||
}
|
||||
|
||||
if m.ExecRunner == nil {
|
||||
m.ExecRunner = &command.Command{}
|
||||
}
|
||||
}
|
||||
|
||||
// VersioningScheme ...
|
||||
func (m *Maven) VersioningScheme() string {
|
||||
return "maven"
|
||||
}
|
||||
|
||||
// GetVersion ...
|
||||
func (m *Maven) GetVersion() (string, error) {
|
||||
m.init()
|
||||
|
||||
version, err := m.Runner.Evaluate(m.PomPath, "project.version", m.ExecRunner)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "Maven - getting version failed")
|
||||
}
|
||||
//ToDo: how to deal with SNAPSHOT replacement?
|
||||
return version, nil
|
||||
}
|
||||
|
||||
// SetVersion ...
|
||||
func (m *Maven) SetVersion(version string) error {
|
||||
m.init()
|
||||
|
||||
groupID, err := m.Runner.Evaluate(m.PomPath, "project.groupId", m.ExecRunner)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Maven - getting groupId failed")
|
||||
}
|
||||
opts := maven.ExecuteOptions{
|
||||
PomPath: m.PomPath,
|
||||
ProjectSettingsFile: m.ProjectSettingsFile,
|
||||
GlobalSettingsFile: m.GlobalSettingsFile,
|
||||
M2Path: m.M2Path,
|
||||
Goals: []string{"org.codehaus.mojo:versions-maven-plugin:2.7:set"},
|
||||
Defines: []string{
|
||||
fmt.Sprintf("-DnewVersion=%v", version),
|
||||
fmt.Sprintf("-DgroupId=%v", groupID),
|
||||
"-DartifactId=*",
|
||||
"-DoldVersion=*",
|
||||
"-DgenerateBackupPoms=false",
|
||||
},
|
||||
}
|
||||
_, err = m.Runner.Execute(&opts, m.ExecRunner)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Maven - setting version %v failed", version)
|
||||
}
|
||||
return nil
|
||||
}
|
121
pkg/versioning/maven_test.go
Normal file
121
pkg/versioning/maven_test.go
Normal file
@ -0,0 +1,121 @@
|
||||
package versioning
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/maven"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type mavenMockRunner struct {
|
||||
evaluateErrorString string
|
||||
executeErrorString string
|
||||
stdout string
|
||||
opts *maven.ExecuteOptions
|
||||
expression string
|
||||
pomFile string
|
||||
}
|
||||
|
||||
func (m *mavenMockRunner) Evaluate(pomFile, expression string, runner mavenExecRunner) (string, error) {
|
||||
m.pomFile = pomFile
|
||||
m.expression = expression
|
||||
if len(m.evaluateErrorString) > 0 {
|
||||
return "", fmt.Errorf(m.evaluateErrorString)
|
||||
}
|
||||
return m.stdout, nil
|
||||
}
|
||||
|
||||
func (m *mavenMockRunner) Execute(opts *maven.ExecuteOptions, runner mavenExecRunner) (string, error) {
|
||||
m.opts = opts
|
||||
if len(m.executeErrorString) > 0 {
|
||||
return "", fmt.Errorf(m.executeErrorString)
|
||||
}
|
||||
if opts.ReturnStdout {
|
||||
return m.stdout, nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func TestMavenGetVersion(t *testing.T) {
|
||||
t.Run("success case", func(t *testing.T) {
|
||||
runner := mavenMockRunner{
|
||||
stdout: "1.2.3",
|
||||
}
|
||||
mvn := &Maven{
|
||||
Runner: &runner,
|
||||
PomPath: "path/to/pom.xml",
|
||||
}
|
||||
version, err := mvn.GetVersion()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "1.2.3", version)
|
||||
assert.Equal(t, "project.version", runner.expression)
|
||||
assert.Equal(t, "path/to/pom.xml", runner.pomFile)
|
||||
})
|
||||
|
||||
t.Run("error case", func(t *testing.T) {
|
||||
runner := mavenMockRunner{
|
||||
stdout: "1.2.3",
|
||||
evaluateErrorString: "maven eval failed",
|
||||
}
|
||||
mvn := &Maven{
|
||||
Runner: &runner,
|
||||
}
|
||||
version, err := mvn.GetVersion()
|
||||
assert.EqualError(t, err, "Maven - getting version failed: maven eval failed")
|
||||
assert.Equal(t, "", version)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestMavenSetVersion(t *testing.T) {
|
||||
t.Run("success case", func(t *testing.T) {
|
||||
runner := mavenMockRunner{
|
||||
stdout: "testGroup",
|
||||
}
|
||||
mvn := &Maven{
|
||||
Runner: &runner,
|
||||
PomPath: "path/to/pom.xml",
|
||||
ProjectSettingsFile: "project-settings.xml",
|
||||
GlobalSettingsFile: "global-settings.xml",
|
||||
M2Path: "m2/path",
|
||||
}
|
||||
expectedOptions := maven.ExecuteOptions{
|
||||
PomPath: "path/to/pom.xml",
|
||||
Defines: []string{"-DnewVersion=1.2.4", "-DgroupId=testGroup", "-DartifactId=*", "-DoldVersion=*", "-DgenerateBackupPoms=false"},
|
||||
Goals: []string{"org.codehaus.mojo:versions-maven-plugin:2.7:set"},
|
||||
ProjectSettingsFile: "project-settings.xml",
|
||||
GlobalSettingsFile: "global-settings.xml",
|
||||
M2Path: "m2/path",
|
||||
}
|
||||
err := mvn.SetVersion("1.2.4")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &expectedOptions, runner.opts)
|
||||
})
|
||||
|
||||
t.Run("evaluate error", func(t *testing.T) {
|
||||
runner := mavenMockRunner{
|
||||
stdout: "testGroup",
|
||||
evaluateErrorString: "maven eval failed",
|
||||
}
|
||||
mvn := &Maven{
|
||||
Runner: &runner,
|
||||
PomPath: "path/to/pom.xml",
|
||||
}
|
||||
err := mvn.SetVersion("1.2.4")
|
||||
assert.EqualError(t, err, "Maven - getting groupId failed: maven eval failed")
|
||||
})
|
||||
|
||||
t.Run("execute error", func(t *testing.T) {
|
||||
runner := mavenMockRunner{
|
||||
stdout: "testGroup",
|
||||
executeErrorString: "maven exec failed",
|
||||
}
|
||||
mvn := &Maven{
|
||||
Runner: &runner,
|
||||
PomPath: "path/to/pom.xml",
|
||||
}
|
||||
err := mvn.SetVersion("1.2.4")
|
||||
assert.EqualError(t, err, "Maven - setting version 1.2.4 failed: maven exec failed")
|
||||
})
|
||||
}
|
78
pkg/versioning/npm.go
Normal file
78
pkg/versioning/npm.go
Normal file
@ -0,0 +1,78 @@
|
||||
package versioning
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Npm ...
|
||||
type Npm struct {
|
||||
PackageJSONPath string
|
||||
PackageJSONContent map[string]interface{}
|
||||
ReadFile func(string) ([]byte, error)
|
||||
WriteFile func(string, []byte, os.FileMode) error
|
||||
}
|
||||
|
||||
// InitBuildDescriptor ...
|
||||
func (n *Npm) init() {
|
||||
if len(n.PackageJSONPath) == 0 {
|
||||
n.PackageJSONPath = "package.json"
|
||||
}
|
||||
if n.ReadFile == nil {
|
||||
n.ReadFile = ioutil.ReadFile
|
||||
}
|
||||
|
||||
if n.WriteFile == nil {
|
||||
n.WriteFile = ioutil.WriteFile
|
||||
}
|
||||
}
|
||||
|
||||
// VersioningScheme ...
|
||||
func (n *Npm) VersioningScheme() string {
|
||||
return "semver2"
|
||||
}
|
||||
|
||||
// GetVersion ...
|
||||
func (n *Npm) GetVersion() (string, error) {
|
||||
n.init()
|
||||
|
||||
content, err := n.ReadFile(n.PackageJSONPath)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to read file '%v'", n.PackageJSONPath)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(content, &n.PackageJSONContent)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to read package.json content")
|
||||
}
|
||||
|
||||
return fmt.Sprint(n.PackageJSONContent["version"]), nil
|
||||
}
|
||||
|
||||
// SetVersion ...
|
||||
func (n *Npm) SetVersion(version string) error {
|
||||
n.init()
|
||||
|
||||
if n.PackageJSONContent == nil {
|
||||
_, err := n.GetVersion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
n.PackageJSONContent["version"] = version
|
||||
|
||||
content, err := json.MarshalIndent(n.PackageJSONContent, "", " ")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create json content for package.json")
|
||||
}
|
||||
err = n.WriteFile(n.PackageJSONPath, content, 0700)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to write file '%v'", n.PackageJSONPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
73
pkg/versioning/npm_test.go
Normal file
73
pkg/versioning/npm_test.go
Normal file
@ -0,0 +1,73 @@
|
||||
package versioning
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
t.Run("default", func(t *testing.T) {
|
||||
npm := Npm{}
|
||||
npm.init()
|
||||
assert.Equal(t, "package.json", npm.PackageJSONPath)
|
||||
})
|
||||
|
||||
t.Run("no default", func(t *testing.T) {
|
||||
npm := Npm{PackageJSONPath: "my/package.json"}
|
||||
npm.init()
|
||||
assert.Equal(t, "my/package.json", npm.PackageJSONPath)
|
||||
})
|
||||
}
|
||||
|
||||
func TestVersioningScheme(t *testing.T) {
|
||||
npm := Npm{}
|
||||
assert.Equal(t, "semver2", npm.VersioningScheme())
|
||||
}
|
||||
|
||||
func TestGetVersion(t *testing.T) {
|
||||
t.Run("success case", func(t *testing.T) {
|
||||
npm := Npm{
|
||||
PackageJSONPath: "my/package.json",
|
||||
ReadFile: func(filename string) ([]byte, error) { return []byte(`{"name": "test","version": "1.2.3"}`), nil },
|
||||
}
|
||||
version, err := npm.GetVersion()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "1.2.3", version)
|
||||
})
|
||||
|
||||
t.Run("error case", func(t *testing.T) {
|
||||
npm := Npm{
|
||||
PackageJSONPath: "my/package.json",
|
||||
ReadFile: func(filename string) ([]byte, error) { return []byte{}, fmt.Errorf("read error") },
|
||||
}
|
||||
_, err := npm.GetVersion()
|
||||
assert.EqualError(t, err, "failed to read file 'my/package.json': read error")
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetVersion(t *testing.T) {
|
||||
t.Run("success case", func(t *testing.T) {
|
||||
var content []byte
|
||||
npm := Npm{
|
||||
PackageJSONPath: "my/package.json",
|
||||
ReadFile: func(filename string) ([]byte, error) { return []byte(`{"name": "test","version": "1.2.3"}`), nil },
|
||||
WriteFile: func(filename string, filecontent []byte, mode os.FileMode) error { content = filecontent; return nil },
|
||||
}
|
||||
err := npm.SetVersion("1.2.4")
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, string(content), "1.2.4")
|
||||
})
|
||||
|
||||
t.Run("error case", func(t *testing.T) {
|
||||
npm := Npm{
|
||||
PackageJSONPath: "my/package.json",
|
||||
ReadFile: func(filename string) ([]byte, error) { return []byte(`{"name": "test","version": "1.2.3"}`), nil },
|
||||
WriteFile: func(filename string, filecontent []byte, mode os.FileMode) error { return fmt.Errorf("write error") },
|
||||
}
|
||||
err := npm.SetVersion("1.2.4")
|
||||
assert.EqualError(t, err, "failed to write file 'my/package.json': write error")
|
||||
})
|
||||
}
|
54
pkg/versioning/versioning.go
Normal file
54
pkg/versioning/versioning.go
Normal file
@ -0,0 +1,54 @@
|
||||
package versioning
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/maven"
|
||||
)
|
||||
|
||||
// Artifact ...
|
||||
type Artifact interface {
|
||||
VersioningScheme() string
|
||||
GetVersion() (string, error)
|
||||
SetVersion(string) error
|
||||
}
|
||||
|
||||
// Options ...
|
||||
type Options struct {
|
||||
ProjectSettingsFile string
|
||||
GlobalSettingsFile string
|
||||
M2Path string
|
||||
}
|
||||
|
||||
type mvnRunner struct{}
|
||||
|
||||
func (m *mvnRunner) Execute(options *maven.ExecuteOptions, execRunner mavenExecRunner) (string, error) {
|
||||
return maven.Execute(options, execRunner)
|
||||
}
|
||||
func (m *mvnRunner) Evaluate(pomFile, expression string, execRunner mavenExecRunner) (string, error) {
|
||||
return maven.Evaluate(pomFile, expression, execRunner)
|
||||
}
|
||||
|
||||
// GetArtifact ...
|
||||
func GetArtifact(buildTool, buildDescriptorFilePath string, opts *Options, execRunner mavenExecRunner) (Artifact, error) {
|
||||
var artifact Artifact
|
||||
switch buildTool {
|
||||
case "maven":
|
||||
artifact = &Maven{
|
||||
Runner: &mvnRunner{},
|
||||
ExecRunner: execRunner,
|
||||
PomPath: buildDescriptorFilePath,
|
||||
ProjectSettingsFile: opts.ProjectSettingsFile,
|
||||
GlobalSettingsFile: opts.GlobalSettingsFile,
|
||||
M2Path: opts.M2Path,
|
||||
}
|
||||
case "npm":
|
||||
artifact = &Npm{
|
||||
PackageJSONPath: buildDescriptorFilePath,
|
||||
}
|
||||
default:
|
||||
return artifact, fmt.Errorf("build tool '%v' not supported", buildTool)
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
}
|
26
pkg/versioning/versioning_test.go
Normal file
26
pkg/versioning/versioning_test.go
Normal file
@ -0,0 +1,26 @@
|
||||
package versioning
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetArtifact(t *testing.T) {
|
||||
t.Run("maven", func(t *testing.T) {
|
||||
maven, err := GetArtifact("maven", "my/pom.xml", &Options{}, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "maven", maven.VersioningScheme())
|
||||
})
|
||||
|
||||
t.Run("npm", func(t *testing.T) {
|
||||
npm, err := GetArtifact("npm", "my/package.json", &Options{}, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "semver2", npm.VersioningScheme())
|
||||
})
|
||||
|
||||
t.Run("not supported build tool", func(t *testing.T) {
|
||||
_, err := GetArtifact("nosupport", "whatever", &Options{}, nil)
|
||||
assert.EqualError(t, err, "build tool 'nosupport' not supported")
|
||||
})
|
||||
}
|
150
resources/metadata/versioning.yaml
Normal file
150
resources/metadata/versioning.yaml
Normal file
@ -0,0 +1,150 @@
|
||||
metadata:
|
||||
name: artifactPrepareVersion
|
||||
aliases:
|
||||
- name: artifactSetVersion
|
||||
- name: setVersion
|
||||
deprecated: true
|
||||
description: Prepares and potentially updates the artifact's version before building the artifact.
|
||||
longDescription: |-
|
||||
Prepares and potentially updates the artifact's version before building the artifact.
|
||||
|
||||
The continuous delivery process requires that each build is done with a unique version number.
|
||||
|
||||
The version generated using this step will contain:
|
||||
|
||||
* Version (major.minor.patch) from descriptor file in master repository is preserved. Developers should be able to autonomously decide on increasing either part of this version number.
|
||||
* Timestamp
|
||||
* CommitId (by default the long version of the hash)
|
||||
|
||||
Optionally, but enabled by default, the new version is pushed as a new tag into the source code repository (e.g. GitHub).
|
||||
If this option is chosen, git credentials and the repository URL needs to be provided.
|
||||
Since you might not want to configure the git credentials in Jenkins, committing and pushing can be disabled using the `commitVersion` parameter as described below.
|
||||
If you require strict reproducibility of your builds, this should be used.
|
||||
spec:
|
||||
inputs:
|
||||
params:
|
||||
- name: buildTool
|
||||
type: string
|
||||
description: Defines the tool which is used for building the artifact.
|
||||
mandatory: true
|
||||
scope:
|
||||
- GENERAL
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: dockerVersionSource
|
||||
type: string
|
||||
description: "For Docker only: Specifies the source to be used for for generating the automatic version. * This can either be the version of the base image - as retrieved from the `FROM` statement within the Dockerfile, e.g. `FROM jenkins:2.46.2` * Alternatively the name of an environment variable defined in the Docker image can be used which contains the version number, e.g. `ENV MY_VERSION 1.2.3`"
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: filePath
|
||||
type: string
|
||||
description: "Defines a custom path to the descriptor file. Build tool specific defaults are used (e.g. maven: pom.xml, npm: package.json, mta: mta.yaml)"
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: gitUserEMail
|
||||
type: string
|
||||
description: Allows to overwrite the global git setting 'user.email' available on your Jenkins server.
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: gitUserName
|
||||
type: string
|
||||
description: Allows to overwrite the global git setting 'user.name' available on your Jenkins server.
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: globalSettingsFile
|
||||
aliases:
|
||||
- name: maven/globalSettingsFile
|
||||
type: string
|
||||
description: Maven only - Path to the mvn settings file that should be used as global settings file.
|
||||
scope:
|
||||
- GENERAL
|
||||
- STEPS
|
||||
- STAGES
|
||||
- PARAMETERS
|
||||
- name: includeCommitId
|
||||
type: bool
|
||||
description: Defines if the automatically generated version (versioningType 'cloud') should include the commit id hash .
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
default: true
|
||||
- name: m2Path
|
||||
aliases:
|
||||
- name: maven/m2Path
|
||||
type: string
|
||||
description: Maven only - Path to the location of the local repository that should be used.
|
||||
scope:
|
||||
- GENERAL
|
||||
- STEPS
|
||||
- STAGES
|
||||
- PARAMETERS
|
||||
- name: password
|
||||
type: string
|
||||
description: Password/token for git authentication
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: projectSettingsFile
|
||||
aliases:
|
||||
- name: maven/projectSettingsFile
|
||||
type: string
|
||||
description: Maven only - Path to the mvn settings file that should be used as project settings file.
|
||||
scope:
|
||||
- GENERAL
|
||||
- STEPS
|
||||
- STAGES
|
||||
- PARAMETERS
|
||||
- name: tagPrefix
|
||||
type: string
|
||||
description: Defines the prefix which is used for the git tag which is written during the versioning run.
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
default: build_
|
||||
- name: username
|
||||
type: string
|
||||
description: User name for git authentication
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: versioningTemplate
|
||||
type: string
|
||||
description: "DEPRECATED: Defines the template for the automatic version which will be created"
|
||||
mandatory: false
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: versioningType
|
||||
type: string
|
||||
description: "Defines the type of versioning (cloud: fully automatic, library: manual, libraryTag (not available yet): automatic based on latest tag)"
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
default: cloud
|
||||
secrets:
|
||||
- name: gitHttpsCredentialsId
|
||||
type: jenkins
|
||||
- name: gitSshKeyCredentialsId
|
||||
type: jenkins
|
||||
outputs:
|
||||
resources:
|
||||
- name: commonPipelineEnvironment
|
||||
type: piperEnvironment
|
||||
params:
|
||||
- name: artifactVersion
|
||||
- name: git/commitId
|
@ -47,6 +47,7 @@ public class CommonStepsTest extends BasePiperTest{
|
||||
|
||||
// all steps not adopting the usual pattern of working with the script.
|
||||
def whitelistScriptReference = [
|
||||
'artifactPrepareVersion',
|
||||
'commonPipelineEnvironment',
|
||||
'checkmarxExecuteScan',
|
||||
'kubernetesDeploy',
|
||||
@ -111,6 +112,7 @@ public class CommonStepsTest extends BasePiperTest{
|
||||
}
|
||||
|
||||
private static fieldRelatedWhitelist = [
|
||||
'artifactPrepareVersion',
|
||||
'durationMeasure', // only expects parameters via signature
|
||||
'prepareDefaultValues', // special step (infrastructure)
|
||||
'piperPipeline', // special step (infrastructure)
|
||||
|
@ -164,6 +164,37 @@ class PiperExecuteBinTest extends BasePiperTest {
|
||||
assertThat(credentials[1], allOf(hasEntry('credentialsId', 'credToken'), hasEntry('variable', 'PIPER_credToken')))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPiperExecuteBinSSHCredentials() {
|
||||
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{"sshCredentialsId":"sshKey", "tokenCredentialsId":"credToken"}')
|
||||
|
||||
List sshKey = []
|
||||
helper.registerAllowedMethod("sshagent", [List, Closure], {s, c ->
|
||||
sshKey = s
|
||||
c()
|
||||
})
|
||||
|
||||
List stepCredentials = [
|
||||
[type: 'token', id: 'tokenCredentialsId', env: ['PIPER_credToken']],
|
||||
[type: 'ssh', id: 'sshCredentialsId'],
|
||||
]
|
||||
stepRule.step.piperExecuteBin(
|
||||
[
|
||||
juStabUtils: utils,
|
||||
jenkinsUtilsStub: jenkinsUtils,
|
||||
testParam: "This is test content",
|
||||
script: nullScript
|
||||
],
|
||||
'testStep',
|
||||
'metadata/test.yaml',
|
||||
stepCredentials
|
||||
)
|
||||
// asserts
|
||||
assertThat(credentials.size(), is(1))
|
||||
assertThat(credentials[0], allOf(hasEntry('credentialsId', 'credToken'), hasEntry('variable', 'PIPER_credToken')))
|
||||
assertThat(sshKey, is(['sshKey']))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPiperExecuteBinNoDockerNoCredentials() {
|
||||
shellCallRule.setReturnValue('./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/test.yaml\'', '{}')
|
||||
|
16
vars/artifactPrepareVersion.groovy
Normal file
16
vars/artifactPrepareVersion.groovy
Normal file
@ -0,0 +1,16 @@
|
||||
import com.sap.piper.PiperGoUtils
|
||||
import com.sap.piper.Utils
|
||||
import groovy.transform.Field
|
||||
|
||||
import static com.sap.piper.Prerequisites.checkScript
|
||||
|
||||
@Field String STEP_NAME = getClass().getName()
|
||||
@Field String METADATA_FILE = 'metadata/versioning.yaml'
|
||||
|
||||
void call(Map parameters = [:]) {
|
||||
List credentials = [
|
||||
[type: 'ssh', id: 'gitSshKeyCredentialsId'],
|
||||
[type: 'usernamePassword', id: 'gitHttpsCredentialsId', env: ['PIPER_username', 'PIPER_password']],
|
||||
]
|
||||
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
|
||||
}
|
@ -94,6 +94,7 @@ void dockerWrapper(script, config, body) {
|
||||
void credentialWrapper(config, List credentialInfo, body) {
|
||||
if (credentialInfo.size() > 0) {
|
||||
def creds = []
|
||||
def sshCreds = []
|
||||
credentialInfo.each { cred ->
|
||||
switch(cred.type) {
|
||||
case "file":
|
||||
@ -105,12 +106,24 @@ void credentialWrapper(config, List credentialInfo, body) {
|
||||
case "usernamePassword":
|
||||
if (config[cred.id]) creds.add(usernamePassword(credentialsId: config[cred.id], usernameVariable: cred.env[0], passwordVariable: cred.env[1]))
|
||||
break
|
||||
case "ssh":
|
||||
if (config[cred.id]) sshCreds.add(config[cred.id])
|
||||
break
|
||||
default:
|
||||
error ("invalid credential type: ${cred.type}")
|
||||
}
|
||||
}
|
||||
withCredentials(creds) {
|
||||
body()
|
||||
|
||||
if (sshCreds.size() > 0) {
|
||||
sshagent (sshCreds) {
|
||||
withCredentials(creds) {
|
||||
body()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
withCredentials(creds) {
|
||||
body()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
body()
|
||||
|
Loading…
x
Reference in New Issue
Block a user