diff --git a/cmd/cnbBuild.go b/cmd/cnbBuild.go index 27f0dcc08..fcdc3c999 100644 --- a/cmd/cnbBuild.go +++ b/cmd/cnbBuild.go @@ -277,10 +277,20 @@ func (config *cnbBuildOptions) resolvePath(utils cnbutils.BuildUtils) (pathEnum, if config.Path == "" { return pathEnumRoot, pwd, nil } - source, err := utils.Abs(config.Path) + matches, err := utils.Glob(config.Path) if err != nil { log.SetErrorCategory(log.ErrorConfiguration) - return "", "", errors.Wrapf(err, "Failed to resolve absolute path for '%s'", config.Path) + return "", "", errors.Wrapf(err, "Failed to resolve glob for '%s'", config.Path) + } + numMatches := len(matches) + if numMatches != 1 { + log.SetErrorCategory(log.ErrorConfiguration) + return "", "", errors.Errorf("Failed to resolve glob for '%s', matching %d file(s)", config.Path, numMatches) + } + source, err := utils.Abs(matches[0]) + if err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return "", "", errors.Wrapf(err, "Failed to resolve absolute path for '%s'", matches[0]) } dir, err := utils.DirExists(source) @@ -470,7 +480,7 @@ func runCnbBuild(config *cnbBuildOptions, telemetryData *telemetry.CustomData, t pathType, source, err := config.resolvePath(utils) if err != nil { log.SetErrorCategory(log.ErrorBuild) - return errors.Wrapf(err, "could no resolve path") + return errors.Wrapf(err, "could not resolve path") } target := "/workspace" diff --git a/cmd/cnbBuild_generated.go b/cmd/cnbBuild_generated.go index dffa8b3c2..dea579377 100644 --- a/cmd/cnbBuild_generated.go +++ b/cmd/cnbBuild_generated.go @@ -169,7 +169,7 @@ func addCnbBuildFlags(cmd *cobra.Command, stepConfig *cnbBuildOptions) { 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 a directory with your sources or an artifact in zip format.\nThis property determines the input to the buildpack.\n") + cmd.Flags().StringVar(&stepConfig.Path, "path", os.Getenv("PIPER_path"), "Glob that should either point to a directory with your sources or one artifact in zip format.\nThis property determines the input to the buildpack.\n") cmd.Flags().StringVar(&stepConfig.ProjectDescriptor, "projectDescriptor", `project.toml`, "Relative path to the project.toml file.\nSee [buildpacks.io](https://buildpacks.io/docs/reference/config/project-descriptor/) for the reference.\nParameters passed to the cnbBuild step will take precedence over the parameters set in the project.toml file, except the `env` block.\nEnvironment variables declared in a project descriptor file, will be merged with the `buildEnvVars` property, with the `buildEnvVars` having a precedence.\n\n*Note*: The project descriptor path should be relative to what is set in the [path](#path) property. If the `path` property is pointing to a zip archive (e.g. jar file), project descriptor path will be relative to the root of the workspace.\n\n*Note*: Inline buildpacks (see [specification](https://buildpacks.io/docs/reference/config/project-descriptor/#build-_table-optional_)) are not supported yet.\n") 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.Flags().StringSliceVar(&stepConfig.CustomTLSCertificateLinks, "customTlsCertificateLinks", []string{}, "List containing download links of custom TLS certificates. This is required to ensure trusted connections to registries with custom certificates.") diff --git a/cmd/cnbBuild_test.go b/cmd/cnbBuild_test.go index 6935f86e3..fb5eb3994 100644 --- a/cmd/cnbBuild_test.go +++ b/cmd/cnbBuild_test.go @@ -465,6 +465,65 @@ uri = "some-buildpack"`)) assert.True(t, customData.Data[0].ProjectDescriptor.ExcludeUsed) }) + t.Run("error case, multiple artifacts in path", func(t *testing.T) { + t.Parallel() + commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{} + config := cnbBuildOptions{ + ContainerImageName: "my-image", + ContainerImageTag: "3.1.5", + ContainerRegistryURL: fmt.Sprintf("https://%s", imageRegistry), + DockerConfigJSON: "/path/to/config.json", + ProjectDescriptor: "project.toml", + AdditionalTags: []string{"latest"}, + Buildpacks: []string{"paketobuildpacks/java", "gcr.io/paketo-buildpacks/node"}, + Path: "target/*.jar", + } + + utils := newCnbBuildTestsUtils() + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddDir("target") + utils.FilesMock.AddFile("target/app.jar", []byte(`FFFFFF`)) + utils.FilesMock.AddFile("target/app-src.jar", []byte(`FFFFFF`)) + + addBuilderFiles(&utils) + + telemetryData := telemetry.CustomData{} + err := callCnbBuild(&config, &telemetryData, &utils, &commonPipelineEnvironment, &piperhttp.Client{}) + require.EqualError(t, err, "could not resolve path: Failed to resolve glob for 'target/*.jar', matching 2 file(s)") + }) + + t.Run("success case, artifacts found by glob", func(t *testing.T) { + t.Parallel() + commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{} + config := cnbBuildOptions{ + ContainerImageName: "my-image", + ContainerImageTag: "3.1.5", + ContainerRegistryURL: fmt.Sprintf("https://%s", imageRegistry), + DockerConfigJSON: "/path/to/config.json", + ProjectDescriptor: "project.toml", + AdditionalTags: []string{"latest"}, + Buildpacks: []string{"paketobuildpacks/java", "gcr.io/paketo-buildpacks/node"}, + Path: "**/target", + } + + utils := newCnbBuildTestsUtils() + utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`)) + utils.FilesMock.AddDir("target") + utils.FilesMock.AddFile("target/app.jar", []byte(`FFFFFF`)) + + addBuilderFiles(&utils) + + telemetryData := telemetry.CustomData{} + err := callCnbBuild(&config, &telemetryData, &utils, &commonPipelineEnvironment, &piperhttp.Client{}) + + require.NoError(t, err) + runner := utils.ExecMockRunner + assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}") + assert.Contains(t, runner.Calls[0].Params, fmt.Sprintf("%s/%s:%s", imageRegistry, config.ContainerImageName, config.ContainerImageTag)) + assert.Equal(t, config.ContainerRegistryURL, commonPipelineEnvironment.container.registryURL) + assert.Equal(t, "my-image:3.1.5", commonPipelineEnvironment.container.imageNameTag) + }) + t.Run("success case (build env telemetry was added)", func(t *testing.T) { t.Parallel() commonPipelineEnvironment := cnbBuildCommonPipelineEnvironment{} diff --git a/integration/testdata/TestCnbIntegration/config_multi_image.yml b/integration/testdata/TestCnbIntegration/config_multi_image.yml index bb53f128d..64b0a8ee9 100644 --- a/integration/testdata/TestCnbIntegration/config_multi_image.yml +++ b/integration/testdata/TestCnbIntegration/config_multi_image.yml @@ -9,6 +9,6 @@ steps: - path: project - containerImageName: go-app containerImageTag: v1.0.0 - path: zip/go.zip + path: "**/go.zip" - path: project containerImageName: my-app2 diff --git a/resources/metadata/cnbBuild.yaml b/resources/metadata/cnbBuild.yaml index 45f752c86..c210d28b1 100644 --- a/resources/metadata/cnbBuild.yaml +++ b/resources/metadata/cnbBuild.yaml @@ -107,7 +107,7 @@ spec: - name: path type: string description: | - The path should either point to a directory with your sources or an artifact in zip format. + Glob that should either point to a directory with your sources or one artifact in zip format. This property determines the input to the buildpack. scope: - PARAMETERS