This repository was archived by the owner on Sep 30, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
SG start bazel enhancements #59718
Merged
Merged
SG start bazel enhancements #59718
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
fcc49fc
WIP draft
jamesmcnamara c12eae5
Merge branch 'main' of github.com:sourcegraph/sourcegraph into jsm/sg…
jamesmcnamara 0f47a01
cleanup
jamesmcnamara 1e0f25d
added output buffering
jamesmcnamara 5a6a4b8
fixed process exiting (I think)
jamesmcnamara 9de816c
added bazel run targets
jamesmcnamara 016b419
Merge branch 'main' into jsm/sg-start-bazel
jamesmcnamara a3f3ae5
ran go mod tidy and gazelle
jamesmcnamara 6b36048
WIP draft
jamesmcnamara b722598
cleanup
jamesmcnamara 3bb5155
added output buffering
jamesmcnamara cd1787a
fixed process exiting (I think)
jamesmcnamara 3bd8396
added bazel run targets
jamesmcnamara 83cb560
ran go mod tidy and gazelle
jamesmcnamara a9407b8
Merge branch 'jsm/sg-start-bazel' of github.com:sourcegraph/sourcegra…
jamesmcnamara d94df1f
fixed installing progress bar render issue
jamesmcnamara 0f47f02
Merge branch 'main' into jsm/sg-start-bazel
jamesmcnamara feeb869
Removed closes that were causing race conditions
jamesmcnamara f572b05
Merge branch 'main' of github.com:sourcegraph/sourcegraph into jsm/sg…
jamesmcnamara ebc2b71
logging extracted from ibazel output
jamesmcnamara 291c219
only log first and relevant errors
jamesmcnamara 737bcbb
Merge branch 'main' into jsm/sg-start-bazel
jamesmcnamara 72958b9
removed slow testing command
jamesmcnamara File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,17 @@ | ||
[] | ||
[ | ||
{ | ||
"regex": "^Check that imports in Go sources match importpath attributes in deps.$", | ||
"command": "./dev/bazel_configure_accept_changes.sh", | ||
"args": [] | ||
}, | ||
{ | ||
"regex": "missing input file", | ||
"command": "./dev/bazel_configure_accept_changes.sh", | ||
"args": [] | ||
}, | ||
{ | ||
"regex": ": undefined:", | ||
"command": "./dev/bazel_configure_accept_changes.sh", | ||
"args": [] | ||
} | ||
] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#! /bin/bash | ||
|
||
# Run bazel configure and if the error code is 110, exit with error code 0 | ||
bazel configure | ||
exit_code=$? | ||
|
||
if [ $exit_code -eq 0 ]; then | ||
echo "No configuration changes made" | ||
exit 0 | ||
elif [ $exit_code -eq 110 ]; then | ||
echo "Bazel configuration completed" | ||
exit 0 | ||
else | ||
echo "Unknown error" | ||
exit $exit_code | ||
fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,150 +3,108 @@ package run | |
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"os/exec" | ||
"strings" | ||
|
||
"github.com/rjeczalik/notify" | ||
"github.com/sourcegraph/sourcegraph/dev/sg/internal/secrets" | ||
"github.com/sourcegraph/sourcegraph/dev/sg/internal/std" | ||
"github.com/sourcegraph/sourcegraph/lib/errors" | ||
"github.com/sourcegraph/sourcegraph/lib/output" | ||
"github.com/sourcegraph/sourcegraph/lib/process" | ||
) | ||
|
||
// A BazelCommand is a command definition for sg run/start that uses | ||
// bazel under the hood. It will handle restarting itself autonomously, | ||
// as long as iBazel is running and watch that specific target. | ||
type BazelCommand struct { | ||
Name string | ||
Description string `yaml:"description"` | ||
Target string `yaml:"target"` | ||
Args string `yaml:"args"` | ||
PreCmd string `yaml:"precmd"` | ||
Env map[string]string `yaml:"env"` | ||
IgnoreStdout bool `yaml:"ignoreStdout"` | ||
IgnoreStderr bool `yaml:"ignoreStderr"` | ||
Name string | ||
Description string `yaml:"description"` | ||
Target string `yaml:"target"` | ||
Args string `yaml:"args"` | ||
PreCmd string `yaml:"precmd"` | ||
Env map[string]string `yaml:"env"` | ||
IgnoreStdout bool `yaml:"ignoreStdout"` | ||
IgnoreStderr bool `yaml:"ignoreStderr"` | ||
ContinueWatchOnExit bool `yaml:"continueWatchOnExit"` | ||
// Preamble is a short and visible message, displayed when the command is launched. | ||
Preamble string `yaml:"preamble"` | ||
ExternalSecrets map[string]secrets.ExternalSecret `yaml:"external_secrets"` | ||
} | ||
|
||
func (bc *BazelCommand) BinLocation() (string, error) { | ||
return binLocation(bc.Target) | ||
func (bc BazelCommand) GetName() string { | ||
return bc.Name | ||
} | ||
|
||
func (bc *BazelCommand) watch(ctx context.Context) (<-chan struct{}, error) { | ||
// Grab the location of the binary in bazel-out. | ||
binLocation, err := bc.BinLocation() | ||
if err != nil { | ||
return nil, err | ||
} | ||
func (bc BazelCommand) GetContinueWatchOnExit() bool { | ||
return bc.ContinueWatchOnExit | ||
} | ||
|
||
// Set up the watcher. | ||
restart := make(chan struct{}) | ||
events := make(chan notify.EventInfo, 1) | ||
if err := notify.Watch(binLocation, events, notify.All); err != nil { | ||
return nil, err | ||
} | ||
func (bc BazelCommand) GetEnv() map[string]string { | ||
return bc.Env | ||
} | ||
|
||
// Start watching for a freshly compiled version of the binary. | ||
go func() { | ||
defer close(events) | ||
defer notify.Stop(events) | ||
|
||
for { | ||
select { | ||
case <-ctx.Done(): | ||
return | ||
case e := <-events: | ||
if e.Event() != notify.Remove { | ||
restart <- struct{}{} | ||
} | ||
} | ||
|
||
} | ||
}() | ||
|
||
return restart, nil | ||
func (bc BazelCommand) GetIgnoreStdout() bool { | ||
return bc.IgnoreStdout | ||
} | ||
|
||
func (bc *BazelCommand) Start(ctx context.Context, dir string, parentEnv map[string]string) error { | ||
std.Out.WriteLine(output.Styledf(output.StylePending, "Running %s...", bc.Name)) | ||
func (bc BazelCommand) GetIgnoreStderr() bool { | ||
return bc.IgnoreStderr | ||
} | ||
|
||
// Run the binary for the first time. | ||
cancel, err := bc.start(ctx, dir, parentEnv) | ||
if err != nil { | ||
return errors.Wrapf(err, "failed to start Bazel command %q", bc.Name) | ||
} | ||
func (bc BazelCommand) GetPreamble() string { | ||
return bc.Preamble | ||
} | ||
|
||
// Restart when the binary change. | ||
wantRestart, err := bc.watch(ctx) | ||
func (bc BazelCommand) GetBinaryLocation() (string, error) { | ||
baseOutput, err := outputPath() | ||
if err != nil { | ||
return err | ||
return "", err | ||
} | ||
// Trim "bazel-out" because the next bazel query will include it. | ||
outputPath := strings.TrimSuffix(strings.TrimSpace(string(baseOutput)), "bazel-out") | ||
|
||
// Wait forever until we're asked to stop or that restarting returns an error. | ||
for { | ||
select { | ||
case <-ctx.Done(): | ||
return ctx.Err() | ||
case <-wantRestart: | ||
std.Out.WriteLine(output.Styledf(output.StylePending, "Restarting %s...", bc.Name)) | ||
cancel() | ||
cancel, err = bc.start(ctx, dir, parentEnv) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
} | ||
|
||
func (bc *BazelCommand) start(ctx context.Context, dir string, parentEnv map[string]string) (func(), error) { | ||
binLocation, err := bc.BinLocation() | ||
// Get the binary from the specific target. | ||
cmd := exec.Command("bazel", "cquery", bc.Target, "--output=files") | ||
baseOutput, err = cmd.Output() | ||
if err != nil { | ||
return nil, err | ||
return "", err | ||
} | ||
binPath := strings.TrimSpace(string(baseOutput)) | ||
|
||
sc := &startedCmd{ | ||
stdoutBuf: &prefixSuffixSaver{N: 32 << 10}, | ||
stderrBuf: &prefixSuffixSaver{N: 32 << 10}, | ||
} | ||
return fmt.Sprintf("%s%s", outputPath, binPath), nil | ||
} | ||
|
||
commandCtx, cancel := context.WithCancel(ctx) | ||
sc.cancel = cancel | ||
sc.Cmd = exec.CommandContext(commandCtx, "bash", "-c", fmt.Sprintf("%s\n%s", bc.PreCmd, binLocation)) | ||
sc.Cmd.Dir = dir | ||
func (bc BazelCommand) GetExternalSecrets() map[string]secrets.ExternalSecret { | ||
return bc.ExternalSecrets | ||
} | ||
|
||
secretsEnv, err := getSecrets(ctx, bc.Name, bc.ExternalSecrets) | ||
func (bc BazelCommand) watchPaths() ([]string, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: shouldn't this be |
||
// Grab the location of the binary in bazel-out. | ||
binLocation, err := bc.GetBinaryLocation() | ||
if err != nil { | ||
std.Out.WriteLine(output.Styledf(output.StyleWarning, "[%s] %s %s", | ||
bc.Name, output.EmojiFailure, err.Error())) | ||
return nil, err | ||
} | ||
return []string{binLocation}, nil | ||
|
||
sc.Cmd.Env = makeEnv(parentEnv, secretsEnv, bc.Env) | ||
} | ||
|
||
var stdoutWriter, stderrWriter io.Writer | ||
logger := newCmdLogger(commandCtx, bc.Name, std.Out.Output) | ||
if bc.IgnoreStdout { | ||
std.Out.WriteLine(output.Styledf(output.StyleSuggestion, "Ignoring stdout of %s", bc.Name)) | ||
stdoutWriter = sc.stdoutBuf | ||
} else { | ||
stdoutWriter = io.MultiWriter(logger, sc.stdoutBuf) | ||
} | ||
if bc.IgnoreStderr { | ||
std.Out.WriteLine(output.Styledf(output.StyleSuggestion, "Ignoring stderr of %s", bc.Name)) | ||
stderrWriter = sc.stderrBuf | ||
func (bc BazelCommand) StartWatch(ctx context.Context) (<-chan struct{}, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would love to but but both Command and BazelCommand use Watch for a local field. |
||
if watchPaths, err := bc.watchPaths(); err != nil { | ||
return nil, err | ||
} else { | ||
stderrWriter = io.MultiWriter(logger, sc.stderrBuf) | ||
return WatchPaths(ctx, watchPaths) | ||
} | ||
} | ||
|
||
eg, err := process.PipeOutputUnbuffered(ctx, sc.Cmd, stdoutWriter, stderrWriter) | ||
func (bc BazelCommand) GetExec(ctx context.Context) (*exec.Cmd, error) { | ||
binLocation, err := bc.GetBinaryLocation() | ||
if err != nil { | ||
return nil, err | ||
} | ||
sc.outEg = eg | ||
println("Binary location: " + binLocation + "\n") | ||
|
||
if err := sc.Start(); err != nil { | ||
return nil, err | ||
} | ||
return exec.CommandContext(ctx, "bash", "-c", fmt.Sprintf("%s\n%s", bc.PreCmd, binLocation)), nil | ||
} | ||
|
||
return cancel, nil | ||
func outputPath() ([]byte, error) { | ||
// Get the output directory from Bazel, which varies depending on which OS | ||
// we're running against. | ||
cmd := exec.Command("bazel", "info", "output_path") | ||
return cmd.Output() | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Contains patterns of bazel output and the command to run to try to auto fix it. iBazel will use this to to try to auto-resolve build problems.