diff --git a/WORKSPACE b/WORKSPACE index 9ed0a61c..e3c25bae 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -16,6 +16,8 @@ # workspace(name = "io_bazel_rules_webtesting") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + # NOTE: URLs are mirrored by an asynchronous review process. They must # be greppable for that to happen. It's OK to submit broken mirror # URLs, so long as they're correctly formatted. Bazel's downloader diff --git a/go/wtl/environment/sauce/sauce.go b/go/wtl/environment/sauce/sauce.go index 6f0326f5..7e908b74 100644 --- a/go/wtl/environment/sauce/sauce.go +++ b/go/wtl/environment/sauce/sauce.go @@ -58,6 +58,7 @@ func NewEnv(m *metadata.Metadata, d diagnostics.Diagnostics) (environment.Env, e } connect = c + address = c.Address } base, err := environment.NewBase(name, m, d) diff --git a/go/wtl/service/sauce/BUILD.bazel b/go/wtl/service/sauce/BUILD.bazel index d69253b4..6984c709 100644 --- a/go/wtl/service/sauce/BUILD.bazel +++ b/go/wtl/service/sauce/BUILD.bazel @@ -28,5 +28,6 @@ go_library( deps = [ "//go/errors:go_default_library", "//go/metadata:go_default_library", + "//go/portpicker:go_default_library", ], ) diff --git a/go/wtl/service/sauce/connect.go b/go/wtl/service/sauce/connect.go index aefb751a..75c793b0 100644 --- a/go/wtl/service/sauce/connect.go +++ b/go/wtl/service/sauce/connect.go @@ -18,12 +18,15 @@ package sauce import ( "bufio" "context" + "fmt" "os/exec" + "strconv" "strings" "sync" "github.com/bazelbuild/rules_webtesting/go/errors" "github.com/bazelbuild/rules_webtesting/go/metadata" + "github.com/bazelbuild/rules_webtesting/go/portpicker" ) const ( @@ -31,12 +34,17 @@ const ( scNamedFile = "SAUCE_CONNECT" ) +// Connect is a service that manages Sauce Connect. type Connect struct { + // Address is the address that the Sauce Connect Selenium relay is running on. + Address string + cmd *exec.Cmd mu sync.Mutex ready bool err error + port int } // New creates a new service that manages Sauce Connect. @@ -46,13 +54,23 @@ func New(m *metadata.Metadata, username, accessKey, tunnelID string) (*Connect, return nil, errors.New(compName, err) } + port, err := portpicker.PickUnusedPort() + if err != nil { + return nil, errors.New(compName, err) + } + cmd := exec.Command( scPath, "--user", username, "--api-key", accessKey, - "--tunnel-identifier", tunnelID) - - return &Connect{cmd: cmd}, nil + "--tunnel-identifier", tunnelID, + "--se-port", strconv.Itoa(port)) + + return &Connect{ + cmd: cmd, + port: port, + Address: fmt.Sprintf("http://%s:%s@localhost:%d/wd/hub/", username, accessKey, port), + }, nil } // Start starts Sauce Connect and waits for it to be ready for use. @@ -121,6 +139,8 @@ func (c *Connect) monitor() { c.ready = false c.err = err } + + portpicker.RecycleUnusedPort(c.port) } func (c *Connect) Name() string { diff --git a/web/repositories.bzl b/web/repositories.bzl index 54f0f4d3..bdb95670 100644 --- a/web/repositories.bzl +++ b/web/repositories.bzl @@ -16,6 +16,7 @@ load("//web/internal:java_import_external.bzl", "java_import_external") load("//web/internal:platform_http_file.bzl", "platform_http_file") load("@bazel_gazelle//:deps.bzl", "go_repository") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # NOTE: URLs are mirrored by an asynchronous review process. They must # be greppable for that to happen. It's OK to submit broken mirror @@ -142,7 +143,7 @@ def browser_repositories(firefox = False, chromium = False, sauce = False): com_saucelabs_sauce_connect() def bazel_skylib(): - native.http_archive( + http_archive( name = "bazel_skylib", sha256 = "d7cffbed034d1203858ca19ff2e88d241781f45652a4c719ed48eedc74bc82a9", strip_prefix = "bazel-skylib-0.3.1", @@ -498,7 +499,7 @@ def org_mozilla_geckodriver(): ) def org_seleniumhq_py(): - native.new_http_archive( + http_archive( name = "org_seleniumhq_py", build_file = str(Label("//build_files:org_seleniumhq_py.BUILD")), sha256 = "5841fb30c3965866220c34d16de8e3d091e2833fcac385160a63db0c3522a297",