Deploy and stop scripts
Tags: go, bash
Published: 2021-06-24 17:28:58

Now that we moved our configuration to ENV, we need to `source .env` every time we restart our machine or shell session, which can become a bit tedious. To make our lives easier, we will create bash scripts for starting and stopping server. While at it, we will also separate deploy for `dev` and `prod` environments. Let's start by creating new directory `internal/cli/` and file `cli.go` inside of it with following content:

```go
package cli

import (
  "flag"
  "fmt"
  "os"
)

func usage() {
  fmt.Print(`This program runs RGB backend server.

Usage:

rgb [arguments]

Supported arguments:

`)
  flag.PrintDefaults()
  os.Exit(1)
}

func Parse() {
  flag.Usage = usage
  env := flag.String("env", "dev", `Sets run environment. Possible values are "dev" and "prod"`)
  flag.Parse()
  fmt.Println(*env)
}
```

This code is pretty straightforward. We set usage text that will be printed if app is started with some invalid options or arguments, after that we set default value and description for `-env` option. Finally, parse all CLI flags with `flag.Parse()`. For the moment we don't do anything smart with that value, we are only printing it. But that will change latter when we add logging. For now let's use this by updating `cmd/rgb/main.go` file:

```go
package main

import (
  "rgb/internal/cli"
  "rgb/internal/conf"
  "rgb/internal/server"
)

func main() {
  cli.Parse()
  server.Start(conf.NewConfig())
}
```

Everything is now ready to write bash scripts that will be used for deploying and stopping our app. I will not go into details about bash commands and syntax but i will explain logic behind it. Lets first create another directory inside of our project root and name it simply `scripts/`. Inside of it we will add our first script, `deploy.sh`:

```bash
#! /bin/bash

# default ENV is dev
env=dev

while test $# -gt 0; do
  case "$1" in
    -env)
      shift
      if test $# -gt 0; then
        env=$1
      fi
      # shift
      ;;
    *)
    break
    ;;
  esac
done

cd ../../rgb
source .env
go build -o cmd/rgb/rgb cmd/rgb/main.go
cmd/rgb/rgb -env $env &
```

In the script above we first set `env=dev` which means that dev environment will be selected by default. After that we are reading arguments passed to this script, and if we found `-env` argument, we will set `env` variable to passed value of that argument. This is done inside of while loop. When `env` variable is set, change directory to project root, source ENV variables and then run `go build -o cmd/rgb/rgb cmd/rgb/main.go`. This will create executable file named `cmd/rgb/rgb` which we can run to start our server. When app is built, we are starting server with `cmd/rgb/rgb -env $env &` which passes value of `env` variable as `-env` flag to our server and then starts it in background because of `$` flag.

Let's now create very simple `stop.sh` script, also inside of `scripts/` directory:

```bash
#! /bin/bash

kill $(pidof rgb)
```

This script will find process ID of our `rgb` app and then kills that process.

Before running both scripts, you will need to make them executable:

```bash
chmod +x deploy.sh
chmod +x stop.sh
```

Now we can start and stop our server by simply positioning inside of `scripts/` directory and running:

```bash
./deploy.sh
./stop.sh
```