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)