Skip to content

Commit

Permalink
Pre & Post commands (#461)
Browse files Browse the repository at this point in the history
* feat: pre_cmd before each build

* test: pre_cmd option & runPreCmd func

* refactor: cmd&pre_cmd run logic into runCommand

* test: runCommand func

* docs: update example toml

* refactor: use fs to ensure pre_cmd is working

* feat: run post_cmd after ^C

* test: post_cmd

* docs: update example toml

* style: use single quotes instead of escape char
  • Loading branch information
kareemmahlees authored Sep 21, 2023
1 parent af962ce commit c29522a
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 5 deletions.
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()
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

0 comments on commit c29522a

Please sign in to comment.