Skip to content

Commit

Permalink
feat: validate ko's main path (#4429)
Browse files Browse the repository at this point in the history
closes #4382
  • Loading branch information
gabrielcipriano committed Nov 19, 2023
1 parent 3c6dcd8 commit 8f6b16f
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 1 deletion.
23 changes: 22 additions & 1 deletion internal/pipe/ko/ko.go
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"io"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -48,7 +49,8 @@ var (
azureKeychain,
)

errNoRepository = errors.New("ko: missing repository: please set either the repository field or a $KO_DOCKER_REPO environment variable")
errNoRepository = errors.New("ko: missing repository: please set either the repository field or a $KO_DOCKER_REPO environment variable")
errInvalidMainPath = errors.New("ko: invalid Main path: ko.main (or build.main if ko.main is not set) should be a relative path.")

Check warning on line 53 in internal/pipe/ko/ko.go

View workflow job for this annotation

GitHub Actions / lint

error-strings: error strings should not be capitalized or end with punctuation or a newline (revive)
)

// Pipe that build OCI compliant images with ko.
Expand Down Expand Up @@ -93,6 +95,10 @@ func (Pipe) Default(ctx *context.Context) error {
ko.Main = build.Main
}

if err := validateMainPath(ko.Main); err != nil {
return err
}

if ko.WorkingDir == "" {
ko.WorkingDir = build.Dir
}
Expand Down Expand Up @@ -420,3 +426,18 @@ func getTimeFromTemplate(ctx *context.Context, t string) (*v1.Time, error) {
}
return &v1.Time{Time: time.Unix(seconds, 0)}, nil
}

func validateMainPath(path string) error {
// if the path is empty, it's probably fine as ko will use the default value
if path == "" {
return nil
}
if matched, _ := regexp.MatchString(`^\.?(\.\/[^\/]?.*)?$`, path); !matched {
return errInvalidMainPath
}
// paths sure can have dots in them, but if the path ends in .go, it's propably a file that one misundertood as a valid value
if strings.HasSuffix(path, ".go") {
return errInvalidMainPath
}
return nil
}
52 changes: 52 additions & 0 deletions internal/pipe/ko/ko_test.go
Expand Up @@ -340,6 +340,58 @@ func TestPublishPipeSuccess(t *testing.T) {
}
}

func TestKoValidateMainPathIssue4382(t *testing.T) {
// testing the validation of the main path directly to cover many cases
require.NoError(t, validateMainPath(""))
require.NoError(t, validateMainPath("."))
require.NoError(t, validateMainPath("./..."))
require.NoError(t, validateMainPath("./app"))
require.NoError(t, validateMainPath("../../../..."))
require.NoError(t, validateMainPath("../../app/"))
require.NoError(t, validateMainPath("./testdata/app/main"))
require.NoError(t, validateMainPath("./testdata/app/folder.with.dots"))

require.ErrorIs(t, validateMainPath("app/"), errInvalidMainPath)
require.ErrorIs(t, validateMainPath("/src/"), errInvalidMainPath)
require.ErrorIs(t, validateMainPath("/src/app"), errInvalidMainPath)
require.ErrorIs(t, validateMainPath("./testdata/app/main.go"), errInvalidMainPath)

// testing with real context
ctxOk := testctx.NewWithCfg(config.Project{
Builds: []config.Build{
{
ID: "foo",
Main: "./...",
},
},
Kos: []config.Ko{
{
ID: "default",
Build: "foo",
Repository: "fakerepo",
},
},
})
require.NoError(t, Pipe{}.Default(ctxOk))

ctxWithInvalidMainPath := testctx.NewWithCfg(config.Project{
Builds: []config.Build{
{
ID: "foo",
Main: "/some/non/relative/path",
},
},
Kos: []config.Ko{
{
ID: "default",
Build: "foo",
Repository: "fakerepo",
},
},
})
require.ErrorIs(t, Pipe{}.Default(ctxWithInvalidMainPath), errInvalidMainPath)
}

func TestPublishPipeError(t *testing.T) {
makeCtx := func() *context.Context {
return testctx.NewWithCfg(config.Project{
Expand Down
1 change: 1 addition & 0 deletions www/docs/customization/ko.md
Expand Up @@ -25,6 +25,7 @@ kos:
build: build-id

# Main path to build.
# It must be a relative path
#
# Default: build.main
main: ./cmd/...
Expand Down

0 comments on commit 8f6b16f

Please sign in to comment.