From af73bbb0f46991c0b8134cc0e5d165f9cc42c7de Mon Sep 17 00:00:00 2001
From: Robert Lin
Date: Fri, 11 May 2018 20:22:54 -0700
Subject: [PATCH 1/6] Return deploy command as callback function post-build
Build functions now implement type Builder, which returns a callback.
This allows running containers to be shut down only after new containers have been built, and allows reduced downtime for apps.
---
daemon/inertia/project/build.go | 72 ++++++++++++++++------------
daemon/inertia/project/build_test.go | 18 +++++--
daemon/inertia/project/deployment.go | 38 +++++++++------
3 files changed, 80 insertions(+), 48 deletions(-)
diff --git a/daemon/inertia/project/build.go b/daemon/inertia/project/build.go
index 5a74e02e..c235a4a6 100644
--- a/daemon/inertia/project/build.go
+++ b/daemon/inertia/project/build.go
@@ -28,6 +28,10 @@ const (
BuildStageName = "build"
)
+// Builder builds projects and returns a callback that can be used to deploy the project.
+// No relation to Bob the Builder, though a Bob did write this.
+type Builder func(*Deployment, *docker.Client, io.Writer) (func() error, error)
+
// getTrueDirectory converts given filepath to host-based filepath
// if applicable - Docker commands are sent to the mounted Docker
// socket and hence are executed on the host, using the host's filepaths,
@@ -51,7 +55,7 @@ func getTrueDirectory(path string) string {
// separate from the daemon and the user's project, and is the
// second container to require access to the docker socket.
// See https://cloud.google.com/community/tutorials/docker-compose-on-container-optimized-os
-func dockerCompose(d *Deployment, cli *docker.Client, out io.Writer) error {
+func dockerCompose(d *Deployment, cli *docker.Client, out io.Writer) (func() error, error) {
fmt.Fprintln(out, "Setting up docker-compose...")
ctx := context.Background()
@@ -73,19 +77,19 @@ func dockerCompose(d *Deployment, cli *docker.Client, out io.Writer) error {
}, nil, BuildStageName,
)
if err != nil {
- return err
+ return nil, err
}
if len(resp.Warnings) > 0 {
fmt.Fprintln(out, "Warnings encountered on docker-compose build.")
warnings := strings.Join(resp.Warnings, "\n")
- return errors.New(warnings)
+ return nil, errors.New(warnings)
}
// Start container to build project
fmt.Fprintln(out, "Building project...")
err = cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
if err != nil {
- return err
+ return nil, err
}
// Attach logs and report build progress until container exits
@@ -94,7 +98,7 @@ func dockerCompose(d *Deployment, cli *docker.Client, out io.Writer) error {
NoTimestamps: true,
})
if err != nil {
- return err
+ return nil, err
}
stop := make(chan struct{})
go common.FlushRoutine(out, reader, stop)
@@ -102,10 +106,10 @@ func dockerCompose(d *Deployment, cli *docker.Client, out io.Writer) error {
close(stop)
reader.Close()
if err != nil {
- return err
+ return nil, err
}
if status != 0 {
- return errors.New("Build exited with non-zero status: " + strconv.FormatInt(status, 10))
+ return nil, errors.New("Build exited with non-zero status: " + strconv.FormatInt(status, 10))
}
fmt.Fprintln(out, "Build exited with status "+strconv.FormatInt(status, 10))
@@ -135,25 +139,27 @@ func dockerCompose(d *Deployment, cli *docker.Client, out io.Writer) error {
}, nil, "docker-compose",
)
if err != nil {
- return err
+ return nil, err
}
if len(resp.Warnings) > 0 {
warnings := strings.Join(resp.Warnings, "\n")
- return errors.New(warnings)
+ return nil, errors.New(warnings)
}
- fmt.Fprintln(out, "Starting up project...")
- return cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
+ return func() error {
+ fmt.Fprintln(out, "Starting up project...")
+ return cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
+ }, nil
}
-// dockerBuild builds project from Dockerfile and deploys it
-func dockerBuild(d *Deployment, cli *docker.Client, out io.Writer) error {
+// dockerBuild builds project from Dockerfile, and returns a callback function to deploy it
+func dockerBuild(d *Deployment, cli *docker.Client, out io.Writer) (func() error, error) {
fmt.Fprintln(out, "Building Dockerfile project...")
ctx := context.Background()
buildCtx := bytes.NewBuffer(nil)
err := common.BuildTar(d.directory, buildCtx)
if err != nil {
- return err
+ return nil, err
}
// @TODO: support configuration
@@ -170,7 +176,7 @@ func dockerBuild(d *Deployment, cli *docker.Client, out io.Writer) error {
},
)
if err != nil {
- return err
+ return nil, err
}
// Output build progress
@@ -192,22 +198,24 @@ func dockerBuild(d *Deployment, cli *docker.Client, out io.Writer) error {
)
if err != nil {
if strings.Contains(err.Error(), "No such image") {
- return errors.New("Image build was unsuccessful")
+ return nil, errors.New("Image build was unsuccessful")
}
- return err
+ return nil, err
}
if len(containerResp.Warnings) > 0 {
warnings := strings.Join(containerResp.Warnings, "\n")
- return errors.New(warnings)
+ return nil, errors.New(warnings)
}
- fmt.Fprintln(out, "Starting up project in container "+d.project+"...")
- return cli.ContainerStart(ctx, containerResp.ID, types.ContainerStartOptions{})
+ return func() error {
+ fmt.Fprintln(out, "Starting up project in container "+d.project+"...")
+ return cli.ContainerStart(ctx, containerResp.ID, types.ContainerStartOptions{})
+ }, nil
}
// herokuishBuild uses the Herokuish tool to use Heroku's official buidpacks
// to build the user project.
-func herokuishBuild(d *Deployment, cli *docker.Client, out io.Writer) error {
+func herokuishBuild(d *Deployment, cli *docker.Client, out io.Writer) (func() error, error) {
fmt.Fprintln(out, "Setting up herokuish...")
ctx := context.Background()
@@ -226,19 +234,19 @@ func herokuishBuild(d *Deployment, cli *docker.Client, out io.Writer) error {
}, nil, BuildStageName,
)
if err != nil {
- return err
+ return nil, err
}
if len(resp.Warnings) > 0 {
fmt.Fprintln(out, "Warnings encountered on herokuish setup.")
warnings := strings.Join(resp.Warnings, "\n")
- return errors.New(warnings)
+ return nil, errors.New(warnings)
}
// Start the herokuish container to build project
fmt.Fprintln(out, "Building project...")
err = cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
if err != nil {
- return err
+ return nil, err
}
// Attach logs and report build progress until container exits
@@ -247,7 +255,7 @@ func herokuishBuild(d *Deployment, cli *docker.Client, out io.Writer) error {
NoTimestamps: true,
})
if err != nil {
- return err
+ return nil, err
}
stop := make(chan struct{})
go common.FlushRoutine(out, reader, stop)
@@ -255,10 +263,10 @@ func herokuishBuild(d *Deployment, cli *docker.Client, out io.Writer) error {
close(stop)
reader.Close()
if err != nil {
- return err
+ return nil, err
}
if status != 0 {
- return errors.New("Build exited with non-zero status: " + strconv.FormatInt(status, 10))
+ return nil, errors.New("Build exited with non-zero status: " + strconv.FormatInt(status, 10))
}
fmt.Fprintln(out, "Build exited with status "+strconv.FormatInt(status, 10))
@@ -269,7 +277,7 @@ func herokuishBuild(d *Deployment, cli *docker.Client, out io.Writer) error {
Reference: imgName,
})
if err != nil {
- return err
+ return nil, err
}
resp, err = cli.ContainerCreate(ctx, &container.Config{
Image: imgName + ":latest",
@@ -278,14 +286,16 @@ func herokuishBuild(d *Deployment, cli *docker.Client, out io.Writer) error {
Cmd: []string{"/start", "web"},
}, nil, nil, d.project)
if err != nil {
- return err
+ return nil, err
}
if len(resp.Warnings) > 0 {
fmt.Fprintln(out, "Warnings encountered on herokuish startup.")
warnings := strings.Join(resp.Warnings, "\n")
- return errors.New(warnings)
+ return nil, errors.New(warnings)
}
fmt.Fprintln(out, "Starting up project in container "+d.project+"...")
- return cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
+ return func() error {
+ return cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
+ }, nil
}
diff --git a/daemon/inertia/project/build_test.go b/daemon/inertia/project/build_test.go
index 6bc3602b..088254f6 100644
--- a/daemon/inertia/project/build_test.go
+++ b/daemon/inertia/project/build_test.go
@@ -60,7 +60,11 @@ func TestDockerComposeIntegration(t *testing.T) {
}
// Execute build
- err = dockerCompose(d, cli, os.Stdout)
+ deploy, err := dockerCompose(d, cli, os.Stdout)
+ assert.Nil(t, err)
+
+ // Execute deploy
+ err = deploy()
assert.Nil(t, err)
// Arbitrary wait for containers to start
@@ -128,7 +132,11 @@ func TestDockerBuildIntegration(t *testing.T) {
}
// Execute build
- err = dockerBuild(d, cli, os.Stdout)
+ deploy, err := dockerBuild(d, cli, os.Stdout)
+ assert.Nil(t, err)
+
+ // Execute deploy
+ err = deploy()
assert.Nil(t, err)
// Arbitrary wait for containers to start
@@ -174,7 +182,11 @@ func TestHerokuishBuildIntegration(t *testing.T) {
}
// Execute build
- err = herokuishBuild(d, cli, os.Stdout)
+ deploy, err := herokuishBuild(d, cli, os.Stdout)
+ assert.Nil(t, err)
+
+ // Execute deploy
+ err = deploy()
assert.Nil(t, err)
// Arbitrary wait for containers to start
diff --git a/daemon/inertia/project/deployment.go b/daemon/inertia/project/deployment.go
index 37827267..d698f85a 100644
--- a/daemon/inertia/project/deployment.go
+++ b/daemon/inertia/project/deployment.go
@@ -35,6 +35,8 @@ type Deployment struct {
branch string
buildType string
+ builders map[string]Builder
+
repo *git.Repository
auth ssh.AuthMethod
mux sync.Mutex
@@ -72,8 +74,13 @@ func NewDeployment(cfg DeploymentConfig, out io.Writer) (*Deployment, error) {
project: cfg.ProjectName,
branch: cfg.Branch,
buildType: cfg.BuildType,
- auth: authMethod,
- repo: repo,
+ builders: map[string]Builder{
+ "herokuish": herokuishBuild,
+ "dockerfile": dockerBuild,
+ "docker-compose": dockerCompose,
+ },
+ auth: authMethod,
+ repo: repo,
}, nil
}
@@ -110,25 +117,28 @@ func (d *Deployment) Deploy(cli *docker.Client, out io.Writer, opts DeployOption
}
}
+ // Use the appropriate build method
+ builder, found := d.builders[strings.ToLower(d.buildType)]
+ if !found {
+ // @todo: attempt a guess at project type instead
+ fmt.Println(out, "Unknown project type "+d.buildType)
+ fmt.Println(out, "Defaulting to docker-compose build")
+ builder = dockerCompose
+ }
+
// Kill active project containers if there are any
err := stopActiveContainers(cli, out)
if err != nil {
return err
}
- // Use the appropriate build method
- switch d.buildType {
- case "herokuish":
- return herokuishBuild(d, cli, out)
- case "dockerfile":
- return dockerBuild(d, cli, out)
- case "docker-compose":
- return dockerCompose(d, cli, out)
- default:
- fmt.Println(out, "Unknown project type "+d.buildType)
- fmt.Println(out, "Defaulting to docker-compose build")
- return dockerCompose(d, cli, out)
+ // Deploy project
+ deploy, err := builder(d, cli, out)
+ if err != nil {
+ return err
}
+
+ return deploy()
}
// Down shuts down the deployment
From 271a2f57bba867423d71145026b5cdf922963fe0 Mon Sep 17 00:00:00 2001
From: Robert Lin
Date: Fri, 11 May 2018 21:30:19 -0700
Subject: [PATCH 2/6] Add deployment tests
---
daemon/inertia/project/deployment.go | 7 ++-
daemon/inertia/project/deployment_test.go | 76 +++++++++++++++++++++++
daemon/inertia/project/docker.go | 2 +
3 files changed, 82 insertions(+), 3 deletions(-)
diff --git a/daemon/inertia/project/deployment.go b/daemon/inertia/project/deployment.go
index d698f85a..ea2e8ed0 100644
--- a/daemon/inertia/project/deployment.go
+++ b/daemon/inertia/project/deployment.go
@@ -36,6 +36,7 @@ type Deployment struct {
buildType string
builders map[string]Builder
+ containerStopper
repo *git.Repository
auth ssh.AuthMethod
@@ -127,7 +128,7 @@ func (d *Deployment) Deploy(cli *docker.Client, out io.Writer, opts DeployOption
}
// Kill active project containers if there are any
- err := stopActiveContainers(cli, out)
+ err := d.containerStopper(cli, out)
if err != nil {
return err
}
@@ -151,13 +152,13 @@ func (d *Deployment) Down(cli *docker.Client, out io.Writer) error {
// active
_, err := getActiveContainers(cli)
if err != nil {
- killErr := stopActiveContainers(cli, out)
+ killErr := d.containerStopper(cli, out)
if killErr != nil {
println(err)
}
return err
}
- return stopActiveContainers(cli, out)
+ return d.containerStopper(cli, out)
}
// Destroy shuts down the deployment and removes the repository
diff --git a/daemon/inertia/project/deployment_test.go b/daemon/inertia/project/deployment_test.go
index dddb235f..b70ea088 100644
--- a/daemon/inertia/project/deployment_test.go
+++ b/daemon/inertia/project/deployment_test.go
@@ -1,10 +1,14 @@
package project
import (
+ "io"
+ "os"
"testing"
"github.com/stretchr/testify/assert"
git "gopkg.in/src-d/go-git.v4"
+
+ docker "github.com/docker/docker/client"
)
func TestSetConfig(t *testing.T) {
@@ -20,6 +24,78 @@ func TestSetConfig(t *testing.T) {
assert.Equal(t, "best", deployment.buildType)
}
+func TestDeploySkipUpdate(t *testing.T) {
+ buildCalled := false
+ stopCalled := false
+ d := Deployment{
+ directory: "./test/",
+ buildType: "test",
+ builders: map[string]Builder{
+ "test": func(*Deployment, *docker.Client, io.Writer) (func() error, error) {
+ return func() error {
+ buildCalled = true
+ return nil
+ }, nil
+ },
+ },
+ containerStopper: func(*docker.Client, io.Writer) error {
+ stopCalled = true
+ return nil
+ },
+ }
+
+ cli, err := docker.NewEnvClient()
+ assert.Nil(t, err)
+ defer cli.Close()
+
+ err = d.Deploy(cli, os.Stdout, DeployOptions{SkipUpdate: true})
+ assert.Nil(t, err)
+ assert.True(t, buildCalled)
+ assert.True(t, stopCalled)
+}
+
+func TestDown(t *testing.T) {
+ called := false
+ d := Deployment{
+ directory: "./test/",
+ buildType: "test",
+ containerStopper: func(*docker.Client, io.Writer) error {
+ called = true
+ return nil
+ },
+ }
+
+ cli, err := docker.NewEnvClient()
+ assert.Nil(t, err)
+ defer cli.Close()
+
+ err = d.Down(cli, os.Stdout)
+ if err != ErrNoContainers {
+ assert.Nil(t, err)
+ }
+
+ assert.True(t, called)
+}
+
+func TestGetStatus(t *testing.T) {
+ // Traverse back down to root directory of repository
+ repo, err := git.PlainOpen("../../../")
+ assert.Nil(t, err)
+
+ cli, err := docker.NewEnvClient()
+ assert.Nil(t, err)
+ defer cli.Close()
+
+ deployment := &Deployment{
+ repo: repo,
+ buildType: "test",
+ }
+ status, err := deployment.GetStatus(cli)
+ assert.Nil(t, err)
+ assert.False(t, status.BuildContainerActive)
+ assert.Equal(t, "test", status.BuildType)
+}
+
func TestGetBranch(t *testing.T) {
deployment := &Deployment{branch: "master"}
assert.Equal(t, "master", deployment.GetBranch())
diff --git a/daemon/inertia/project/docker.go b/daemon/inertia/project/docker.go
index bef7a742..be3f847e 100644
--- a/daemon/inertia/project/docker.go
+++ b/daemon/inertia/project/docker.go
@@ -58,6 +58,8 @@ func getActiveContainers(cli *docker.Client) ([]types.Container, error) {
return containers, nil
}
+type containerStopper func(*docker.Client, io.Writer) error
+
// stopActiveContainers kills all active project containers (ie not including daemon)
func stopActiveContainers(cli *docker.Client, out io.Writer) error {
fmt.Fprintln(out, "Shutting down active containers...")
From 333d6ad135e536e9c2d9546a50aa1c36906ec3e0 Mon Sep 17 00:00:00 2001
From: Robert Lin
Date: Fri, 11 May 2018 20:57:20 -0700
Subject: [PATCH 3/6] Add Windows installation instructions
---
README.md | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 2e97dc77..5ac4bf35 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
- Simple, self-hosted continuous deployment.
+ Effortless, self-hosted continuous deployment.
@@ -29,7 +29,7 @@
----------------
-Inertia is a simple cross-platform command line application that enables effortless setup and management of continuous, automated deployment on any virtual private server. It is built and maintained with :heart: by [UBC Launch Pad](https://www.ubclaunchpad.com/).
+Inertia is a simple cross-platform command line application that enables effortless setup and management of continuous, automated deployment all sorts of projects on any virtual private server. It is built and maintained with :heart: by [UBC Launch Pad](https://www.ubclaunchpad.com/).
@@ -49,24 +49,33 @@ Inertia is a simple cross-platform command line application that enables effortl
----------------
### Contents
-- **[Getting Started](#package-getting-started)**
+- [Getting Started](#package-getting-started)
- [Setup](#setup)
- [Continuous Deployment](#continuous-deployment)
- [Deployment Management](#deployment-management)
- [Release Streams](#release-streams)
-- **[Motivation and Design](#bulb-motivation-and-design)**
-- **[Contributing](#books-contributing)**
+- [Motivation and Design](#bulb-motivation-and-design)
+- [Contributing](#books-contributing)
# :package: Getting Started
-All you need to get started is a [compatible project](https://github.com/ubclaunchpad/inertia/wiki/Project-Compatibility), the Inertia CLI, and access to a virtual private server. The CLI can be installed using [Homebrew](https://brew.sh):
+All you need to get started is a [compatible project](https://github.com/ubclaunchpad/inertia/wiki/Project-Compatibility), the Inertia CLI, and access to a virtual private server.
+
+**MacOS** - the CLI can be installed using [Homebrew](https://brew.sh):
```bash
$> brew install ubclaunchpad/tap/inertia
```
+**Windows** - the CLI can be installed using [Scoop](http://scoop.sh):
+
+```bash
+$> scoop bucket add ubclaunchpad https://github.com/ubclaunchpad/scoop-bucket
+$> scoop install inertia
+```
+
For other platforms, you can [download the appropriate binary from the Releases page](https://github.com/ubclaunchpad/inertia/releases).
### Setup
@@ -179,6 +188,6 @@ Inertia is set up serverside by executing a script over SSH that installs Docker
Any contribution (pull requests, feedback, bug reports, ideas, etc.) is welcome!
-Please see our [contribution guide](https://github.com/ubclaunchpad/inertia/blob/master/.github/CONTRIBUTING.md) for contribution guidelines and a detailed guide to help you get started with Inertia's codebase.
+Please see our [contribution guide](https://github.com/ubclaunchpad/inertia/blob/master/.github/CONTRIBUTING.md) for contribution guidelines as well as a detailed guide to help you get started with Inertia's codebase.
From 8d4ad48ec7dee4cb9f6c0ed55b890e9a770ba575 Mon Sep 17 00:00:00 2001
From: Robert Lin
Date: Fri, 11 May 2018 22:27:31 -0700
Subject: [PATCH 4/6] Only build on ubclaunchpad/inertia
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 9552935f..7f4ddfe8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -69,5 +69,5 @@ jobs:
file: inertia.*
go: "1.10"
on:
- tags: true
branch: master
+ repo: ubclaunchpad/inertia
From a7e1b96c7cc95edbfba034c1b04a05da053f26a2 Mon Sep 17 00:00:00 2001
From: Robert Lin
Date: Fri, 11 May 2018 22:31:33 -0700
Subject: [PATCH 5/6] Assign containerStopper on new Deployment
---
daemon/inertia/project/deployment.go | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/daemon/inertia/project/deployment.go b/daemon/inertia/project/deployment.go
index ea2e8ed0..05571cc7 100644
--- a/daemon/inertia/project/deployment.go
+++ b/daemon/inertia/project/deployment.go
@@ -71,15 +71,21 @@ func NewDeployment(cfg DeploymentConfig, out io.Writer) (*Deployment, error) {
}
return &Deployment{
+ // Properties
directory: directory,
project: cfg.ProjectName,
branch: cfg.Branch,
buildType: cfg.BuildType,
+
+ // Functions
builders: map[string]Builder{
"herokuish": herokuishBuild,
"dockerfile": dockerBuild,
"docker-compose": dockerCompose,
},
+ containerStopper: stopActiveContainers,
+
+ // Repository
auth: authMethod,
repo: repo,
}, nil
From 8bae20d51b62228aca17b5b2e3f65c7ac6053942 Mon Sep 17 00:00:00 2001
From: Robert Lin
Date: Fri, 11 May 2018 22:58:49 -0700
Subject: [PATCH 6/6] Tag deployment tests as integration tests, attempt second
builds
Check if building a new container while containers are already up breaks anything
---
daemon/inertia/project/build_test.go | 116 ++++++++++++++++++++--
daemon/inertia/project/deployment_test.go | 18 +++-
2 files changed, 124 insertions(+), 10 deletions(-)
diff --git a/daemon/inertia/project/build_test.go b/daemon/inertia/project/build_test.go
index 088254f6..e3e23f75 100644
--- a/daemon/inertia/project/build_test.go
+++ b/daemon/inertia/project/build_test.go
@@ -2,6 +2,7 @@ package project
import (
"context"
+ "io"
"os"
"path"
"strings"
@@ -14,7 +15,8 @@ import (
"github.com/stretchr/testify/assert"
)
-func cleanupContainers(cli *docker.Client) error {
+// killTestContainers is a helper for tests - it implements project.ContainerStopper
+func killTestContainers(cli *docker.Client, w io.Writer) error {
ctx := context.Background()
containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
if err != nil {
@@ -45,7 +47,7 @@ func TestDockerComposeIntegration(t *testing.T) {
defer cli.Close()
// Set up
- err = cleanupContainers(cli)
+ err = killTestContainers(cli, nil)
assert.Nil(t, err)
testProjectDir := path.Join(
@@ -57,6 +59,13 @@ func TestDockerComposeIntegration(t *testing.T) {
directory: testProjectDir,
project: testProjectName,
buildType: "docker-compose",
+
+ builders: map[string]Builder{
+ "herokuish": herokuishBuild,
+ "dockerfile": dockerBuild,
+ "docker-compose": dockerCompose,
+ },
+ containerStopper: killTestContainers,
}
// Execute build
@@ -105,7 +114,46 @@ func TestDockerComposeIntegration(t *testing.T) {
assert.True(t, foundDC, "docker-compose container should be active")
assert.True(t, foundP, "project container should be active")
- err = cleanupContainers(cli)
+ // Attempt another deploy using Deployment
+ err = d.Deploy(cli, os.Stdout, DeployOptions{SkipUpdate: true})
+ assert.Nil(t, err)
+
+ // Arbitrary wait for containers to start again
+ time.Sleep(5 * time.Second)
+
+ // Check for containers
+ containers, err = cli.ContainerList(
+ context.Background(),
+ types.ContainerListOptions{},
+ )
+ assert.Nil(t, err)
+ foundDC = false
+ foundP = false
+ for _, c := range containers {
+ if strings.Contains(c.Names[0], "docker-compose") {
+ foundDC = true
+ }
+ if strings.Contains(c.Names[0], testProjectName) {
+ foundP = true
+ }
+ }
+
+ // try again if project no up (workaround for Travis)
+ if !foundP {
+ time.Sleep(10 * time.Second)
+ containers, err = cli.ContainerList(
+ context.Background(),
+ types.ContainerListOptions{},
+ )
+ assert.Nil(t, err)
+ for _, c := range containers {
+ if strings.Contains(c.Names[0], testProjectName) {
+ foundP = true
+ }
+ }
+ }
+
+ err = killTestContainers(cli, nil)
assert.Nil(t, err)
}
@@ -117,7 +165,7 @@ func TestDockerBuildIntegration(t *testing.T) {
assert.Nil(t, err)
defer cli.Close()
- err = cleanupContainers(cli)
+ err = killTestContainers(cli, nil)
assert.Nil(t, err)
testProjectDir := path.Join(
@@ -129,6 +177,13 @@ func TestDockerBuildIntegration(t *testing.T) {
directory: testProjectDir,
project: testProjectName,
buildType: "dockerfile",
+
+ builders: map[string]Builder{
+ "herokuish": herokuishBuild,
+ "dockerfile": dockerBuild,
+ "docker-compose": dockerCompose,
+ },
+ containerStopper: killTestContainers,
}
// Execute build
@@ -155,7 +210,27 @@ func TestDockerBuildIntegration(t *testing.T) {
}
assert.True(t, foundP, "project container should be active")
- err = cleanupContainers(cli)
+ // Attempt another deploy using Deployment
+ err = d.Deploy(cli, os.Stdout, DeployOptions{SkipUpdate: true})
+ assert.Nil(t, err)
+
+ // Arbitrary wait for containers to start
+ time.Sleep(5 * time.Second)
+
+ containers, err = cli.ContainerList(
+ context.Background(),
+ types.ContainerListOptions{},
+ )
+ assert.Nil(t, err)
+ foundP = false
+ for _, c := range containers {
+ if strings.Contains(c.Names[0], testProjectName) {
+ foundP = true
+ }
+ }
+ assert.True(t, foundP, "project container should be active")
+
+ err = killTestContainers(cli, nil)
assert.Nil(t, err)
}
@@ -167,7 +242,7 @@ func TestHerokuishBuildIntegration(t *testing.T) {
assert.Nil(t, err)
defer cli.Close()
- err = cleanupContainers(cli)
+ err = killTestContainers(cli, nil)
assert.Nil(t, err)
testProjectDir := path.Join(
@@ -179,6 +254,13 @@ func TestHerokuishBuildIntegration(t *testing.T) {
directory: testProjectDir,
project: testProjectName,
buildType: "herokuish",
+
+ builders: map[string]Builder{
+ "herokuish": herokuishBuild,
+ "dockerfile": dockerBuild,
+ "docker-compose": dockerCompose,
+ },
+ containerStopper: killTestContainers,
}
// Execute build
@@ -205,6 +287,26 @@ func TestHerokuishBuildIntegration(t *testing.T) {
}
assert.True(t, foundP, "project container should be active")
- err = cleanupContainers(cli)
+ // Attempt another deploy using Deployment
+ err = d.Deploy(cli, os.Stdout, DeployOptions{SkipUpdate: true})
+ assert.Nil(t, err)
+
+ // Arbitrary wait for containers to start
+ time.Sleep(5 * time.Second)
+
+ containers, err = cli.ContainerList(
+ context.Background(),
+ types.ContainerListOptions{},
+ )
+ assert.Nil(t, err)
+ foundP = false
+ for _, c := range containers {
+ if strings.Contains(c.Names[0], testProjectName) {
+ foundP = true
+ }
+ }
+ assert.True(t, foundP, "project container should be active")
+
+ err = killTestContainers(cli, nil)
assert.Nil(t, err)
}
diff --git a/daemon/inertia/project/deployment_test.go b/daemon/inertia/project/deployment_test.go
index b70ea088..a787b8bf 100644
--- a/daemon/inertia/project/deployment_test.go
+++ b/daemon/inertia/project/deployment_test.go
@@ -24,7 +24,11 @@ func TestSetConfig(t *testing.T) {
assert.Equal(t, "best", deployment.buildType)
}
-func TestDeploySkipUpdate(t *testing.T) {
+func TestDeployMockSkipUpdateIntegration(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping integration test")
+ }
+
buildCalled := false
stopCalled := false
d := Deployment{
@@ -54,7 +58,11 @@ func TestDeploySkipUpdate(t *testing.T) {
assert.True(t, stopCalled)
}
-func TestDown(t *testing.T) {
+func TestDownIntegration(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping integration test")
+ }
+
called := false
d := Deployment{
directory: "./test/",
@@ -77,7 +85,11 @@ func TestDown(t *testing.T) {
assert.True(t, called)
}
-func TestGetStatus(t *testing.T) {
+func TestGetStatusIntegration(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping integration test")
+ }
+
// Traverse back down to root directory of repository
repo, err := git.PlainOpen("../../../")
assert.Nil(t, err)