mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-01-16 05:16:08 +02:00
feat(cnbBuild): preserve maven test results in the workspace (#3429)
Co-authored-by: Pavel Busko <pavel.busko@sap.com> Co-authored-by: Ralf Pannemans <ralf.pannemans@sap.com>
This commit is contained in:
parent
7007efc35f
commit
1750b75cb8
@ -98,14 +98,6 @@ func isIgnored(find string, include, exclude *ignore.GitIgnore) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func isDir(path string) (bool, error) {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return info.IsDir(), nil
|
||||
}
|
||||
|
||||
func isBuilder(utils cnbutils.BuildUtils) error {
|
||||
exists, err := utils.FileExists(creatorPath)
|
||||
if err != nil {
|
||||
@ -163,7 +155,7 @@ func copyProject(source, target string, include, exclude *ignore.GitIgnore, util
|
||||
}
|
||||
if !isIgnored(relPath, include, exclude) {
|
||||
target := path.Join(target, strings.ReplaceAll(sourceFile, source, ""))
|
||||
dir, err := isDir(sourceFile)
|
||||
dir, err := utils.DirExists(sourceFile)
|
||||
if err != nil {
|
||||
log.SetErrorCategory(log.ErrorBuild)
|
||||
return errors.Wrapf(err, "Checking file info '%s' failed", target)
|
||||
@ -221,6 +213,27 @@ func prepareDockerConfig(source string, utils cnbutils.BuildUtils) (string, erro
|
||||
return source, nil
|
||||
}
|
||||
|
||||
func linkTargetFolder(utils cnbutils.BuildUtils, source, target string) error {
|
||||
var err error
|
||||
linkPath := filepath.Join(target, "target")
|
||||
targetPath := filepath.Join(source, "target")
|
||||
if ok, _ := utils.DirExists(targetPath); !ok {
|
||||
err = utils.MkdirAll(targetPath, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if ok, _ := utils.DirExists(linkPath); ok {
|
||||
err = utils.RemoveAll(linkPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return utils.Symlink(targetPath, linkPath)
|
||||
}
|
||||
|
||||
func (c *cnbBuildOptions) mergeEnvVars(vars map[string]interface{}) {
|
||||
if c.BuildEnvVars == nil {
|
||||
c.BuildEnvVars = vars
|
||||
@ -302,20 +315,23 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u
|
||||
}
|
||||
|
||||
target := "/workspace"
|
||||
source, err := utils.Getwd()
|
||||
pwd, err := utils.Getwd()
|
||||
if err != nil {
|
||||
log.SetErrorCategory(log.ErrorBuild)
|
||||
return errors.Wrap(err, "failed to get current working directory")
|
||||
}
|
||||
|
||||
var source string
|
||||
if len(config.Path) > 0 {
|
||||
source = config.Path
|
||||
} else {
|
||||
source = pwd
|
||||
}
|
||||
|
||||
dir, err := isDir(source)
|
||||
dir, err := utils.DirExists(source)
|
||||
if err != nil {
|
||||
log.SetErrorCategory(log.ErrorBuild)
|
||||
return errors.Wrapf(err, "Checking file info '%s' failed", target)
|
||||
return errors.Wrapf(err, "Checking file info '%s' failed", source)
|
||||
}
|
||||
|
||||
if dir {
|
||||
@ -332,6 +348,14 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u
|
||||
}
|
||||
}
|
||||
|
||||
if ok, _ := utils.FileExists(filepath.Join(target, "pom.xml")); ok {
|
||||
err = linkTargetFolder(utils, pwd, target)
|
||||
if err != nil {
|
||||
log.SetErrorCategory(log.ErrorBuild)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
metadata.WriteProjectMetadata(GeneralConfig.EnvRootPath, utils)
|
||||
|
||||
var buildpacksPath = "/cnb/buildpacks"
|
||||
|
@ -192,6 +192,55 @@ func TestRunCnbBuild(t *testing.T) {
|
||||
assert.Contains(t, runner.Calls[0].Params, fmt.Sprintf("%s/%s:3.1.5", registry, config.ContainerImageName))
|
||||
})
|
||||
|
||||
t.Run("pom.xml exists (symlink for the target folder)", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
config := cnbBuildOptions{
|
||||
ContainerImageName: "my-image",
|
||||
ContainerImageTag: "3.1.5",
|
||||
ContainerRegistryURL: "some-registry",
|
||||
DockerConfigJSON: "/path/to/config.json",
|
||||
}
|
||||
|
||||
utils := newCnbBuildTestsUtils()
|
||||
utils.FilesMock.CurrentDir = "/jenkins"
|
||||
utils.FilesMock.AddDir("/jenkins")
|
||||
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
||||
utils.FilesMock.AddFile("/workspace/pom.xml", []byte("test"))
|
||||
addBuilderFiles(&utils)
|
||||
|
||||
err := runCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
runner := utils.ExecMockRunner
|
||||
assertLifecycleCalls(t, runner)
|
||||
|
||||
assert.True(t, utils.FilesMock.HasCreatedSymlink("/jenkins/target", "/workspace/target"))
|
||||
})
|
||||
|
||||
t.Run("no pom.xml exists (no symlink for the target folder)", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
config := cnbBuildOptions{
|
||||
ContainerImageName: "my-image",
|
||||
ContainerImageTag: "3.1.5",
|
||||
ContainerRegistryURL: "some-registry",
|
||||
DockerConfigJSON: "/path/to/config.json",
|
||||
}
|
||||
|
||||
utils := newCnbBuildTestsUtils()
|
||||
utils.FilesMock.CurrentDir = "/jenkins"
|
||||
utils.FilesMock.AddDir("/jenkins")
|
||||
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
|
||||
addBuilderFiles(&utils)
|
||||
|
||||
err := runCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
runner := utils.ExecMockRunner
|
||||
assertLifecycleCalls(t, runner)
|
||||
|
||||
assert.False(t, utils.FilesMock.HasCreatedSymlink("/jenkins/target", "/workspace/target"))
|
||||
})
|
||||
|
||||
t.Run("error case: Invalid DockerConfigJSON file", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{}
|
||||
|
@ -1,3 +1,4 @@
|
||||
//go:build !release
|
||||
// +build !release
|
||||
|
||||
package mock
|
||||
@ -38,6 +39,8 @@ func (fInfo fileInfoMock) Sys() interface{} { return nil }
|
||||
type fileProperties struct {
|
||||
content *[]byte
|
||||
mode os.FileMode
|
||||
isLink bool
|
||||
target string
|
||||
}
|
||||
|
||||
// isDir returns true when the properties describe a directory entry.
|
||||
@ -153,6 +156,18 @@ func (f *FilesMock) HasCopiedFile(src string, dest string) bool {
|
||||
return f.copiedFiles[f.toAbsPath(src)] == f.toAbsPath(dest)
|
||||
}
|
||||
|
||||
// HasCreatedSymlink returns true if the virtual file system has a symlink with a specific target.
|
||||
func (f *FilesMock) HasCreatedSymlink(oldname, newname string) bool {
|
||||
if f.files == nil {
|
||||
return false
|
||||
}
|
||||
props, exists := f.files[f.toAbsPath(newname)]
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
return props.isLink && props.target == oldname
|
||||
}
|
||||
|
||||
// FileExists returns true if file content has been associated with the given path, false otherwise.
|
||||
// Only relative paths are supported.
|
||||
func (f *FilesMock) FileExists(path string) (bool, error) {
|
||||
@ -455,6 +470,33 @@ func (f *FilesMock) Abs(path string) (string, error) {
|
||||
return f.toAbsPath(path), nil
|
||||
}
|
||||
|
||||
func (f *FilesMock) Symlink(oldname, newname string) error {
|
||||
if f.FileWriteError != nil {
|
||||
return f.FileWriteError
|
||||
}
|
||||
|
||||
if f.FileWriteErrors[newname] != nil {
|
||||
return f.FileWriteErrors[newname]
|
||||
}
|
||||
|
||||
parentExists, err := f.DirExists(filepath.Dir(newname))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !parentExists {
|
||||
return fmt.Errorf("failed to create symlink: parent directory %s doesn't exist", filepath.Dir(newname))
|
||||
}
|
||||
|
||||
f.init()
|
||||
|
||||
f.files[newname] = &fileProperties{
|
||||
isLink: true,
|
||||
target: oldname,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FileMock can be used in places where a io.Closer, io.StringWriter or io.Writer is expected.
|
||||
// It is the concrete type returned from FilesMock.Open()
|
||||
type FileMock struct {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package mock
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@ -642,3 +643,33 @@ func TestFilesMockTempDir(t *testing.T) {
|
||||
assert.True(t, ok)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFilesMockSymlink(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("creates a symlink", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
files.AddDir("/backup")
|
||||
assert.NoError(t, files.Symlink("/folder", "/backup/folder"))
|
||||
|
||||
assert.True(t, files.HasCreatedSymlink("/folder", "/backup/folder"))
|
||||
})
|
||||
|
||||
t.Run("fails if parent directory doesn't exist", func(t *testing.T) {
|
||||
files := FilesMock{}
|
||||
err := files.Symlink("/non/existent/folder", "/symbolic/link")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "failed to create symlink: parent directory /symbolic doesn't exist", err.Error())
|
||||
})
|
||||
|
||||
t.Run("fails if FileWriteError is specified", func(t *testing.T) {
|
||||
expectedErr := errors.New("test")
|
||||
files := FilesMock{
|
||||
FileWriteErrors: map[string]error{
|
||||
"/symbolic/link": expectedErr,
|
||||
},
|
||||
}
|
||||
err := files.Symlink("/non/existent/folder", "/symbolic/link")
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, expectedErr, err)
|
||||
})
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ type FileUtils interface {
|
||||
RemoveAll(string) error
|
||||
FileRename(string, string) error
|
||||
Getwd() (string, error)
|
||||
Symlink(oldname string, newname string) error
|
||||
}
|
||||
|
||||
// Files ...
|
||||
@ -384,3 +385,8 @@ func (f Files) Stat(path string) (os.FileInfo, error) {
|
||||
func (f Files) Abs(path string) (string, error) {
|
||||
return filepath.Abs(path)
|
||||
}
|
||||
|
||||
// Symlink is a wrapper for os.Symlink
|
||||
func (f Files) Symlink(oldname, newname string) error {
|
||||
return os.Symlink(oldname, newname)
|
||||
}
|
||||
|
@ -548,5 +548,5 @@ steps:
|
||||
whitesource: 'whitesourceExecuteScan'
|
||||
labelPrefix: pr_
|
||||
cnbBuild:
|
||||
stashExcludes:
|
||||
stashBack: '**/*'
|
||||
stashIncludes:
|
||||
stashBack: '**/target/*.exec, **/*.jtl, **/target/**/*.xml'
|
||||
|
Loading…
Reference in New Issue
Block a user