Skip to content

Commit

Permalink
Merge branch 'master' into #176-querystring
Browse files Browse the repository at this point in the history
  • Loading branch information
PiggySpeed committed May 13, 2018
2 parents 2d215e5 + 025d16f commit 7a8cb36
Show file tree
Hide file tree
Showing 7 changed files with 306 additions and 66 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,5 @@ jobs:
file: inertia.*
go: "1.10"
on:
tags: true
branch: master
repo: ubclaunchpad/inertia
23 changes: 16 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
</p>

<p align="center">
Simple, self-hosted continuous deployment.
Effortless, self-hosted continuous deployment.
</p>

<p align="center">
Expand All @@ -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/).

<p align="center">
<img src="/.static/inertia-init.png" width="45%" />
Expand All @@ -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)

<br>

# :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
Expand Down Expand Up @@ -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.

<br>
72 changes: 41 additions & 31 deletions daemon/inertia/project/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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()

Expand All @@ -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
Expand All @@ -94,18 +98,18 @@ 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)
status, err := cli.ContainerWait(ctx, resp.ID)
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))

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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()

Expand All @@ -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
Expand All @@ -247,18 +255,18 @@ 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)
status, err := cli.ContainerWait(ctx, resp.ID)
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))

Expand All @@ -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",
Expand All @@ -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
}

0 comments on commit 7a8cb36

Please sign in to comment.