You've already forked sap-jenkins-library
mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-09-16 09:26:22 +02:00
add support for toml file
This commit is contained in:
@@ -3,17 +3,21 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/buildsettings"
|
||||
"github.com/SAP/jenkins-library/pkg/command"
|
||||
"github.com/SAP/jenkins-library/pkg/feature"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/piperutils"
|
||||
"github.com/SAP/jenkins-library/pkg/python"
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
)
|
||||
|
||||
const (
|
||||
PyBomFilename = "bom-pip.xml"
|
||||
stepName = "pythonBuild"
|
||||
cycloneDxVersion = "6.1.1"
|
||||
cycloneDxPackageVersion = "cyclonedx-bom==6.1.1"
|
||||
cycloneDxSchemaVersion = "1.4"
|
||||
)
|
||||
@@ -52,32 +56,49 @@ func pythonBuild(config pythonBuildOptions, telemetryData *telemetry.CustomData,
|
||||
}
|
||||
|
||||
func runPythonBuild(config *pythonBuildOptions, telemetryData *telemetry.CustomData, utils pythonBuildUtils, commonPipelineEnvironment *pythonBuildCommonPipelineEnvironment) error {
|
||||
pipInstallFlags := []string{"install", "--upgrade"}
|
||||
virutalEnvironmentPathMap := make(map[string]string)
|
||||
|
||||
err := createVirtualEnvironment(utils, config, virutalEnvironmentPathMap)
|
||||
if err != nil {
|
||||
// create virtualEnv
|
||||
if err := createVirtualEnvironment(utils, config, virutalEnvironmentPathMap); err != nil {
|
||||
return err
|
||||
}
|
||||
//TODO: use a defer func to cleanup the virtual environment
|
||||
|
||||
err = buildExecute(config, utils, pipInstallFlags, virutalEnvironmentPathMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Python build failed with error: %w", err)
|
||||
// FEATURE FLAG (com_sap_piper_featureFlag_pythonToml) to switch to new implementation of python build step
|
||||
if feature.IsFeatureEnabled("pythonToml") {
|
||||
// check project descriptor
|
||||
buildDescriptorFilePath, err := searchDescriptor([]string{"pyproject.toml", "setup.py"}, utils.FileExists)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// build package
|
||||
if strings.HasSuffix(buildDescriptorFilePath, "pyproject.toml") {
|
||||
if err := python.InstallProjectDependencies(utils.RunExecutable, python.Binary); err != nil {
|
||||
return fmt.Errorf("Failed to install project dependencies: %w", err)
|
||||
}
|
||||
if err := python.Build(utils.RunExecutable, python.Binary, config.BuildFlags, config.SetupFlags); err != nil {
|
||||
return fmt.Errorf("Failed to build python project: %w", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := buildExecute(config, utils, virutalEnvironmentPathMap); err != nil {
|
||||
return fmt.Errorf("Python build failed with error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// generate BOM
|
||||
if config.CreateBOM {
|
||||
if err := runBOMCreationForPy(utils, pipInstallFlags, virutalEnvironmentPathMap, config); err != nil {
|
||||
if err := runBOMCreationForPy(utils, virutalEnvironmentPathMap, config); err != nil {
|
||||
return fmt.Errorf("BOM creation failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// generate build settings information
|
||||
log.Entry().Debugf("creating build settings information...")
|
||||
|
||||
dockerImage, err := GetDockerImageValue(stepName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pythonConfig := buildsettings.BuildOptions{
|
||||
CreateBOM: config.CreateBOM,
|
||||
Publish: config.Publish,
|
||||
@@ -90,21 +111,18 @@ func runPythonBuild(config *pythonBuildOptions, telemetryData *telemetry.CustomD
|
||||
}
|
||||
commonPipelineEnvironment.custom.buildSettingsInfo = buildSettingsInfo
|
||||
|
||||
// publish package
|
||||
if config.Publish {
|
||||
if err := publishWithTwine(config, utils, pipInstallFlags, virutalEnvironmentPathMap); err != nil {
|
||||
if err := publishWithTwine(config, utils, virutalEnvironmentPathMap); err != nil {
|
||||
return fmt.Errorf("failed to publish: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = removeVirtualEnvironment(utils, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
// remove virtualEnv
|
||||
return removeVirtualEnvironment(utils, config)
|
||||
}
|
||||
|
||||
func buildExecute(config *pythonBuildOptions, utils pythonBuildUtils, pipInstallFlags []string, virutalEnvironmentPathMap map[string]string) error {
|
||||
func buildExecute(config *pythonBuildOptions, utils pythonBuildUtils, virutalEnvironmentPathMap map[string]string) error {
|
||||
var flags []string
|
||||
flags = append(flags, config.BuildFlags...)
|
||||
flags = append(flags, "setup.py")
|
||||
@@ -138,18 +156,17 @@ func createVirtualEnvironment(utils pythonBuildUtils, config *pythonBuildOptions
|
||||
}
|
||||
|
||||
func removeVirtualEnvironment(utils pythonBuildUtils, config *pythonBuildOptions) error {
|
||||
err := utils.RemoveAll(config.VirutalEnvironmentName)
|
||||
if err != nil {
|
||||
return err
|
||||
if err := utils.RemoveAll(config.VirutalEnvironmentName); err != nil {
|
||||
return fmt.Errorf("failed to remove virtual environment: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runBOMCreationForPy(utils pythonBuildUtils, pipInstallFlags []string, virutalEnvironmentPathMap map[string]string, config *pythonBuildOptions) error {
|
||||
pipInstallOriginalFlags := pipInstallFlags
|
||||
func runBOMCreationForPy(utils pythonBuildUtils, virutalEnvironmentPathMap map[string]string, config *pythonBuildOptions) error {
|
||||
// install dependencies from requirements.txt
|
||||
exists, _ := utils.FileExists(config.RequirementsFilePath)
|
||||
if exists {
|
||||
pipInstallRequirementsFlags := append(pipInstallOriginalFlags, "--requirement", config.RequirementsFilePath)
|
||||
pipInstallRequirementsFlags := append(python.PipInstallFlags, "--requirement", config.RequirementsFilePath)
|
||||
if err := utils.RunExecutable(virutalEnvironmentPathMap["pip"], pipInstallRequirementsFlags...); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -157,29 +174,58 @@ func runBOMCreationForPy(utils pythonBuildUtils, pipInstallFlags []string, virut
|
||||
log.Entry().Warnf("unable to find requirements.txt file at %s , continuing SBOM generation without requirements.txt", config.RequirementsFilePath)
|
||||
}
|
||||
|
||||
pipInstallCycloneDxFlags := append(pipInstallOriginalFlags, cycloneDxPackageVersion)
|
||||
|
||||
// install cyclonedx
|
||||
pipInstallCycloneDxFlags := append(python.PipInstallFlags, cycloneDxPackageVersion)
|
||||
if err := utils.RunExecutable(virutalEnvironmentPathMap["pip"], pipInstallCycloneDxFlags...); err != nil {
|
||||
return err
|
||||
}
|
||||
virutalEnvironmentPathMap["cyclonedx"] = filepath.Join(config.VirutalEnvironmentName, "bin", "cyclonedx-py")
|
||||
|
||||
if err := utils.RunExecutable(virutalEnvironmentPathMap["cyclonedx"], "env", "--output-file", PyBomFilename, "--output-format", "XML", "--spec-version", cycloneDxSchemaVersion); err != nil {
|
||||
// run cyclonedx
|
||||
// TODO: use modules, python -m cyclonedx_py ... to avoid virutalEnvironmentPathMap
|
||||
if err := utils.RunExecutable(
|
||||
virutalEnvironmentPathMap["cyclonedx"],
|
||||
"env",
|
||||
"--output-file", PyBomFilename,
|
||||
"--output-format", "XML",
|
||||
"--spec-version", cycloneDxSchemaVersion,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func publishWithTwine(config *pythonBuildOptions, utils pythonBuildUtils, pipInstallFlags []string, virutalEnvironmentPathMap map[string]string) error {
|
||||
pipInstallFlags = append(pipInstallFlags, "twine")
|
||||
if err := utils.RunExecutable(virutalEnvironmentPathMap["pip"], pipInstallFlags...); err != nil {
|
||||
func publishWithTwine(config *pythonBuildOptions, utils pythonBuildUtils, virutalEnvironmentPathMap map[string]string) error {
|
||||
if err := python.Install(utils.RunExecutable, "twine", "", config.VirutalEnvironmentName, virutalEnvironmentPathMap); err != nil {
|
||||
return err
|
||||
}
|
||||
virutalEnvironmentPathMap["twine"] = filepath.Join(config.VirutalEnvironmentName, "bin", "twine")
|
||||
if err := utils.RunExecutable(virutalEnvironmentPathMap["twine"], "upload", "--username", config.TargetRepositoryUser,
|
||||
"--password", config.TargetRepositoryPassword, "--repository-url", config.TargetRepositoryURL, "--disable-progress-bar",
|
||||
"dist/*"); err != nil {
|
||||
|
||||
// TODO: use modules, python -m twine ... to avoid virutalEnvironmentPathMap
|
||||
if err := utils.RunExecutable(
|
||||
virutalEnvironmentPathMap["twine"],
|
||||
"upload",
|
||||
"--username", config.TargetRepositoryUser,
|
||||
"--password", config.TargetRepositoryPassword,
|
||||
"--repository-url", config.TargetRepositoryURL,
|
||||
"--disable-progress-bar",
|
||||
"dist/*",
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func searchDescriptor(supported []string, existsFunc func(string) (bool, error)) (string, error) {
|
||||
var descriptor string
|
||||
for _, f := range supported {
|
||||
exists, _ := existsFunc(f)
|
||||
if exists {
|
||||
descriptor = f
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(descriptor) == 0 {
|
||||
return "", fmt.Errorf("no build descriptor available, supported: %v", supported)
|
||||
}
|
||||
return descriptor, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user