github.com/jaylevin/jenkins-library@v1.230.4/pkg/versioning/versioning.go (about)

     1  package versioning
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net/http"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/SAP/jenkins-library/pkg/piperutils"
    11  
    12  	"github.com/SAP/jenkins-library/pkg/maven"
    13  )
    14  
    15  // Coordinates to address the artifact coordinates like groupId, artifactId, version and packaging
    16  type Coordinates struct {
    17  	GroupID    string
    18  	ArtifactID string
    19  	Version    string
    20  	Packaging  string
    21  }
    22  
    23  // Artifact defines the versioning operations for various build tools
    24  type Artifact interface {
    25  	VersioningScheme() string
    26  	GetVersion() (string, error)
    27  	SetVersion(string) error
    28  	GetCoordinates() (Coordinates, error)
    29  }
    30  
    31  // Options define build tool specific settings in order to properly retrieve e.g. the version / coordinates of an artifact
    32  type Options struct {
    33  	ProjectSettingsFile  string
    34  	DockerImage          string
    35  	GlobalSettingsFile   string
    36  	M2Path               string
    37  	VersionSource        string
    38  	VersionSection       string
    39  	VersionField         string
    40  	VersioningScheme     string
    41  	HelmUpdateAppVersion bool
    42  }
    43  
    44  // Utils defines the versioning operations for various build tools
    45  type Utils interface {
    46  	Stdout(out io.Writer)
    47  	Stderr(err io.Writer)
    48  	RunExecutable(e string, p ...string) error
    49  
    50  	DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error
    51  	Glob(pattern string) (matches []string, err error)
    52  	FileExists(filename string) (bool, error)
    53  	Copy(src, dest string) (int64, error)
    54  	MkdirAll(path string, perm os.FileMode) error
    55  	FileWrite(path string, content []byte, perm os.FileMode) error
    56  	FileRead(path string) ([]byte, error)
    57  	FileRemove(path string) error
    58  }
    59  
    60  type mvnRunner struct{}
    61  
    62  func (m *mvnRunner) Execute(options *maven.ExecuteOptions, utils maven.Utils) (string, error) {
    63  	return maven.Execute(options, utils)
    64  }
    65  func (m *mvnRunner) Evaluate(options *maven.EvaluateOptions, expression string, utils maven.Utils) (string, error) {
    66  	return maven.Evaluate(options, expression, utils)
    67  }
    68  
    69  var fileExists func(string) (bool, error)
    70  
    71  // GetArtifact returns the build tool specific implementation for retrieving version, etc. of an artifact
    72  func GetArtifact(buildTool, buildDescriptorFilePath string, opts *Options, utils Utils) (Artifact, error) {
    73  	var artifact Artifact
    74  	if fileExists == nil {
    75  		fileExists = piperutils.FileExists
    76  	}
    77  	switch buildTool {
    78  	case "custom":
    79  		var err error
    80  		artifact, err = customArtifact(buildDescriptorFilePath, opts.VersionField, opts.VersionSection, opts.VersioningScheme)
    81  		if err != nil {
    82  			return artifact, err
    83  		}
    84  	case "docker":
    85  		artifact = &Docker{
    86  			utils:            utils,
    87  			options:          opts,
    88  			path:             buildDescriptorFilePath,
    89  			versionSource:    opts.VersionSource,
    90  			versioningScheme: opts.VersioningScheme,
    91  		}
    92  	case "dub":
    93  		if len(buildDescriptorFilePath) == 0 {
    94  			buildDescriptorFilePath = "dub.json"
    95  		}
    96  		artifact = &JSONfile{
    97  			path:         buildDescriptorFilePath,
    98  			versionField: "version",
    99  		}
   100  	case "gradle":
   101  		if len(buildDescriptorFilePath) == 0 {
   102  			buildDescriptorFilePath = "gradle.properties"
   103  		}
   104  		artifact = &Gradle{
   105  			path:         buildDescriptorFilePath,
   106  			versionField: opts.VersionField,
   107  			utils:        utils,
   108  		}
   109  	case "golang":
   110  		if len(buildDescriptorFilePath) == 0 {
   111  			var err error
   112  			buildDescriptorFilePath, err = searchDescriptor([]string{"go.mod", "VERSION", "version.txt"}, fileExists)
   113  			if err != nil {
   114  				return artifact, err
   115  			}
   116  		}
   117  
   118  		switch buildDescriptorFilePath {
   119  		case "go.mod":
   120  			artifact = &GoMod{path: buildDescriptorFilePath, fileExists: fileExists}
   121  			break
   122  		default:
   123  			artifact = &Versionfile{path: buildDescriptorFilePath}
   124  		}
   125  	case "helm":
   126  		artifact = &HelmChart{
   127  			path:             buildDescriptorFilePath,
   128  			utils:            utils,
   129  			updateAppVersion: opts.HelmUpdateAppVersion,
   130  		}
   131  	case "maven":
   132  		if len(buildDescriptorFilePath) == 0 {
   133  			buildDescriptorFilePath = "pom.xml"
   134  		}
   135  		artifact = &Maven{
   136  			runner: &mvnRunner{},
   137  			utils:  utils,
   138  			options: maven.EvaluateOptions{
   139  				PomPath:             buildDescriptorFilePath,
   140  				ProjectSettingsFile: opts.ProjectSettingsFile,
   141  				GlobalSettingsFile:  opts.GlobalSettingsFile,
   142  				M2Path:              opts.M2Path,
   143  			},
   144  		}
   145  	case "mta":
   146  		if len(buildDescriptorFilePath) == 0 {
   147  			buildDescriptorFilePath = "mta.yaml"
   148  		}
   149  		artifact = &YAMLfile{
   150  			path:            buildDescriptorFilePath,
   151  			versionField:    "version",
   152  			artifactIDField: "ID",
   153  		}
   154  	case "npm", "yarn":
   155  		if len(buildDescriptorFilePath) == 0 {
   156  			buildDescriptorFilePath = "package.json"
   157  		}
   158  		artifact = &JSONfile{
   159  			path:         buildDescriptorFilePath,
   160  			versionField: "version",
   161  		}
   162  	case "pip":
   163  		if len(buildDescriptorFilePath) == 0 {
   164  			var err error
   165  			buildDescriptorFilePath, err = searchDescriptor([]string{"setup.py", "version.txt", "VERSION"}, fileExists)
   166  			if err != nil {
   167  				return artifact, err
   168  			}
   169  		}
   170  		artifact = &Pip{
   171  			path:       buildDescriptorFilePath,
   172  			fileExists: fileExists,
   173  		}
   174  	case "sbt":
   175  		if len(buildDescriptorFilePath) == 0 {
   176  			var err error
   177  			buildDescriptorFilePath, err = searchDescriptor([]string{"sbtDescriptor.json", "build.sbt"}, fileExists)
   178  			if err != nil {
   179  				return artifact, err
   180  			}
   181  		}
   182  		artifact = &JSONfile{
   183  			path:         buildDescriptorFilePath,
   184  			versionField: "version",
   185  		}
   186  	default:
   187  		return artifact, fmt.Errorf("build tool '%v' not supported", buildTool)
   188  	}
   189  
   190  	return artifact, nil
   191  }
   192  
   193  func searchDescriptor(supported []string, existsFunc func(string) (bool, error)) (string, error) {
   194  	var descriptor string
   195  	for _, f := range supported {
   196  		exists, _ := existsFunc(f)
   197  		if exists {
   198  			descriptor = f
   199  			break
   200  		}
   201  	}
   202  	if len(descriptor) == 0 {
   203  		return "", fmt.Errorf("no build descriptor available, supported: %v", supported)
   204  	}
   205  	return descriptor, nil
   206  }
   207  
   208  func customArtifact(buildDescriptorFilePath, field, section, scheme string) (Artifact, error) {
   209  	switch filepath.Ext(buildDescriptorFilePath) {
   210  	case ".cfg", ".ini":
   211  		return &INIfile{
   212  			path:             buildDescriptorFilePath,
   213  			versionField:     field,
   214  			versionSection:   section,
   215  			versioningScheme: scheme,
   216  		}, nil
   217  	case ".json":
   218  		return &JSONfile{
   219  			path:         buildDescriptorFilePath,
   220  			versionField: field,
   221  		}, nil
   222  	case ".yaml", ".yml":
   223  		return &YAMLfile{
   224  			path:         buildDescriptorFilePath,
   225  			versionField: field,
   226  		}, nil
   227  	case ".txt", "":
   228  		return &Versionfile{
   229  			path:             buildDescriptorFilePath,
   230  			versioningScheme: scheme,
   231  		}, nil
   232  	default:
   233  		return nil, fmt.Errorf("file type not supported: '%v'", buildDescriptorFilePath)
   234  	}
   235  }