Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre & Post commands #461

Merged
merged 10 commits into from
Sep 21, 2023
4 changes: 4 additions & 0 deletions air_example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ root = "."
tmp_dir = "tmp"

[build]
# Array of commands to run before each build
pre_cmd = ["echo 'hello air' > pre_cmd.txt"]
# Just plain old shell command. You could use `make` as well.
cmd = "go build -o ./tmp/main ."
# Array of commands to run after ^C
post_cmd = ["echo 'hello air' > post_cmd.txt"]
# Binary file yields from `cmd`.
bin = "tmp/main"
# Customize binary, can setup environment variables when run your app.
Expand Down
2 changes: 2 additions & 0 deletions runner/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ type Config struct {
}

type cfgBuild struct {
PreCmd []string `toml:"pre_cmd"`
Cmd string `toml:"cmd"`
PostCmd []string `toml:"post_cmd"`
Bin string `toml:"bin"`
FullBin string `toml:"full_bin"`
ArgsBin []string `toml:"args_bin"`
Expand Down
1 change: 1 addition & 0 deletions runner/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const (

func getWindowsConfig() Config {
build := cfgBuild{
PreCmd: []string{"echo Hello Air"},
Cmd: "go build -o ./tmp/main .",
Bin: "./tmp/main",
Log: "build-errors.log",
Expand Down
53 changes: 48 additions & 5 deletions runner/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,13 @@ func (e *Engine) buildRun() {
default:
}
var err error
if err = e.runPreCmd(); err != nil {
e.canExit <- true
e.runnerLog("failed to execute pre_cmd: %s", err.Error())
if e.config.Build.StopOnError {
return
}
}
if err = e.building(); err != nil {
e.canExit <- true
e.buildLog("failed to build, error: %s", err.Error())
Expand Down Expand Up @@ -410,10 +417,9 @@ func (e *Engine) flushEvents() {
}
}

func (e *Engine) building() error {
var err error
e.buildLog("building...")
cmd, stdout, stderr, err := e.startCmd(e.config.Build.Cmd)
// utility to execute commands, such as cmd & pre_cmd
func (e *Engine) runCommand(command string) error {
cmd, stdout, stderr, err := e.startCmd(command)
if err != nil {
return err
}
Expand All @@ -423,14 +429,48 @@ func (e *Engine) building() error {
}()
_, _ = io.Copy(os.Stdout, stdout)
_, _ = io.Copy(os.Stderr, stderr)
// wait for building
// wait for command to finish
err = cmd.Wait()
if err != nil {
return err
}
return nil
}

// run cmd option in .air.toml
func (e *Engine) building() error {
e.buildLog("building...")
err := e.runCommand(e.config.Build.Cmd)
if err != nil {
return err
}
return nil
}

// run pre_cmd option in .air.toml
func (e *Engine) runPreCmd() error {
for _, command := range e.config.Build.PreCmd {
e.runnerLog("> %s", command)
err := e.runCommand(command)
if err != nil {
return err
}
}
return nil
}

// run post_cmd option in .air.toml
func (e *Engine) runPostCmd() error {
for _, command := range e.config.Build.PostCmd {
e.runnerLog("> %s", command)
err := e.runCommand(command)
if err != nil {
return err
}
}
return nil
}

func (e *Engine) runBin() error {
// control killFunc should be kill or not
killCh := make(chan struct{})
Expand Down Expand Up @@ -557,5 +597,8 @@ func (e *Engine) cleanup() {

// Stop the air
func (e *Engine) Stop() {
if err := e.runPostCmd(); err != nil {
e.runnerLog("failed to execute post_cmd, error: %s", err.Error())
}
close(e.exitCh)
}
72 changes: 72 additions & 0 deletions runner/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,78 @@ func TestRerunWhenFileChanged(t *testing.T) {
}
}

func TestRunCommand(t *testing.T) {
// generate a random port
port, f := GetPort()
f()
t.Logf("port: %d", port)
tmpDir := initTestEnv(t, port)
// change dir to tmpDir
chdir(t, tmpDir)
engine, err := NewEngine("", true)
if err != nil {
t.Fatalf("Should not be fail: %s.", err)
}
err = engine.runCommand("touch test.txt")
if err != nil {
t.Fatalf("Should not be fail: %s.", err)
}
if _, err := os.Stat("./test.txt"); err != nil {
if os.IsNotExist(err) {
t.Fatalf("Should not be fail: %s.", err)
}
}
}

func TestRunPreCmd(t *testing.T) {
// generate a random port
port, f := GetPort()
f()
t.Logf("port: %d", port)
tmpDir := initTestEnv(t, port)
// change dir to tmpDir
chdir(t, tmpDir)
engine, err := NewEngine("", true)
if err != nil {
t.Fatalf("Should not be fail: %s.", err)
}
err = engine.runPreCmd()
xiantang marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

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

You should use a real command for integration testing, such as writing a file to the test folder and then checking if the file exists after execution is complete

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think the current unit tests can test anything

if err != nil {
t.Fatalf("Should not be fail: %s.", err)
}
if _, err := os.Stat("./pre_cmd.txt"); err != nil {
if os.IsNotExist(err) {
t.Fatalf("Should not be fail: %s.", err)
}
}
}

func TestRunPostCmd(t *testing.T) {
// generate a random port
port, f := GetPort()
f()
t.Logf("port: %d", port)
tmpDir := initTestEnv(t, port)
// change dir to tmpDir
chdir(t, tmpDir)

engine, err := NewEngine("", true)
if err != nil {
t.Fatalf("Should not be fail: %s.", err)
}

err = engine.runPostCmd()
if err != nil {
t.Fatalf("Should not be fail: %s.", err)
}

if _, err := os.Stat("./post_cmd.txt"); err != nil {
if os.IsNotExist(err) {
t.Fatalf("Should not be fail: %s.", err)
}
}
}

func TestRunBin(t *testing.T) {
engine, err := NewEngine("", true)
if err != nil {
Expand Down