1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-03-03 15:02:35 +02:00

versioning: gradle (#2319)

* versioning: add gradle

* complete initGetArtifact

* correct error message

* improve init handling
This commit is contained in:
Oliver Nocon 2020-11-06 09:20:08 +01:00 committed by GitHub
parent a19cbd63ee
commit bdf4e8da7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 318 additions and 16 deletions

View File

@ -2,11 +2,14 @@ package versioning
import (
"bytes"
"github.com/SAP/jenkins-library/pkg/command"
"github.com/SAP/jenkins-library/pkg/log"
"io"
"io/ioutil"
"os"
"regexp"
"strings"
"github.com/SAP/jenkins-library/pkg/command"
"github.com/SAP/jenkins-library/pkg/log"
)
type gradleExecRunner interface {
@ -27,9 +30,33 @@ type GradleDescriptor struct {
type Gradle struct {
execRunner gradleExecRunner
gradlePropsOut []byte
path string
propertiesFile *PropertiesFile
versionField string
writeFile func(string, []byte, os.FileMode) error
}
func (g *Gradle) init() error {
if g.writeFile == nil {
g.writeFile = ioutil.WriteFile
}
if g.propertiesFile == nil {
g.propertiesFile = &PropertiesFile{
path: g.path,
versioningScheme: g.VersioningScheme(),
versionField: g.versionField,
writeFile: g.writeFile,
}
err := g.propertiesFile.init()
if err != nil {
return err
}
}
return nil
}
func (g *Gradle) initGetArtifact() error {
if g.execRunner == nil {
g.execRunner = &command.Command{}
}
@ -99,7 +126,7 @@ func (g *Gradle) GetCoordinates() (Coordinates, error) {
// GetArtifactID returns the current ID of the artifact
func (g *Gradle) GetArtifactID() (string, error) {
err := g.init()
err := g.initGetArtifact()
if err != nil {
return "", err
}
@ -113,23 +140,19 @@ func (g *Gradle) GetArtifactID() (string, error) {
// GetVersion returns the current version of the artifact
func (g *Gradle) GetVersion() (string, error) {
versionID := "unspecified"
err := g.init()
if err != nil {
return "", err
}
r := regexp.MustCompile("(?m:^version: (.*))")
match := r.FindString(string(g.gradlePropsOut))
versionIDSlice := strings.Split(match, ` `)
if len(versionIDSlice) > 1 {
versionID = versionIDSlice[1]
}
return versionID, nil
return g.propertiesFile.GetVersion()
}
// SetVersion updates the version of the artifact
func (g *Gradle) SetVersion(version string) error {
return nil
err := g.init()
if err != nil {
return err
}
return g.propertiesFile.SetVersion(version)
}

View File

@ -0,0 +1,54 @@
package versioning
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestGradleGetVersion(t *testing.T) {
t.Run("success case", func(t *testing.T) {
tmpFolder, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal("failed to create temp dir")
}
defer os.RemoveAll(tmpFolder)
gradlePropsFilePath := filepath.Join(tmpFolder, "gradle.properties")
ioutil.WriteFile(gradlePropsFilePath, []byte("version = 1.2.3"), 0666)
gradle := &Gradle{
path: gradlePropsFilePath,
}
version, err := gradle.GetVersion()
assert.NoError(t, err)
assert.Equal(t, "1.2.3", version)
})
}
func TestGradleSetVersion(t *testing.T) {
t.Run("success case", func(t *testing.T) {
tmpFolder, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal("failed to create temp dir")
}
defer os.RemoveAll(tmpFolder)
gradlePropsFilePath := filepath.Join(tmpFolder, "gradle.properties")
ioutil.WriteFile(gradlePropsFilePath, []byte("version = 0.0.1"), 0666)
var content []byte
gradle := &Gradle{
path: gradlePropsFilePath,
writeFile: func(filename string, filecontent []byte, mode os.FileMode) error { content = filecontent; return nil },
}
err = gradle.SetVersion("1.2.3")
assert.NoError(t, err)
assert.Contains(t, string(content), "version = 1.2.3")
})
}

View File

@ -10,7 +10,7 @@ import (
"gopkg.in/ini.v1"
)
// INIfile defines an artifact using a json file for versioning
// INIfile defines an artifact using a ini file for versioning
type INIfile struct {
path string
content *ini.File

View File

@ -0,0 +1,86 @@
package versioning
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"github.com/magiconair/properties"
"github.com/pkg/errors"
)
// PropertiesFile defines an artifact using a properties file for versioning
type PropertiesFile struct {
path string
content *properties.Properties
versioningScheme string
versionField string
writeFile func(string, []byte, os.FileMode) error
}
func (p *PropertiesFile) init() error {
if len(p.versionField) == 0 {
p.versionField = "version"
}
if p.writeFile == nil {
p.writeFile = ioutil.WriteFile
}
if p.content == nil {
var err error
p.content, err = properties.LoadFile(p.path, properties.UTF8)
if err != nil {
return errors.Wrapf(err, "failed to load file %v", p.path)
}
}
return nil
}
// VersioningScheme returns the relevant versioning scheme
func (p *PropertiesFile) VersioningScheme() string {
if len(p.versioningScheme) == 0 {
return "semver2"
}
return p.versioningScheme
}
// GetVersion returns the current version of the artifact with a ini-file-based build descriptor
func (p *PropertiesFile) GetVersion() (string, error) {
err := p.init()
if err != nil {
return "", err
}
version := p.content.GetString(p.versionField, "")
if len(version) == 0 {
return "", fmt.Errorf("no version found in field %v", p.versionField)
}
return version, nil
}
// SetVersion updates the version of the artifact with a ini-file-based build descriptor
func (p *PropertiesFile) SetVersion(version string) error {
err := p.init()
if err != nil {
return err
}
err = p.content.SetValue(p.versionField, version)
if err != nil {
return errors.Wrapf(err, "failed to set version")
}
var propsContent bytes.Buffer
_, err = p.content.Write(&propsContent, properties.UTF8)
if err != nil {
return errors.Wrap(err, "failed to write version")
}
err = p.writeFile(p.path, propsContent.Bytes(), 0666)
if err != nil {
return errors.Wrap(err, "failed to write file")
}
return nil
}
// GetCoordinates returns the coordinates
func (p *PropertiesFile) GetCoordinates() (Coordinates, error) {
return nil, nil
}

View File

@ -0,0 +1,124 @@
package versioning
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/magiconair/properties"
"github.com/stretchr/testify/assert"
)
func TestPropertiesFileGetVersion(t *testing.T) {
t.Run("success case", func(t *testing.T) {
tmpFolder, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal("failed to create temp dir")
}
defer os.RemoveAll(tmpFolder)
propsFilePath := filepath.Join(tmpFolder, "my.props")
ioutil.WriteFile(propsFilePath, []byte("version = 1.2.3"), 0666)
propsfile := PropertiesFile{
path: propsFilePath,
}
version, err := propsfile.GetVersion()
assert.NoError(t, err)
assert.Equal(t, "1.2.3", version)
})
t.Run("success case - custom version field", func(t *testing.T) {
tmpFolder, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal("failed to create temp dir")
}
defer os.RemoveAll(tmpFolder)
propsFilePath := filepath.Join(tmpFolder, "my.props")
ioutil.WriteFile(propsFilePath, []byte("customversion = 1.2.3"), 0666)
propsfile := PropertiesFile{
path: propsFilePath,
versionField: "customversion",
}
version, err := propsfile.GetVersion()
assert.NoError(t, err)
assert.Equal(t, "1.2.3", version)
})
t.Run("error case - file not found", func(t *testing.T) {
tmpFolder, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal("failed to create temp dir")
}
defer os.RemoveAll(tmpFolder)
propsFilePath := filepath.Join(tmpFolder, "my.props")
propsfile := PropertiesFile{
path: propsFilePath,
}
_, err = propsfile.GetVersion()
assert.Contains(t, fmt.Sprint(err), "failed to load")
})
t.Run("error case - no version found", func(t *testing.T) {
tmpFolder, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal("failed to create temp dir")
}
defer os.RemoveAll(tmpFolder)
propsFilePath := filepath.Join(tmpFolder, "my.props")
ioutil.WriteFile(propsFilePath, []byte("versionx = 1.2.3"), 0666)
propsfile := PropertiesFile{
path: propsFilePath,
}
_, err = propsfile.GetVersion()
assert.EqualError(t, err, "no version found in field version")
})
}
func TestPropertiesFileSetVersion(t *testing.T) {
t.Run("success case", func(t *testing.T) {
tmpFolder, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal("failed to create temp dir")
}
defer os.RemoveAll(tmpFolder)
propsFilePath := filepath.Join(tmpFolder, "my.props")
ioutil.WriteFile(propsFilePath, []byte("version = 0.0.1"), 0666)
var content []byte
propsfile := PropertiesFile{
path: propsFilePath,
writeFile: func(filename string, filecontent []byte, mode os.FileMode) error { content = filecontent; return nil },
}
err = propsfile.SetVersion("1.2.3")
assert.NoError(t, err)
assert.Contains(t, string(content), "version = 1.2.3")
})
t.Run("error case - write failed", func(t *testing.T) {
props := properties.LoadMap(map[string]string{"version": "0.0.1"})
propsfile := PropertiesFile{
content: props,
path: "gradle.properties",
versionField: "version",
writeFile: func(filename string, filecontent []byte, mode os.FileMode) error { return fmt.Errorf("write error") },
}
err := propsfile.SetVersion("1.2.3")
assert.EqualError(t, err, "failed to write file: write error")
})
}

View File

@ -73,9 +73,12 @@ func GetArtifact(buildTool, buildDescriptorFilePath string, opts *Options, execR
}
case "gradle":
if len(buildDescriptorFilePath) == 0 {
buildDescriptorFilePath = "build.gradle"
buildDescriptorFilePath = "gradle.properties"
}
artifact = &Gradle{
path: buildDescriptorFilePath,
versionField: opts.VersionField,
}
artifact = &Gradle{}
case "golang":
if len(buildDescriptorFilePath) == 0 {
var err error

View File

@ -64,6 +64,18 @@ func TestGetArtifact(t *testing.T) {
assert.EqualError(t, err, "no build descriptor available, supported: [VERSION version.txt go.mod]")
})
t.Run("gradle", func(t *testing.T) {
gradle, err := GetArtifact("gradle", "", &Options{VersionField: "theversion"}, nil)
assert.NoError(t, err)
theType, ok := gradle.(*Gradle)
assert.True(t, ok)
assert.Equal(t, "gradle.properties", theType.path)
assert.Equal(t, "theversion", theType.versionField)
assert.Equal(t, "semver2", gradle.VersioningScheme())
})
t.Run("maven", func(t *testing.T) {
opts := Options{
ProjectSettingsFile: "projectsettings.xml",