Merge pull request #3646 from crazy-max/urlutil

history: don't import build package
This commit is contained in:
Tõnis Tiigi
2026-02-11 10:59:05 -08:00
committed by GitHub
8 changed files with 156 additions and 35 deletions
+9 -8
View File
@@ -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"
@@ -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))
@@ -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(
@@ -1330,10 +1331,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
@@ -1363,7 +1364,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
@@ -1381,7 +1382,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"
@@ -1411,7 +1412,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:
@@ -1433,7 +1434,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 {
+3 -2
View File
@@ -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"
)
@@ -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
+4 -3
View File
@@ -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"
@@ -710,7 +711,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) {
@@ -751,7 +752,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
@@ -824,7 +825,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
-18
View File
@@ -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"
)
@@ -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
+3 -2
View File
@@ -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"
@@ -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:]
+2 -2
View File
@@ -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"
@@ -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)
}
+25
View File
@@ -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
View File
@@ -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))
})
}
}