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
2 changes: 1 addition & 1 deletion .bazelversion
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.6.2
8.2.1
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ bazel_dep(name = "bazel_skylib", version = "1.8.2")
bazel_dep(name = "rules_proto", version = "7.1.0")
bazel_dep(name = "rules_go", version = "0.57.0", repo_name = "io_bazel_rules_go")
bazel_dep(name = "gazelle", version = "0.45.0", repo_name = "bazel_gazelle")
bazel_dep(name = "bazel_features", version = "1.21.0")

# Configure Go SDK
go_sdk = use_extension("@io_bazel_rules_go//go:extensions.bzl", "go_sdk")
Expand Down
1,126 changes: 41 additions & 1,085 deletions MODULE.bazel.lock

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion cmd/ibazel/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ var Version = "Development"

var overrideableStartupFlags []string = []string{
"--bazelrc",
"--bazelrc=",
"--nobazelrc",
"--home_rc",
"--nohome_rc",
"--output_base",
Expand All @@ -53,6 +55,9 @@ var overrideableBazelFlags []string = []string{
"--define=",
"--dynamic_mode=",
"--enable_bzlmod=",
"--enable_bzlmod",
"--enable_workspace",
"--enable_workspace=",
"--features=",
"--flaky_test_attempts=",
"--host_jvmopt",
Expand All @@ -62,6 +67,7 @@ var overrideableBazelFlags []string = []string{
"-k",
"--nocache_test_results",
"--noenable_bzlmod",
"--noenable_workspace",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey @janwinkler1 with changes like this, and where bazel changes an --experimental_<something> into a --<something> do we need to start determining the bazel version before choosing which arguments pass-through ? Or should we keep a super-set of all arguments, and let bazel figure out which don't work for its version ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chickenandpork TBH i am a bit torn on what the best approach might be. AFAIU

bazel 7: WORKSPACE is the default, BZLMOD needs to be enabled
bazel 8: WORKSPACE needs to be enabled, BZLMOD is the default
bazel 9: according to https://bazel.build/about/roadmap WORKSPACE might not even be supported anymore, BZLMOD is the default

therefore, if we want to cater all versions, something where bazel "figures this out itself" might be the best option? altough not the safest?

but ATM i was too invested with trying to fight windows, without a windows PC :/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@janwinkler1 your efforts are appreciated too -- I don't think any of us has a Windows box online :)

The CI presents its own challenges.

Are you on the ibazel slack channel ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chickenandpork thank you! no i am not :)

"--nostamp",
"--output_groups=",
"--override_repository=",
Expand Down Expand Up @@ -214,7 +220,7 @@ func applyDefaultBazelArgs(bazelArgs []string) []string {
return bazelArgs
}
}
if (isTerminal()) {
if isTerminal() {
return append(bazelArgs, "--isatty=1")
} else {
return append(bazelArgs, "--isatty=0")
Expand Down
10 changes: 7 additions & 3 deletions internal/bazel/bazel.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,8 @@ func (b *bazel) newCommand(command string, args ...string) (*bytes.Buffer, *byte
func (b *bazel) Info() (map[string]string, *bytes.Buffer, error) {
b.WriteToStderr(false)
b.WriteToStdout(false)
stdoutBuffer, stderrBuffer := b.newCommand("info")

stdoutBuffer, stderrBuffer:= b.newCommand("info", b.args...)
// This gofunction only prints if 'bazel info' takes longer than 8 seconds
doneCh := make(chan struct{})
defer close(doneCh)
Expand Down Expand Up @@ -293,6 +293,7 @@ func (b *bazel) processInfo(info string) (map[string]string, error) {
func (b *bazel) Query(args ...string) (*blaze_query.QueryResult, error) {
blazeArgs := append([]string(nil), "--output=proto", "--order_output=no", "--color=no")
blazeArgs = append(blazeArgs, args...)
blazeArgs = append(blazeArgs, b.args...)

b.WriteToStderr(true) // revert 34c48343 (#536: Improve logging infrastructure) TODO: hide behind argument?
b.WriteToStdout(false)
Expand Down Expand Up @@ -384,10 +385,13 @@ func (b *bazel) Test(args ...string) (*bytes.Buffer, error) {
func (b *bazel) Run(args ...string) (*exec.Cmd, *bytes.Buffer, error) {
b.WriteToStderr(true)
b.WriteToStdout(true)
stdoutBuffer, stderrBuffer := b.newCommand("run", append(b.args, args...)...)
runArgs := append(b.args, args...)
stdoutBuffer, stderrBuffer := b.newCommand("run", runArgs...)
b.cmd.Stdin = os.Stdin

_, _ = stdoutBuffer.Write(stderrBuffer.Bytes())
if _, err := stdoutBuffer.Write(stderrBuffer.Bytes()); err != nil {
return nil, nil, fmt.Errorf("stdout.write(): %w", err)
}

err := b.cmd.Run()
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions internal/e2e/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ go_library(
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
"@io_bazel_rules_go//go/tools/bazel_testing:go_default_library",
"@org_golang_x_tools//txtar",
"//internal/utils"
],
)
56 changes: 33 additions & 23 deletions internal/e2e/ibazel.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"testing"
"time"

"github.com/bazelbuild/bazel-watcher/internal/utils"
"github.com/bazelbuild/rules_go/go/tools/bazel_testing"
)

Expand All @@ -22,6 +23,10 @@ const (
defaultDelay = 50 * time.Second
)

var defaultFlags = []string{
"--graceful_termination_wait_duration=1s",
}

type IBazelTester struct {
t *testing.T
ibazelLogFile string
Expand All @@ -35,9 +40,9 @@ type IBazelTester struct {
}

func NewIBazelTester(t *testing.T) *IBazelTester {
f, err := ioutil.TempFile("", "ibazel_output.*.log")
f, err := os.CreateTemp("", "ibazel_output.*.log")
if err != nil {
panic(fmt.Sprintf("Error ioutil.Tempfile: %v", err))
panic(fmt.Sprintf("Error os.CreateTemp: %v", err))
}

return &IBazelTester{
Expand Down Expand Up @@ -66,13 +71,14 @@ func (i *IBazelTester) Test(bazelArgs []string, targets ...string) {
args := []string{"--bazel_path=" + i.bazelPath()}
args = append(args,
"--log_to_file="+i.ibazelLogFile,
"--graceful_termination_wait_duration=1s")
)
args = append(args, "test")
args = append(args, "--bazelrc=/dev/null")
bazelArgs = utils.EnsureBazel8Compatibility(bazelArgs)
args = append(args, targets...)
args = append(args, bazelArgs...)
i.cmd = exec.Command(ibazelPath, args...)
i.t.Logf("ibazel invoked as: %s", strings.Join(i.cmd.Args, " "))
i.t.Logf("ibazel invoked in %s as: %s", i.cmd.Dir,
strings.Join(i.cmd.Args, " "))

i.stdoutBuffer = &Buffer{}
i.cmd.Stdout = i.stdoutBuffer
Expand All @@ -89,15 +95,17 @@ func (i *IBazelTester) Coverage(bazelArgs []string, targets ...string) {
i.t.Helper()

args := []string{"--bazel_path=" + i.bazelPath()}
args = append(args, defaultFlags...)
args = append(args,
"--log_to_file="+i.ibazelLogFile,
"--graceful_termination_wait_duration=1s")
)
args = append(args, "coverage")
args = append(args, "--bazelrc=/dev/null")
bazelArgs = utils.EnsureBazel8Compatibility(bazelArgs)
args = append(args, targets...)
args = append(args, bazelArgs...)
i.cmd = exec.Command(ibazelPath, args...)
i.t.Logf("ibazel invoked as: %s", strings.Join(i.cmd.Args, " "))
i.t.Logf("ibazel invoked in %s as: %s", i.cmd.Dir,
strings.Join(i.cmd.Args, " "))

i.stdoutBuffer = &Buffer{}
i.cmd.Stdout = i.stdoutBuffer
Expand All @@ -112,24 +120,22 @@ func (i *IBazelTester) Coverage(bazelArgs []string, targets ...string) {

func (i *IBazelTester) Run(bazelArgs []string, target string) {
i.t.Helper()
i.run(target, bazelArgs, []string{
"--log_to_file=" + i.ibazelLogFile,
"--graceful_termination_wait_duration=1s",
})
i.run(target, utils.EnsureBazel8Compatibility(bazelArgs), append(defaultFlags,
"--log_to_file="+i.ibazelLogFile,
))
}

func (i *IBazelTester) RunWithProfiler(target string, profiler string) {
i.t.Helper()
i.run(target, []string{}, []string{
"--log_to_file=" + i.ibazelLogFile,
"--graceful_termination_wait_duration=1s",
"--profile_dev=" + profiler,
})
i.run(target, utils.EnsureBazel8Compatibility([]string{}), append(defaultFlags,
"--log_to_file="+i.ibazelLogFile,
"--profile_dev="+profiler,
))
}

func (i *IBazelTester) runWithFixCommands(target string, prebuild bool) {
i.t.Helper()
i.runUnverified(target, []string{}, []string{
i.runUnverified(target, utils.EnsureBazel8Compatibility([]string{}), []string{
"--log_to_file=" + i.ibazelLogFile,
"--graceful_termination_wait_duration=1s",
"--run_output=true",
Expand All @@ -150,13 +156,13 @@ func (i *IBazelTester) RunUnverifiedWithBazelFixCommands(target string) {

func (i *IBazelTester) RunWithAdditionalArgs(target string, additionalArgs []string) {
i.t.Helper()
i.run(target, []string{}, additionalArgs)
i.run(target, utils.EnsureBazel8Compatibility([]string{}), additionalArgs)
}

func (i *IBazelTester) RunUnverifiedWithAdditionalArgs(target string, additionalArgs []string) {
i.t.Helper()
prebuild := false
i.runUnverified(target, []string{}, additionalArgs, prebuild)
i.runUnverified(target, utils.EnsureBazel8Compatibility([]string{}), additionalArgs, prebuild)
}

func (i *IBazelTester) GetOutput() string {
Expand Down Expand Up @@ -440,15 +446,17 @@ func (i *IBazelTester) runUnverified(target string, bazelArgs []string, addition
args := []string{"--bazel_path=" + i.bazelPath()}
args = append(args, additionalArgs...)
args = append(args, "run")
args = append(args, "--bazelrc=/dev/null")

args = append(args, target)
args = append(args, bazelArgs...)
i.cmd = exec.Command(ibazelPath, args...)
i.t.Logf("ibazel invoked as: %s", strings.Join(i.cmd.Args, " "))
i.t.Logf("ibazel invoked in %s as: %s in: %s",
i.cmd.Dir, strings.Join(i.cmd.Args, " "),
os.Getenv("TEST_TMPDIR"))

checkArgs := []string{"build"}
checkArgs = append(checkArgs, target)
checkArgs = append(checkArgs, bazelArgs...)
checkArgs = append(checkArgs, utils.EnsureBazel8Compatibility(bazelArgs)...)
cmd := bazel_testing.BazelCmd(checkArgs...)

var buildStdout, buildStderr bytes.Buffer
Expand All @@ -461,6 +469,8 @@ func (i *IBazelTester) runUnverified(target string, bazelArgs []string, addition
if exitErr, ok := err.(*exec.ExitError); ok {
status := exitErr.Sys().(syscall.WaitStatus)
i.t.Fatalf("Unable to build target. Error code: %d\nStdout:\n%s\nStderr:\n%s", status.ExitStatus(), buildStdout.String(), buildStderr.String())
} else {
i.t.Fatalf("Unable to build target. %v", err)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions internal/ibazel/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ go_library(
visibility = ["//:__subpackages__"],
deps = [
"//internal/bazel",
"//internal/utils",
"//internal/ibazel/command",
"//internal/ibazel/fswatcher",
"//internal/ibazel/fswatcher/common",
Expand Down
10 changes: 6 additions & 4 deletions internal/ibazel/ibazel.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"time"

"github.com/bazelbuild/bazel-watcher/internal/bazel"
"github.com/bazelbuild/bazel-watcher/internal/utils"
"github.com/bazelbuild/bazel-watcher/internal/ibazel/command"
"github.com/bazelbuild/bazel-watcher/internal/ibazel/fswatcher"
"github.com/bazelbuild/bazel-watcher/internal/ibazel/fswatcher/common"
Expand All @@ -43,9 +44,9 @@ var bazelNew = bazel.New
var commandDefaultCommand = command.DefaultCommand
var commandNotifyCommand = command.NotifyCommand
var exitMessages = map[os.Signal]string{
syscall.SIGINT: "Subprocess killed from getting SIGINT (trigger SIGINT again to stop ibazel)",
syscall.SIGTERM: "Subprocess killed from getting SIGTERM",
syscall.SIGHUP: "Subprocess killed from getting SIGHUP",
syscall.SIGINT: "Subprocess killed from getting SIGINT (trigger SIGINT again to stop ibazel)",
syscall.SIGTERM: "Subprocess killed from getting SIGTERM",
syscall.SIGHUP: "Subprocess killed from getting SIGHUP",
}

type State string
Expand Down Expand Up @@ -169,7 +170,8 @@ func (i *IBazel) handleSignals() {
func (i *IBazel) newBazel() bazel.Bazel {
b := bazelNew()
b.SetStartupArgs(i.startupArgs)
b.SetArguments(i.bazelArgs)
bazelArgs := utils.EnsureBazel8Compatibility(i.bazelArgs)
b.SetArguments(bazelArgs)
return b
}

Expand Down
12 changes: 6 additions & 6 deletions internal/ibazel/ibazel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,10 @@ func TestIBazelBuild(t *testing.T) {
i.build("//path/to:target")
expected := [][]string{
{"SetStartupArgs"},
{"SetArguments"},
{"SetArguments", "--enable_bzlmod"},
{"Info"},
{"SetStartupArgs"},
{"SetArguments"},
{"SetArguments", "--enable_bzlmod"},
{"Cancel"},
{"WriteToStderr", "true"},
{"WriteToStdout", "true"},
Expand Down Expand Up @@ -337,16 +337,16 @@ func TestIBazelTest(t *testing.T) {
i.test("//path/to:target")
expected := [][]string{
{"SetStartupArgs"},
{"SetArguments"},
{"SetArguments", "--enable_bzlmod"},
{"Info"},
{"SetStartupArgs"},
{"SetArguments"},
{"SetArguments", "--enable_bzlmod"},
{"SetStartupArgs"},
{"SetArguments"},
{"SetArguments", "--enable_bzlmod"},
{"WriteToStderr", "false"},
{"WriteToStdout", "false"},
{"CQuery", "//path/to:target"},
{"SetArguments", "--test_output=streamed"},
{"SetArguments", "--test_output=streamed", "--enable_bzlmod"},
{"Cancel"},
{"WriteToStderr", "true"},
{"WriteToStdout", "true"},
Expand Down
14 changes: 14 additions & 0 deletions internal/utils/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "utils",
srcs = ["compatibility.go"],
importpath = "github.com/bazelbuild/bazel-watcher/internal/utils",
visibility = ["//visibility:public"],
)

go_test(
name = "utils_test",
srcs = ["compatibility_test.go"],
embed = [":utils"],
)
51 changes: 51 additions & 0 deletions internal/utils/compatibility.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package utils

import (
"os"
"strings"
)

// EnsureBazel8Compatibility adds appropriate --enable_bzlmod or --enable_workspace
// flags to bazel arguments when running with Bazel 8+, which requires explicit
// selection between bzlmod and WORKSPACE modes.
func EnsureBazel8Compatibility(args []string) []string {
// If user already specified a mode, respect their choice
for _, arg := range args {
if strings.HasPrefix(arg, "--enable_bzlmod") || strings.HasPrefix(arg, "--enable_workspace") {
return args
}
}

// Check for local_repository usage (forces WORKSPACE mode)
if hasLocalRepository() {
return append(args, "--enable_workspace")
}

// Auto-detect based on project files in current directory
if _, err := os.Stat("MODULE.bazel"); err == nil {
return append(args, "--enable_bzlmod")
}
if _, err := os.Stat("WORKSPACE"); err == nil {
return append(args, "--enable_workspace")
}
if _, err := os.Stat("WORKSPACE.bazel"); err == nil {
return append(args, "--enable_workspace")
}

// Default to bzlmod for new projects
return append(args, "--enable_bzlmod")
}

func hasLocalRepository() bool {
workspaceData, err := os.ReadFile("WORKSPACE")
if err != nil {
return false // No WORKSPACE file or can't read it
}

for _, line := range strings.Split(string(workspaceData), "\n") {
if strings.HasPrefix(strings.TrimSpace(line), "local_repository(") {
return true
}
}
return false
}
Loading