Skip to content

Commit a5a59ed

Browse files
authored
find bazel exec if not specified via command line (#7)
* find bazel exec if not specified via command line * output impacted targets in verbose mode
1 parent 4515697 commit a5a59ed

4 files changed

Lines changed: 101 additions & 12 deletions

File tree

.github/workflows/bazel-ci.yaml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,15 @@ jobs:
3333
id: get-revisions
3434
run: GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} ./tools/diff-sha.sh
3535
- name: get-test-targets
36-
run: $(bazel info bazel-bin)/cli/bazel-differ_/bazel-differ get-targets -w $(pwd) -b $(which bazelisk) -s ${{ steps.get-revisions.outputs.previous_sha }} -f ${{ steps.get-revisions.outputs.current_sha }} -o test_targets.txt
36+
run: $(bazel info bazel-bin)/cli/bazel-differ_/bazel-differ get-targets -w $(pwd) -s ${{ steps.get-revisions.outputs.previous_sha }} -f ${{ steps.get-revisions.outputs.current_sha }} -o test_targets.txt
3737
- name: run-test-targets
3838
if: hashFiles('test_targets.txt') != ''
39-
run: |
40-
cat test_targets.txt
41-
bazel test --target_pattern_file=test_targets.txt
39+
run: bazel test --target_pattern_file=test_targets.txt || echo "No targets to run."
4240
- name: get-build-targets
43-
run: $(bazel info bazel-bin)/cli/bazel-differ_/bazel-differ get-targets -w $(pwd) -b $(which bazelisk) -s ${{ steps.get-revisions.outputs.previous_sha }} -f ${{ steps.get-revisions.outputs.current_sha }} -o build_targets.txt
44-
- name: run-build-targets
4541
if: hashFiles('build_targets.txt') != ''
46-
run: |
47-
cat build_targets.txt
48-
bazel build --target_pattern_file=build_targets.txt || echo "No targets to run."
42+
run: $(bazel info bazel-bin)/cli/bazel-differ_/bazel-differ get-targets -w $(pwd) -s ${{ steps.get-revisions.outputs.previous_sha }} -f ${{ steps.get-revisions.outputs.current_sha }} -o build_targets.txt -v
43+
- name: run-build-targets
44+
run: bazel build --target_pattern_file=build_targets.txt || echo "No targets to run."
4945
# Run tests
5046
- name: gazelle check
5147
run: bazel run //:gazelle_ci

cmd/get_targets.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ $ bazel-differ get-targets -w path/to/workspace -b $(which bazel) -s START_HASH
4444

4545
if Output != "" {
4646
internal.WriteTargetsFile(targetNames, Output)
47-
} else {
47+
}
48+
49+
if Output == "" || Verbose {
4850
for k := range targetNames {
4951
fmt.Println(k)
5052
}

cmd/root.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ package cmd
33
import (
44
"fmt"
55
"github.com/ewhauser/bazel-differ/internal"
6-
"os"
7-
86
"github.com/spf13/cobra"
7+
"os"
98
)
109

1110
var WorkspacePath string

internal/bazel.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,98 @@ import (
2424
"log"
2525
"os"
2626
"os/exec"
27+
"path/filepath"
2728
"strings"
2829
"time"
2930
)
3031

32+
// bazelNpmPath looks up a relative path to a binary from @bazel/bazel
33+
// This is used as an alternate resolution when no bazel binary is in the $PATH
34+
// When running from the @bazel/ibazel npm package, our binary is
35+
// /DIR/node_modules/@bazel/ibazel/bin/darwin_amd64/ibazel
36+
// We can find bazel in
37+
// /DIR/node_modules/@bazel/bazel-darwin_x64/bazel-0.28.0-darwin-x86_64
38+
func bazelNpmPath(ibazelBinPath string) (string, error) {
39+
s := strings.Split(ibazelBinPath, "/")
40+
for i := 0; i+4 < len(s); i++ {
41+
prefix, nm, scope, pkg, dir, bin := s[0:i], s[i], s[i+1], s[i+2], s[i+3], s[i+4]
42+
if nm == "node_modules" && scope == "@bazel" && pkg == "ibazel" && dir == "bin" {
43+
// See mapping in release/npm/index.js - ibazel is named with "amd64" arch
44+
// but @bazel/bazel uses node arch names
45+
arch := strings.Replace(bin, "amd64", "x64", 1)
46+
dir := strings.Join(append(prefix, nm, scope, "bazel-"+arch), "/")
47+
// Find the bazel binary in the directory - it will have a version number in the name
48+
// so we list all the files and find a bazel-*-$ARCH
49+
if fd, err := os.Open(filepath.FromSlash(dir)); err == nil {
50+
if names, err := fd.Readdirnames(0); err == nil {
51+
for j := 0; j < len(names); j++ {
52+
if strings.HasPrefix(names[j], "bazel-") {
53+
return dir + "/" + names[j], nil
54+
}
55+
}
56+
}
57+
}
58+
}
59+
}
60+
return "", errors.New("bazel binary not found in @bazel/bazel package")
61+
}
62+
63+
// bazeliskNpmPath looks up a relative path to a binary from @bazel/bazelisk
64+
// This is used as an alternate resolution when no bazel binary is in the $PATH
65+
// When running from the @bazel/ibazel npm package, our binary is
66+
// /DIR/node_modules/@bazel/ibazel/bin/darwin_amd64/ibazel
67+
// We can find bazelisk in
68+
// /DIR/node_modules/@bazel/bazelisk/bazelizk-darwin_amd64
69+
func bazeliskNpmPath(ibazelBinPath string) (string, error) {
70+
s := strings.Split(ibazelBinPath, "/")
71+
for i := 0; i+4 < len(s); i++ {
72+
prefix, nm, scope, pkg, dir, bin := s[0:i], s[i], s[i+1], s[i+2], s[i+3], s[i+4]
73+
if nm == "node_modules" && scope == "@bazel" && pkg == "ibazel" && dir == "bin" {
74+
var ext string
75+
if strings.HasPrefix(bin, "windows_") {
76+
ext = ".exe"
77+
}
78+
name := strings.Join(append(prefix, nm, scope, "bazelisk", "bazelisk-"+bin+ext), "/")
79+
_, err := os.Stat(name)
80+
if err != nil {
81+
if !os.IsNotExist(err) {
82+
return "", err
83+
}
84+
continue
85+
}
86+
return name, nil
87+
}
88+
}
89+
return "", errors.New("bazelisk binary not found in @bazel/bazelisk package")
90+
}
91+
92+
func findBazel() string {
93+
// Frontend devs may have installed @bazel/bazelisk and @bazel/ibazel from npm
94+
// If they also have bazelisk in the $PATH, we want to resolve this one, to avoid version skew
95+
if npmPath, err := bazeliskNpmPath(filepath.ToSlash(os.Args[0])); err == nil {
96+
return filepath.FromSlash(npmPath)
97+
}
98+
// Frontend devs may have installed @bazel/bazel and @bazel/ibazel from npm
99+
// If they also have bazel in the $PATH, we want to resolve this one, to avoid version skew
100+
if npmPath, err := bazelNpmPath(filepath.ToSlash(os.Args[0])); err == nil {
101+
return filepath.FromSlash(npmPath)
102+
}
103+
// Check in $PATH for system-installed Bazelisk
104+
if path, err := exec.LookPath("bazelisk"); err == nil {
105+
return path
106+
}
107+
// Check in $PATH for system-installed Bazel
108+
if path, err := exec.LookPath("bazel"); err == nil {
109+
return path
110+
}
111+
112+
// If we've fallen through to here, the lookup won't succeed.
113+
// Return "bazel" so that we'll later fail with an error
114+
// exec: "bazel": executable file not found in $PATH
115+
// which helps the user understand that we looked in the $PATH
116+
return "bazel"
117+
}
118+
31119
type Bazel interface {
32120
SetArguments([]string)
33121
SetStartupArgs([]string)
@@ -58,6 +146,10 @@ type bazel struct {
58146
}
59147

60148
func NewBazel(path string, workingDirectory string) Bazel {
149+
if path == "" {
150+
path = findBazel()
151+
}
152+
61153
return &bazel{
62154
path: path,
63155
workingDirectory: workingDirectory,

0 commit comments

Comments
 (0)