Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions bake/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/platformutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/urlutil"
dockeropts "github.com/docker/cli/opts"
hcl "github.com/hashicorp/hcl/v2"
"github.com/moby/buildkit/client"
Expand Down Expand Up @@ -1302,7 +1303,7 @@ func updateContext(t *build.Inputs, inp *Input) {
if strings.HasPrefix(v.Path, "cwd://") || strings.HasPrefix(v.Path, "target:") || strings.HasPrefix(v.Path, "docker-image:") {
continue
}
if build.IsRemoteURL(v.Path) {
if urlutil.IsRemoteURL(v.Path) {
continue
}
st := llb.Scratch().File(llb.Copy(*inp.State, v.Path, "/"), llb.WithCustomNamef("set context %s to %s", k, v.Path))
Expand All @@ -1316,7 +1317,7 @@ func updateContext(t *build.Inputs, inp *Input) {
if strings.HasPrefix(t.ContextPath, "cwd://") {
return
}
if build.IsRemoteURL(t.ContextPath) {
if urlutil.IsRemoteURL(t.ContextPath) {
return
}
st := llb.Scratch().File(
Expand All @@ -1329,10 +1330,10 @@ func updateContext(t *build.Inputs, inp *Input) {
}

func isRemoteContext(t build.Inputs, inp *Input) bool {
if build.IsRemoteURL(t.ContextPath) {
if urlutil.IsRemoteURL(t.ContextPath) {
return true
}
if inp != nil && build.IsRemoteURL(inp.URL) && !strings.HasPrefix(t.ContextPath, "cwd://") {
if inp != nil && urlutil.IsRemoteURL(inp.URL) && !strings.HasPrefix(t.ContextPath, "cwd://") {
return true
}
return false
Expand Down Expand Up @@ -1362,7 +1363,7 @@ func collectLocalPaths(t build.Inputs) []string {
}

func isLocalPath(p string) (string, bool) {
if build.IsRemoteURL(p) || strings.HasPrefix(p, "target:") || strings.HasPrefix(p, "docker-image:") {
if urlutil.IsRemoteURL(p) || strings.HasPrefix(p, "target:") || strings.HasPrefix(p, "docker-image:") {
return "", false
}
return strings.TrimPrefix(p, "cwd://"), true
Expand All @@ -1380,7 +1381,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if t.Context != nil {
contextPath = *t.Context
}
if !strings.HasPrefix(contextPath, "cwd://") && !build.IsRemoteURL(contextPath) {
if !strings.HasPrefix(contextPath, "cwd://") && !urlutil.IsRemoteURL(contextPath) {
contextPath = path.Clean(contextPath)
}
dockerfilePath := "Dockerfile"
Expand Down Expand Up @@ -1410,7 +1411,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if err != nil {
return nil, err
}
} else if !build.IsRemoteURL(bi.DockerfilePath) && strings.HasPrefix(bi.ContextPath, "cwd://") && (inp != nil && build.IsRemoteURL(inp.URL)) {
} else if !urlutil.IsRemoteURL(bi.DockerfilePath) && strings.HasPrefix(bi.ContextPath, "cwd://") && (inp != nil && urlutil.IsRemoteURL(inp.URL)) {
// We don't currently support reading a remote Dockerfile with a local
// context when doing a remote invocation because we automatically
// derive the dockerfile from the context atm:
Expand All @@ -1432,7 +1433,7 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if v, ok := strings.CutPrefix(bi.ContextPath, "cwd://"); ok {
bi.ContextPath = path.Clean(v)
}
if !build.IsRemoteURL(bi.ContextPath) && bi.ContextState == nil && !filepath.IsAbs(bi.DockerfilePath) {
if !urlutil.IsRemoteURL(bi.ContextPath) && bi.ContextState == nil && !filepath.IsAbs(bi.DockerfilePath) {
bi.DockerfilePath = filepath.Join(bi.ContextPath, bi.DockerfilePath)
}
for k, v := range bi.NamedContexts {
Expand Down
5 changes: 3 additions & 2 deletions build/localstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/docker/buildx/builder"
"github.com/docker/buildx/localstate"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/urlutil"
"github.com/moby/buildkit/client"
)

Expand All @@ -16,13 +17,13 @@ func saveLocalState(so *client.SolveOpt, target string, opts Options, node build
}
lp := opts.Inputs.ContextPath
dp := opts.Inputs.DockerfilePath
if dp != "" && !IsRemoteURL(lp) && lp != "-" && dp != "-" {
if dp != "" && !urlutil.IsRemoteURL(lp) && lp != "-" && dp != "-" {
dp, err = filepath.Abs(dp)
if err != nil {
return err
}
}
if lp != "" && !IsRemoteURL(lp) && lp != "-" {
if lp != "" && !urlutil.IsRemoteURL(lp) && lp != "-" {
lp, err = filepath.Abs(lp)
if err != nil {
return err
Expand Down
7 changes: 4 additions & 3 deletions build/opt.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/docker/buildx/util/dockerutil"
"github.com/docker/buildx/util/osutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/urlutil"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/client/ociindex"
Expand Down Expand Up @@ -700,7 +701,7 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro
dockerfileDir = filepath.Dir(inp.DockerfilePath)
dockerfileName = filepath.Base(inp.DockerfilePath)
}
case IsRemoteURL(inp.ContextPath):
case urlutil.IsRemoteURL(inp.ContextPath):
if inp.DockerfilePath == "-" {
dockerfileReader = inp.InStream.NewReadCloser()
} else if filepath.IsAbs(inp.DockerfilePath) {
Expand Down Expand Up @@ -741,7 +742,7 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro
dockerfileName = "Dockerfile"
target.FrontendAttrs["dockerfilekey"] = "dockerfile"
}
if isHTTPURL(inp.DockerfilePath) {
if urlutil.IsHTTPURL(inp.DockerfilePath) {
dockerfileDir, err = createTempDockerfileFromURL(ctx, d, inp.DockerfilePath, pw)
if err != nil {
return nil, err
Expand Down Expand Up @@ -811,7 +812,7 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro
continue
}

if IsRemoteURL(v.Path) || strings.HasPrefix(v.Path, "docker-image://") || strings.HasPrefix(v.Path, "target:") {
if urlutil.IsRemoteURL(v.Path) || strings.HasPrefix(v.Path, "docker-image://") || strings.HasPrefix(v.Path, "target:") {
target.FrontendAttrs["context:"+k] = v.Path
processGitURL(v.Path, "context:"+k, target, caps)
continue
Expand Down
18 changes: 0 additions & 18 deletions build/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (

"github.com/docker/buildx/driver"
"github.com/docker/cli/opts"
"github.com/moby/buildkit/frontend/dockerfile/dfgitutil"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
Expand All @@ -25,23 +24,6 @@ const (
mobyHostGatewayName = "host-gateway"
)

// isHTTPURL returns true if the provided str is an HTTP(S) URL by checking if it
// has a http:// or https:// scheme. No validation is performed to verify if the
// URL is well-formed.
func isHTTPURL(str string) bool {
return strings.HasPrefix(str, "https://") || strings.HasPrefix(str, "http://")
}

func IsRemoteURL(c string) bool {
if isHTTPURL(c) {
return true
}
if _, ok, _ := dfgitutil.ParseGitRef(c); ok {
return true
}
return false
}

func isArchive(header []byte) bool {
for _, m := range [][]byte{
{0x42, 0x5A, 0x68}, // bzip2
Expand Down
5 changes: 3 additions & 2 deletions commands/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/docker/buildx/util/osutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/tracing"
"github.com/docker/buildx/util/urlutil"
"github.com/docker/cli/cli/command"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/session/auth/authprovider"
Expand Down Expand Up @@ -613,11 +614,11 @@ func saveLocalStateGroup(dockerCli command.Cli, in bakeOptions, targets []string
// from the command line arguments.
func bakeArgs(args []string) (url, cmdContext string, targets []string) {
cmdContext, targets = "cwd://", args
if len(targets) == 0 || !build.IsRemoteURL(targets[0]) {
if len(targets) == 0 || !urlutil.IsRemoteURL(targets[0]) {
return url, cmdContext, targets
}
url, targets = targets[0], targets[1:]
if len(targets) == 0 || !build.IsRemoteURL(targets[0]) {
if len(targets) == 0 || !urlutil.IsRemoteURL(targets[0]) {
return url, cmdContext, targets
}
cmdContext, targets = targets[0], targets[1:]
Expand Down
4 changes: 2 additions & 2 deletions commands/history/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import (
"sync"
"time"

"github.com/docker/buildx/build"
"github.com/docker/buildx/builder"
"github.com/docker/buildx/localstate"
"github.com/docker/buildx/util/urlutil"
"github.com/docker/cli/cli/command"
controlapi "github.com/moby/buildkit/api/services/control"
"github.com/moby/buildkit/frontend/dockerfile/dfgitutil"
Expand Down Expand Up @@ -56,7 +56,7 @@ func BuildName(fattrs map[string]string, ls *localstate.State) string {
}

var localPath string
if ls != nil && !build.IsRemoteURL(ls.LocalPath) {
if ls != nil && !urlutil.IsRemoteURL(ls.LocalPath) {
if ls.LocalPath != "" && ls.LocalPath != "-" {
localPath = filepath.ToSlash(ls.LocalPath)
}
Expand Down
25 changes: 25 additions & 0 deletions util/urlutil/urlutil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package urlutil

import (
"strings"

"github.com/moby/buildkit/frontend/dockerfile/dfgitutil"
)

// IsHTTPURL returns true if the provided str is an HTTP(S) URL by checking if
// it has a http:// or https:// scheme. No validation is performed to verify if
// the URL is well-formed.
func IsHTTPURL(str string) bool {
return strings.HasPrefix(str, "https://") || strings.HasPrefix(str, "http://")
}

// IsRemoteURL returns true for HTTP(S) URLs and Git references.
func IsRemoteURL(c string) bool {
if IsHTTPURL(c) {
return true
}
if _, ok, _ := dfgitutil.ParseGitRef(c); ok {
return true
}
return false
}
110 changes: 110 additions & 0 deletions util/urlutil/urlutil_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package urlutil

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestIsHTTPURL(t *testing.T) {
tests := []struct {
name string
input string
want bool
}{
{
name: "https url",
input: "https://example.com/repo.git",
want: true,
},
{
name: "http url",
input: "http://example.com/repo.git",
want: true,
},
{
name: "http prefix only",
input: "http://",
want: true,
},
{
name: "non-http protocol",
input: "git://example.com/repo.git",
want: false,
},
{
name: "no protocol",
input: "example.com/repo.git",
want: false,
},
{
name: "uppercase protocol is not matched",
input: "HTTPS://example.com/repo.git",
want: false,
},
{
name: "leading whitespace does not match",
input: " https://example.com/repo.git",
want: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
require.Equal(t, tc.want, IsHTTPURL(tc.input))
})
}
}

func TestIsRemoteURL(t *testing.T) {
tests := []struct {
name string
input string
want bool
}{
{
name: "https url is remote",
input: "https://example.com/not-a-git-url",
want: true,
},
{
name: "http url is remote",
input: "http://example.com/path",
want: true,
},
{
name: "scp style git remote",
input: "git@github.com:moby/buildkit.git",
want: true,
},
{
name: "github shorthand git remote",
input: "github.com/moby/buildkit",
want: true,
},
{
name: "relative local path is not remote",
input: "./hack",
want: false,
},
{
name: "plain local path is not remote",
input: "hack/dockerfiles",
want: false,
},
{
name: "unknown protocol is not remote",
input: "docker-image://alpine",
want: false,
},
{
name: "empty is not remote",
input: "",
want: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
require.Equal(t, tc.want, IsRemoteURL(tc.input))
})
}
}