You've already forked sap-jenkins-library
							
							
				mirror of
				https://github.com/SAP/jenkins-library.git
				synced 2025-10-30 23:57:50 +02:00 
			
		
		
		
	feat: add validation for sbom generated by gradle (#5522)
This commit is contained in:
		| @@ -235,6 +235,33 @@ func createBOM(config *gradleExecuteBuildOptions, utils gradleExecuteBuildUtils) | |||||||
| 		log.Entry().WithError(err).Errorf("failed to create BOM: %v", err) | 		log.Entry().WithError(err).Errorf("failed to create BOM: %v", err) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Validate generated SBOMs | ||||||
|  | 	bomFilename := gradleBomFilename + ".xml" | ||||||
|  | 	err = utils.WalkDir(rootPath, func(path string, d fs.DirEntry, err error) error { | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		if d.IsDir() { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		if strings.HasSuffix(path, bomFilename) { | ||||||
|  | 			log.Entry().Infof("Validating generated SBOM: %s", path) | ||||||
|  |  | ||||||
|  | 			if err := piperutils.ValidateCycloneDX14(path); err != nil { | ||||||
|  | 				log.Entry().Warnf("SBOM validation failed: %v", err) | ||||||
|  | 			} else { | ||||||
|  | 				purl := piperutils.GetPurl(path) | ||||||
|  | 				log.Entry().Infof("SBOM validation passed") | ||||||
|  | 				log.Entry().Infof("SBOM PURL: %s", purl) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Entry().Warnf("Failed to walk directory for SBOM validation: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ import ( | |||||||
| 	"github.com/pkg/errors" | 	"github.com/pkg/errors" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
|  |  | ||||||
|  | 	"github.com/SAP/jenkins-library/pkg/config" | ||||||
| 	"github.com/SAP/jenkins-library/pkg/mock" | 	"github.com/SAP/jenkins-library/pkg/mock" | ||||||
| 	"github.com/SAP/jenkins-library/pkg/piperenv" | 	"github.com/SAP/jenkins-library/pkg/piperenv" | ||||||
| ) | ) | ||||||
| @@ -43,6 +44,9 @@ func (d isDirEntryMock) Info() (fs.FileInfo, error) { | |||||||
|  |  | ||||||
| func TestRunGradleExecuteBuild(t *testing.T) { | func TestRunGradleExecuteBuild(t *testing.T) { | ||||||
| 	pipelineEnv := &gradleExecuteBuildCommonPipelineEnvironment{} | 	pipelineEnv := &gradleExecuteBuildCommonPipelineEnvironment{} | ||||||
|  | 	SetConfigOptions(ConfigCommandOptions{ | ||||||
|  | 		OpenFile: config.OpenPiperFile, | ||||||
|  | 	}) | ||||||
|  |  | ||||||
| 	t.Run("failed case - build.gradle isn't present", func(t *testing.T) { | 	t.Run("failed case - build.gradle isn't present", func(t *testing.T) { | ||||||
| 		utils := gradleExecuteBuildMockUtils{ | 		utils := gradleExecuteBuildMockUtils{ | ||||||
| @@ -61,9 +65,13 @@ func TestRunGradleExecuteBuild(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("success case - only build", func(t *testing.T) { | 	t.Run("success case - only build", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			return nil // No BOM files | ||||||
|  | 		} | ||||||
| 		utils := gradleExecuteBuildMockUtils{ | 		utils := gradleExecuteBuildMockUtils{ | ||||||
| 			ExecMockRunner: &mock.ExecMockRunner{}, | 			ExecMockRunner: &mock.ExecMockRunner{}, | ||||||
| 			FilesMock:      &mock.FilesMock{}, | 			FilesMock:      &mock.FilesMock{}, | ||||||
|  | 			Filepath:       walkDir, | ||||||
| 		} | 		} | ||||||
| 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
| 		options := &gradleExecuteBuildOptions{ | 		options := &gradleExecuteBuildOptions{ | ||||||
| @@ -79,9 +87,13 @@ func TestRunGradleExecuteBuild(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("success case - build with flags", func(t *testing.T) { | 	t.Run("success case - build with flags", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			return nil // No BOM files | ||||||
|  | 		} | ||||||
| 		utils := gradleExecuteBuildMockUtils{ | 		utils := gradleExecuteBuildMockUtils{ | ||||||
| 			ExecMockRunner: &mock.ExecMockRunner{}, | 			ExecMockRunner: &mock.ExecMockRunner{}, | ||||||
| 			FilesMock:      &mock.FilesMock{}, | 			FilesMock:      &mock.FilesMock{}, | ||||||
|  | 			Filepath:       walkDir, | ||||||
| 		} | 		} | ||||||
| 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
| 		options := &gradleExecuteBuildOptions{ | 		options := &gradleExecuteBuildOptions{ | ||||||
| @@ -98,11 +110,24 @@ func TestRunGradleExecuteBuild(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("success case - bom creation", func(t *testing.T) { | 	t.Run("success case - bom creation", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			var dirMock isDirEntryMock = func() bool { | ||||||
|  | 				return false | ||||||
|  | 			} | ||||||
|  | 			// Simulate finding a BOM file | ||||||
|  | 			return fn(filepath.Join("path", "to", "build", "reports", "bom-gradle.xml"), dirMock, nil) | ||||||
|  | 		} | ||||||
| 		utils := gradleExecuteBuildMockUtils{ | 		utils := gradleExecuteBuildMockUtils{ | ||||||
| 			ExecMockRunner: &mock.ExecMockRunner{}, | 			ExecMockRunner: &mock.ExecMockRunner{}, | ||||||
| 			FilesMock:      &mock.FilesMock{}, | 			FilesMock:      &mock.FilesMock{}, | ||||||
|  | 			Filepath:       walkDir, | ||||||
| 		} | 		} | ||||||
| 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
|  | 		// Add a valid BOM file for validation | ||||||
|  | 		utils.FilesMock.AddFile(filepath.Join("path", "to", "build", "reports", "bom-gradle.xml"), []byte(`<?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <bom xmlns="http://cyclonedx.org/schema/bom/1.4" version="1"> | ||||||
|  |   <components/> | ||||||
|  | </bom>`)) | ||||||
| 		options := &gradleExecuteBuildOptions{ | 		options := &gradleExecuteBuildOptions{ | ||||||
| 			Path:       "path/to", | 			Path:       "path/to", | ||||||
| 			Task:       "build", | 			Task:       "build", | ||||||
| @@ -153,9 +178,13 @@ func TestRunGradleExecuteBuild(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("success case - build using wrapper", func(t *testing.T) { | 	t.Run("success case - build using wrapper", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			return nil // No BOM files | ||||||
|  | 		} | ||||||
| 		utils := gradleExecuteBuildMockUtils{ | 		utils := gradleExecuteBuildMockUtils{ | ||||||
| 			ExecMockRunner: &mock.ExecMockRunner{}, | 			ExecMockRunner: &mock.ExecMockRunner{}, | ||||||
| 			FilesMock:      &mock.FilesMock{}, | 			FilesMock:      &mock.FilesMock{}, | ||||||
|  | 			Filepath:       walkDir, | ||||||
| 		} | 		} | ||||||
| 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
| 		utils.FilesMock.AddFile("gradlew", []byte{}) | 		utils.FilesMock.AddFile("gradlew", []byte{}) | ||||||
| @@ -172,11 +201,15 @@ func TestRunGradleExecuteBuild(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("failed case - build", func(t *testing.T) { | 	t.Run("failed case - build", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			return nil // No BOM files | ||||||
|  | 		} | ||||||
| 		utils := gradleExecuteBuildMockUtils{ | 		utils := gradleExecuteBuildMockUtils{ | ||||||
| 			ExecMockRunner: &mock.ExecMockRunner{ | 			ExecMockRunner: &mock.ExecMockRunner{ | ||||||
| 				ShouldFailOnCommand: map[string]error{"gradle build -p path/to": errors.New("failed to build")}, | 				ShouldFailOnCommand: map[string]error{"gradle build -p path/to": errors.New("failed to build")}, | ||||||
| 			}, | 			}, | ||||||
| 			FilesMock: &mock.FilesMock{}, | 			FilesMock: &mock.FilesMock{}, | ||||||
|  | 			Filepath:  walkDir, | ||||||
| 		} | 		} | ||||||
| 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
| 		options := &gradleExecuteBuildOptions{ | 		options := &gradleExecuteBuildOptions{ | ||||||
| @@ -191,11 +224,15 @@ func TestRunGradleExecuteBuild(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("failed case - build with flags", func(t *testing.T) { | 	t.Run("failed case - build with flags", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			return nil // No BOM files | ||||||
|  | 		} | ||||||
| 		utils := gradleExecuteBuildMockUtils{ | 		utils := gradleExecuteBuildMockUtils{ | ||||||
| 			ExecMockRunner: &mock.ExecMockRunner{ | 			ExecMockRunner: &mock.ExecMockRunner{ | ||||||
| 				ShouldFailOnCommand: map[string]error{"gradle clean build -x test -p path/to": errors.New("failed to build with flags")}, | 				ShouldFailOnCommand: map[string]error{"gradle clean build -x test -p path/to": errors.New("failed to build with flags")}, | ||||||
| 			}, | 			}, | ||||||
| 			FilesMock: &mock.FilesMock{}, | 			FilesMock: &mock.FilesMock{}, | ||||||
|  | 			Filepath:  walkDir, | ||||||
| 		} | 		} | ||||||
| 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
| 		options := &gradleExecuteBuildOptions{ | 		options := &gradleExecuteBuildOptions{ | ||||||
| @@ -211,11 +248,15 @@ func TestRunGradleExecuteBuild(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("failed case - bom creation", func(t *testing.T) { | 	t.Run("failed case - bom creation", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			return nil // No BOM files (build failed before creation) | ||||||
|  | 		} | ||||||
| 		utils := gradleExecuteBuildMockUtils{ | 		utils := gradleExecuteBuildMockUtils{ | ||||||
| 			ExecMockRunner: &mock.ExecMockRunner{ | 			ExecMockRunner: &mock.ExecMockRunner{ | ||||||
| 				ShouldFailOnCommand: map[string]error{"./gradlew cyclonedxBom -p path/to --init-script initScript.gradle.tmp": errors.New("failed to create bom")}, | 				ShouldFailOnCommand: map[string]error{"./gradlew cyclonedxBom -p path/to --init-script initScript.gradle.tmp": errors.New("failed to create bom")}, | ||||||
| 			}, | 			}, | ||||||
| 			FilesMock: &mock.FilesMock{}, | 			FilesMock: &mock.FilesMock{}, | ||||||
|  | 			Filepath:  walkDir, | ||||||
| 		} | 		} | ||||||
| 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
| 		utils.FilesMock.AddFile("gradlew", []byte{}) | 		utils.FilesMock.AddFile("gradlew", []byte{}) | ||||||
| @@ -232,11 +273,15 @@ func TestRunGradleExecuteBuild(t *testing.T) { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("failed case - publish artifacts", func(t *testing.T) { | 	t.Run("failed case - publish artifacts", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			return nil // No module files | ||||||
|  | 		} | ||||||
| 		utils := gradleExecuteBuildMockUtils{ | 		utils := gradleExecuteBuildMockUtils{ | ||||||
| 			ExecMockRunner: &mock.ExecMockRunner{ | 			ExecMockRunner: &mock.ExecMockRunner{ | ||||||
| 				ShouldFailOnCommand: map[string]error{"./gradlew publish -p path/to --init-script initScript.gradle.tmp": errors.New("failed to publish artifacts")}, | 				ShouldFailOnCommand: map[string]error{"./gradlew publish -p path/to --init-script initScript.gradle.tmp": errors.New("failed to publish artifacts")}, | ||||||
| 			}, | 			}, | ||||||
| 			FilesMock: &mock.FilesMock{}, | 			FilesMock: &mock.FilesMock{}, | ||||||
|  | 			Filepath:  walkDir, | ||||||
| 		} | 		} | ||||||
| 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
| 		utils.FilesMock.AddFile("gradlew", []byte{}) | 		utils.FilesMock.AddFile("gradlew", []byte{}) | ||||||
| @@ -251,6 +296,70 @@ func TestRunGradleExecuteBuild(t *testing.T) { | |||||||
| 		assert.Error(t, err) | 		assert.Error(t, err) | ||||||
| 		assert.Contains(t, err.Error(), "failed to publish artifacts") | 		assert.Contains(t, err.Error(), "failed to publish artifacts") | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("success case - bom creation with multiple modules", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			var dirMock isDirEntryMock = func() bool { | ||||||
|  | 				return false | ||||||
|  | 			} | ||||||
|  | 			// Simulate finding multiple BOM files from different modules | ||||||
|  | 			_ = fn(filepath.Join("module1", "build", "reports", "bom-gradle.xml"), dirMock, nil) | ||||||
|  | 			_ = fn(filepath.Join("module2", "build", "reports", "bom-gradle.xml"), dirMock, nil) | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		utils := gradleExecuteBuildMockUtils{ | ||||||
|  | 			ExecMockRunner: &mock.ExecMockRunner{}, | ||||||
|  | 			FilesMock:      &mock.FilesMock{}, | ||||||
|  | 			Filepath:       walkDir, | ||||||
|  | 		} | ||||||
|  | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
|  | 		// Add valid BOM files for both modules | ||||||
|  | 		validBOM := []byte(`<?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <bom xmlns="http://cyclonedx.org/schema/bom/1.4" version="1"> | ||||||
|  |   <components/> | ||||||
|  | </bom>`) | ||||||
|  | 		utils.FilesMock.AddFile(filepath.Join("module1", "build", "reports", "bom-gradle.xml"), validBOM) | ||||||
|  | 		utils.FilesMock.AddFile(filepath.Join("module2", "build", "reports", "bom-gradle.xml"), validBOM) | ||||||
|  | 		options := &gradleExecuteBuildOptions{ | ||||||
|  | 			Path:       "path/to", | ||||||
|  | 			Task:       "build", | ||||||
|  | 			UseWrapper: false, | ||||||
|  | 			CreateBOM:  true, | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv) | ||||||
|  | 		assert.NoError(t, err) | ||||||
|  | 		assert.Equal(t, 3, len(utils.Calls)) | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	t.Run("success case - bom creation with invalid BOM (validation warns but doesn't fail)", func(t *testing.T) { | ||||||
|  | 		var walkDir WalkDirFunc = func(root string, fn fs.WalkDirFunc) error { | ||||||
|  | 			var dirMock isDirEntryMock = func() bool { | ||||||
|  | 				return false | ||||||
|  | 			} | ||||||
|  | 			// Simulate finding an invalid BOM file | ||||||
|  | 			return fn(filepath.Join("path", "to", "build", "reports", "bom-gradle.xml"), dirMock, nil) | ||||||
|  | 		} | ||||||
|  | 		utils := gradleExecuteBuildMockUtils{ | ||||||
|  | 			ExecMockRunner: &mock.ExecMockRunner{}, | ||||||
|  | 			FilesMock:      &mock.FilesMock{}, | ||||||
|  | 			Filepath:       walkDir, | ||||||
|  | 		} | ||||||
|  | 		utils.FilesMock.AddFile("path/to/build.gradle", []byte{}) | ||||||
|  | 		// Add an invalid BOM file | ||||||
|  | 		utils.FilesMock.AddFile(filepath.Join("path", "to", "build", "reports", "bom-gradle.xml"), []byte(`invalid xml content`)) | ||||||
|  | 		options := &gradleExecuteBuildOptions{ | ||||||
|  | 			Path:       "path/to", | ||||||
|  | 			Task:       "build", | ||||||
|  | 			UseWrapper: false, | ||||||
|  | 			CreateBOM:  true, | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Should not fail even with invalid BOM (validation only warns) | ||||||
|  | 		err := runGradleExecuteBuild(options, nil, utils, pipelineEnv) | ||||||
|  | 		assert.NoError(t, err) | ||||||
|  | 		assert.Equal(t, 3, len(utils.Calls)) | ||||||
|  | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestGetPublishedArtifactsNames(t *testing.T) { | func TestGetPublishedArtifactsNames(t *testing.T) { | ||||||
|   | |||||||
| @@ -9,46 +9,43 @@ package main | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"io" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/docker/docker/api/types/container" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| 	"github.com/testcontainers/testcontainers-go" | 	"github.com/testcontainers/testcontainers-go" | ||||||
|  | 	"github.com/testcontainers/testcontainers-go/exec" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | const DOCKER_IMAGE_GRADLE = "gradle:6-jdk11-alpine" | ||||||
|  |  | ||||||
| func TestGradleIntegrationExecuteBuildJavaProjectBOMCreationUsingWrapper(t *testing.T) { | func TestGradleIntegrationExecuteBuildJavaProjectBOMCreationUsingWrapper(t *testing.T) { | ||||||
| 	// t.Parallel() | 	t.Parallel() | ||||||
| 	ctx := context.Background() | 	ctx := context.Background() | ||||||
|  |  | ||||||
| 	pwd, err := os.Getwd() | 	pwd, err := os.Getwd() | ||||||
| 	assert.NoError(t, err, "Getting current working directory failed.") | 	assert.NoError(t, err, "Getting current working directory failed.") | ||||||
| 	pwd = filepath.Dir(pwd) | 	pwd = filepath.Dir(pwd) | ||||||
|  |  | ||||||
| 	// using custom createTmpDir function to avoid issues with symlinks on Docker for Mac |  | ||||||
| 	tempDir, err := createTmpDir(t) |  | ||||||
| 	assert.NoError(t, err, "Error when creating temp dir") |  | ||||||
|  |  | ||||||
| 	err = copyDir(filepath.Join(pwd, "integration", "testdata", "TestGradleIntegration", "java-project"), tempDir) |  | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal("Failed to copy test project.") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	//workaround to use test script util it is possible to set workdir for Exec call |  | ||||||
| 	testScript := fmt.Sprintf(`#!/bin/sh |  | ||||||
| cd /test |  | ||||||
| /piperbin/piper gradleExecuteBuild >test-log.txt 2>&1 |  | ||||||
| `) |  | ||||||
| 	os.WriteFile(filepath.Join(tempDir, "runPiper.sh"), []byte(testScript), 0700) |  | ||||||
|  |  | ||||||
| 	reqNode := testcontainers.ContainerRequest{ | 	reqNode := testcontainers.ContainerRequest{ | ||||||
| 		Image: "adoptopenjdk/openjdk11:jdk-11.0.11_9-alpine", | 		Image: DOCKER_IMAGE_GRADLE, | ||||||
| 		Cmd:   []string{"tail", "-f"}, | 		Cmd:   []string{"tail", "-f"}, | ||||||
| 		Mounts: testcontainers.Mounts( | 		Files: []testcontainers.ContainerFile{ | ||||||
| 			testcontainers.BindMount(pwd, "/piperbin"), | 			{ | ||||||
| 			testcontainers.BindMount(tempDir, "/test"), | 				HostFilePath:      filepath.Join(pwd, "integration", "testdata", "TestGradleIntegration", "java-project"), | ||||||
| 		), | 				ContainerFilePath: "/", | ||||||
|  | 				FileMode:          0755, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		HostConfigModifier: func(hc *container.HostConfig) { | ||||||
|  | 			hc.Binds = []string{ | ||||||
|  | 				fmt.Sprintf("%s:/piperbin", pwd), | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	nodeContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | 	nodeContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | ||||||
| @@ -57,71 +54,55 @@ cd /test | |||||||
| 	}) | 	}) | ||||||
| 	require.NoError(t, err) | 	require.NoError(t, err) | ||||||
|  |  | ||||||
| 	code, _, err := nodeContainer.Exec(ctx, []string{"sh", "/test/runPiper.sh"}) | 	code, reader, err := nodeContainer.Exec(ctx, []string{"/piperbin/piper", "gradleExecuteBuild"}, exec.WithWorkingDir("/java-project")) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Equal(t, 0, code) | 	assert.Equal(t, 0, code) | ||||||
|  |  | ||||||
| 	content, err := os.ReadFile(filepath.Join(tempDir, "/test-log.txt")) | 	outputBytes, err := io.ReadAll(reader) | ||||||
| 	if err != nil { | 	assert.NoError(t, err) | ||||||
| 		t.Fatal("Could not read test-log.txt.", err) | 	output := string(outputBytes) | ||||||
| 	} |  | ||||||
| 	output := string(content) |  | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: ./gradlew tasks") | 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: ./gradlew tasks") | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: ./gradlew cyclonedxBom --init-script initScript.gradle.tmp") | 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: ./gradlew cyclonedxBom --init-script initScript.gradle.tmp") | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: ./gradlew build") | 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: ./gradlew build") | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - BUILD SUCCESSFUL") | 	assert.Contains(t, output, "info  gradleExecuteBuild - BUILD SUCCESSFUL") | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - SUCCESS") | 	assert.Contains(t, output, "info  gradleExecuteBuild - SUCCESS") | ||||||
|  | 	assert.Contains(t, output, "Validating generated SBOM:") | ||||||
|  | 	assert.Contains(t, output, "SBOM validation passed") | ||||||
|  | 	assert.Contains(t, output, "SBOM PURL:") | ||||||
|  |  | ||||||
| 	//workaround to use test script util it is possible to set workdir for Exec call | 	code, reader, err = nodeContainer.Exec(ctx, []string{"ls", "-l", "./build/reports/"}, exec.WithWorkingDir("/java-project")) | ||||||
| 	testScript = fmt.Sprintf(`#!/bin/sh |  | ||||||
| cd /test |  | ||||||
| ls -l ./build/reports/ >files-list.txt 2>&1 |  | ||||||
| `) |  | ||||||
| 	os.WriteFile(filepath.Join(tempDir, "runPiper.sh"), []byte(testScript), 0700) |  | ||||||
|  |  | ||||||
| 	code, _, err = nodeContainer.Exec(ctx, []string{"sh", "/test/runPiper.sh"}) |  | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Equal(t, 0, code) | 	assert.Equal(t, 0, code) | ||||||
|  |  | ||||||
| 	content, err = os.ReadFile(filepath.Join(tempDir, "/files-list.txt")) | 	lsOutputBytes, err := io.ReadAll(reader) | ||||||
| 	if err != nil { | 	assert.NoError(t, err) | ||||||
| 		t.Fatal("Could not read files-list.txt.", err) | 	lsOutput := string(lsOutputBytes) | ||||||
| 	} | 	assert.Contains(t, lsOutput, "bom-gradle.xml") | ||||||
| 	output = string(content) |  | ||||||
| 	assert.Contains(t, output, "bom-gradle.xml") |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestGradleIntegrationExecuteBuildJavaProjectWithBomPlugin(t *testing.T) { | func TestGradleIntegrationExecuteBuildJavaProjectWithBomPlugin(t *testing.T) { | ||||||
| 	// t.Parallel() | 	t.Parallel() | ||||||
| 	ctx := context.Background() | 	ctx := context.Background() | ||||||
|  |  | ||||||
| 	pwd, err := os.Getwd() | 	pwd, err := os.Getwd() | ||||||
| 	assert.NoError(t, err, "Getting current working directory failed.") | 	assert.NoError(t, err, "Getting current working directory failed.") | ||||||
| 	pwd = filepath.Dir(pwd) | 	pwd = filepath.Dir(pwd) | ||||||
|  |  | ||||||
| 	// using custom createTmpDir function to avoid issues with symlinks on Docker for Mac |  | ||||||
| 	tempDir, err := createTmpDir(t) |  | ||||||
| 	assert.NoError(t, err, "Error when creating temp dir") |  | ||||||
|  |  | ||||||
| 	err = copyDir(filepath.Join(pwd, "integration", "testdata", "TestGradleIntegration", "java-project-with-bom-plugin"), tempDir) |  | ||||||
| 	if err != nil { |  | ||||||
| 		t.Fatal("Failed to copy test project.") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	//workaround to use test script util it is possible to set workdir for Exec call |  | ||||||
| 	testScript := fmt.Sprintf(`#!/bin/sh |  | ||||||
| cd /test |  | ||||||
| /piperbin/piper gradleExecuteBuild >test-log.txt 2>&1 |  | ||||||
| `) |  | ||||||
| 	os.WriteFile(filepath.Join(tempDir, "runPiper.sh"), []byte(testScript), 0700) |  | ||||||
|  |  | ||||||
| 	reqNode := testcontainers.ContainerRequest{ | 	reqNode := testcontainers.ContainerRequest{ | ||||||
| 		Image: "gradle:6-jdk11-alpine", | 		Image: DOCKER_IMAGE_GRADLE, | ||||||
| 		Cmd:   []string{"tail", "-f"}, | 		Cmd:   []string{"tail", "-f"}, | ||||||
| 		Mounts: testcontainers.Mounts( | 		Files: []testcontainers.ContainerFile{ | ||||||
| 			testcontainers.BindMount(pwd, "/piperbin"), | 			{ | ||||||
| 			testcontainers.BindMount(tempDir, "/test"), | 				HostFilePath:      filepath.Join(pwd, "integration", "testdata", "TestGradleIntegration", "java-project-with-bom-plugin"), | ||||||
| 		), | 				ContainerFilePath: "/", | ||||||
|  | 				FileMode:          0755, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		HostConfigModifier: func(hc *container.HostConfig) { | ||||||
|  | 			hc.Binds = []string{ | ||||||
|  | 				fmt.Sprintf("%s:/piperbin", pwd), | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	nodeContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | 	nodeContainer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ | ||||||
| @@ -130,36 +111,28 @@ cd /test | |||||||
| 	}) | 	}) | ||||||
| 	require.NoError(t, err) | 	require.NoError(t, err) | ||||||
|  |  | ||||||
| 	code, _, err := nodeContainer.Exec(ctx, []string{"sh", "/test/runPiper.sh"}) | 	code, reader, err := nodeContainer.Exec(ctx, []string{"/piperbin/piper", "gradleExecuteBuild"}, exec.WithWorkingDir("/java-project-with-bom-plugin")) | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Equal(t, 0, code) | 	assert.Equal(t, 0, code) | ||||||
|  |  | ||||||
| 	content, err := os.ReadFile(filepath.Join(tempDir, "/test-log.txt")) | 	outputBytes, err := io.ReadAll(reader) | ||||||
| 	if err != nil { | 	assert.NoError(t, err) | ||||||
| 		t.Fatal("Could not read test-log.txt.", err) | 	output := string(outputBytes) | ||||||
| 	} |  | ||||||
| 	output := string(content) |  | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: gradle tasks") | 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: gradle tasks") | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: gradle cyclonedxBom") | 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: gradle cyclonedxBom") | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: gradle build") | 	assert.Contains(t, output, "info  gradleExecuteBuild - running command: gradle build") | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - BUILD SUCCESSFUL") | 	assert.Contains(t, output, "info  gradleExecuteBuild - BUILD SUCCESSFUL") | ||||||
| 	assert.Contains(t, output, "info  gradleExecuteBuild - SUCCESS") | 	assert.Contains(t, output, "info  gradleExecuteBuild - SUCCESS") | ||||||
|  | 	assert.Contains(t, output, "Validating generated SBOM:") | ||||||
|  | 	assert.Contains(t, output, "SBOM validation passed") | ||||||
|  | 	assert.Contains(t, output, "SBOM PURL:") | ||||||
|  |  | ||||||
| 	//workaround to use test script util it is possible to set workdir for Exec call | 	code, reader, err = nodeContainer.Exec(ctx, []string{"ls", "-l", "./build/reports/"}, exec.WithWorkingDir("/java-project-with-bom-plugin")) | ||||||
| 	testScript = fmt.Sprintf(`#!/bin/sh |  | ||||||
| cd /test |  | ||||||
| ls -l ./build/reports/ >files-list.txt 2>&1 |  | ||||||
| `) |  | ||||||
| 	os.WriteFile(filepath.Join(tempDir, "runPiper.sh"), []byte(testScript), 0700) |  | ||||||
|  |  | ||||||
| 	code, _, err = nodeContainer.Exec(ctx, []string{"sh", "/test/runPiper.sh"}) |  | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Equal(t, 0, code) | 	assert.Equal(t, 0, code) | ||||||
|  |  | ||||||
| 	content, err = os.ReadFile(filepath.Join(tempDir, "/files-list.txt")) | 	lsOutputBytes, err := io.ReadAll(reader) | ||||||
| 	if err != nil { | 	assert.NoError(t, err) | ||||||
| 		t.Fatal("Could not read files-list.txt.", err) | 	lsOutput := string(lsOutputBytes) | ||||||
| 	} | 	assert.Contains(t, lsOutput, "bom-gradle.xml") | ||||||
| 	output = string(content) |  | ||||||
| 	assert.Contains(t, output, "bom-gradle.xml") |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user