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

cnbBuild: support for zip archives as path argument (#3123)

This commit is contained in:
Pavel Busko 2021-09-27 10:32:05 +02:00 committed by GitHub
parent 0978f1492a
commit 61b33ec66e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 117 additions and 31 deletions

View File

@ -1,6 +1,7 @@
package cmd
import (
"archive/zip"
"encoding/json"
"fmt"
"os"
@ -88,6 +89,70 @@ func isBuilder(utils cnbutils.BuildUtils) (bool, error) {
return true, nil
}
func isZip(path string) bool {
r, err := zip.OpenReader(path)
switch {
case err == nil:
r.Close()
return true
case err == zip.ErrFormat:
return false
default:
return false
}
}
func copyProject(source, target string, utils cnbutils.BuildUtils) error {
sourceFiles, _ := utils.Glob(path.Join(source, "**"))
for _, sourceFile := range sourceFiles {
if !isIgnored(sourceFile) {
target := path.Join(target, strings.ReplaceAll(sourceFile, source, ""))
dir, err := isDir(sourceFile)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Checking file info '%s' failed", target)
}
if dir {
err = utils.MkdirAll(target, os.ModePerm)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Creating directory '%s' failed", target)
}
} else {
log.Entry().Debugf("Copying '%s' to '%s'", sourceFile, target)
_, err = utils.Copy(sourceFile, target)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Copying '%s' to '%s' failed", sourceFile, target)
}
}
} else {
log.Entry().Debugf("Filtered out '%s'", sourceFile)
}
}
return nil
}
func copyFile(source, target string, utils cnbutils.BuildUtils) error {
if isZip(source) {
log.Entry().Infof("Extracting archive '%s' to '%s'", source, target)
_, err := piperutils.Unzip(source, target)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Extracting archive '%s' to '%s' failed", source, target)
}
} else {
log.SetErrorCategory(log.ErrorBuild)
return errors.New("application path must be a directory or zip")
}
return nil
}
func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, utils cnbutils.BuildUtils, commonPipelineEnvironment *cnbBuildCommonPipelineEnvironment) error {
var err error
@ -140,33 +205,23 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u
source = config.Path
}
sourceFiles, _ := utils.Glob(path.Join(source, "**"))
for _, sourceFile := range sourceFiles {
if !isIgnored(sourceFile) {
target := path.Join(target, strings.ReplaceAll(sourceFile, source, ""))
dir, err := isDir(sourceFile)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Checking file info '%s' failed", target)
}
dir, err := isDir(source)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Checking file info '%s' failed", target)
}
if dir {
err = utils.MkdirAll(target, os.ModePerm)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Creating directory '%s' failed", target)
}
} else {
log.Entry().Debugf("Copying '%s' to '%s'", sourceFile, target)
_, err = utils.Copy(sourceFile, target)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Copying '%s' to '%s' failed", sourceFile, target)
}
}
} else {
log.Entry().Debugf("Filtered out '%s'", sourceFile)
if dir {
err = copyProject(source, target, utils)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Copying '%s' into '%s' failed", source, target)
}
} else {
err = copyFile(source, target, utils)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrapf(err, "Copying '%s' into '%s' failed", source, target)
}
}
@ -211,20 +266,20 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, u
err = utils.RunExecutable(detectorPath, "-buildpacks", buildpacksPath, "-order", orderPath)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrap(err, fmt.Sprintf("execution of '%s' failed", detectorPath))
return errors.Wrapf(err, "execution of '%s' failed", detectorPath)
}
err = utils.RunExecutable(builderPath, "-buildpacks", buildpacksPath)
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrap(err, fmt.Sprintf("execution of '%s' failed", builderPath))
return errors.Wrapf(err, "execution of '%s' failed", builderPath)
}
utils.AppendEnv([]string{fmt.Sprintf("CNB_REGISTRY_AUTH=%s", string(cnbRegistryAuth))})
err = utils.RunExecutable(exporterPath, fmt.Sprintf("%s:%s", containerImage, containerImageTag), fmt.Sprintf("%s:latest", containerImage))
if err != nil {
log.SetErrorCategory(log.ErrorBuild)
return errors.Wrap(err, fmt.Sprintf("execution of '%s' failed", exporterPath))
return errors.Wrapf(err, "execution of '%s' failed", exporterPath)
}
return nil

View File

@ -137,7 +137,7 @@ func addCnbBuildFlags(cmd *cobra.Command, stepConfig *cnbBuildOptions) {
cmd.Flags().StringVar(&stepConfig.ContainerImageTag, "containerImageTag", os.Getenv("PIPER_containerImageTag"), "Tag of the container which will be built")
cmd.Flags().StringVar(&stepConfig.ContainerRegistryURL, "containerRegistryUrl", os.Getenv("PIPER_containerRegistryUrl"), "Container registry where the image should be pushed to")
cmd.Flags().StringSliceVar(&stepConfig.Buildpacks, "buildpacks", []string{}, "List of custom buildpacks to use in the form of '<hostname>/<repo>[:<tag>]'.")
cmd.Flags().StringVar(&stepConfig.Path, "path", os.Getenv("PIPER_path"), "The path should either point to your sources or an artifact build before.")
cmd.Flags().StringVar(&stepConfig.Path, "path", os.Getenv("PIPER_path"), "The path should either point to a directory with your sources or an artifact in zip format.")
cmd.Flags().StringVar(&stepConfig.DockerConfigJSON, "dockerConfigJSON", os.Getenv("PIPER_dockerConfigJSON"), "Path to the file `.docker/config.json` - this is typically provided by your CI/CD system. You can find more details about the Docker credentials in the [Docker documentation](https://docs.docker.com/engine/reference/commandline/login/).")
cmd.MarkFlagRequired("containerImageName")

View File

@ -1,4 +1,6 @@
//go:build integration
// +build integration
// can be execute with go test -tags=integration ./integration/...
package main
@ -23,6 +25,35 @@ func TestNpmProject(t *testing.T) {
container.assertHasOutput(t, "failed to write image to the following tags: [test/not-found:0.0.1")
}
func TestZipPath(t *testing.T) {
t.Parallel()
container := givenThisContainer(t, IntegrationTestDockerExecRunnerBundle{
Image: "paketobuildpacks/builder:full",
User: "cnb",
TestDir: []string{"testdata", "TestCnbIntegration", "zip"},
})
container.whenRunningPiperCommand("cnbBuild", "--containerImageName", "not-found", "--containerImageTag", "0.0.1", "--containerRegistryUrl", "test", "--path", "go.zip")
container.assertHasOutput(t, "running command: /cnb/lifecycle/detector")
container.assertHasOutput(t, "Installing Go")
container.assertHasOutput(t, "Paketo Go Build Buildpack")
container.assertHasOutput(t, "Saving test/not-found:0.0.1")
}
func TestNonZipPath(t *testing.T) {
t.Parallel()
container := givenThisContainer(t, IntegrationTestDockerExecRunnerBundle{
Image: "paketobuildpacks/builder:full",
User: "cnb",
TestDir: []string{"testdata", "TestMtaIntegration", "npm"},
})
container.whenRunningPiperCommand("cnbBuild", "--containerImageName", "not-found", "--containerImageTag", "0.0.1", "--containerRegistryUrl", "test", "--path", "mta.yaml")
container.assertHasOutput(t, "Copying 'mta.yaml' into '/workspace' failed: application path must be a directory or zip")
}
func TestNpmCustomBuildpacksFullProject(t *testing.T) {
t.Parallel()
container := givenThisContainer(t, IntegrationTestDockerExecRunnerBundle{

Binary file not shown.

View File

@ -57,7 +57,7 @@ spec:
- STEPS
- name: path
type: string
description: The path should either point to your sources or an artifact build before.
description: The path should either point to a directory with your sources or an artifact in zip format.
scope:
- PARAMETERS
- STAGES