Skip to content

Commit

Permalink
Dockerize and add ci
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeljguarino committed Oct 13, 2019
1 parent 733b2fe commit 2a27824
Show file tree
Hide file tree
Showing 13 changed files with 262 additions and 7 deletions.
53 changes: 53 additions & 0 deletions .semaphore/semaphore.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
version: v1.0
name: Chartmart
agent:
machine:
type: e1-standard-2
os_image: ubuntu1804
blocks:
- name: test
dependencies: []
task:
secrets:
- name: gcp-test
jobs:
- name: Test
commands:
- checkout
- echo $GOOGLE_APPLICATION_CREDENTIALS > key.json
- export GOOGLE_APPLICATION_CREDENTIALS="$(pwd)/key.json"
- sem-version elixir 1.9.0
- make testup
- mix local.hex --force
- mix local.rebar --force

- cache restore mix-deps-$SEMAPHORE_GIT_BRANCH-$(checksum mix.lock),mix-deps-$SEMAPHORE_GIT_BRANCH,mix-deps-master
- cache restore mix-build-1-$SEMAPHORE_GIT_BRANCH-$(checksum mix.lock),mix-build-1-$SEMAPHORE_GIT_BRANCH,mix-build-1-master

- mix deps.get
- mix test

- cache store mix-deps-$SEMAPHORE_GIT_BRANCH-$(checksum mix.lock) deps
- cache store mix-build-$SEMAPHORE_GIT_BRANCH-$(checksum mix.lock) _build
- cache store mix-deps-$SEMAPHORE_GIT_BRANCH deps
- cache store mix-build-$SEMAPHORE_GIT_BRANCH _build
- name: build
dependencies: ['test']
skip:
when: "branch != 'master'"
task:
secrets:
- name: GCP
- name: gcp-test
prologue:
commands:
# Authenticate using the file injected from the secret
- gcloud auth activate-service-account --key-file=.secrets/gcp.json
# Don't forget -q to silence confirmation prompts
- gcloud auth configure-docker -q
- checkout
jobs:
- name: "Build chartmart"
commands:
- make build APP_NAME=chartmart
- make push APP_NAME=chartmart
82 changes: 82 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# The version of Alpine to use for the final image
# This should match the version of Alpine that the `elixir:1.7.2-alpine` image uses
ARG ALPINE_VERSION=3.8

FROM elixir:1.9-alpine AS builder

# The following are build arguments used to change variable parts of the image.
# The name of your application/release (required)
ARG APP_NAME
# The version of the application we are building (required)
ARG APP_VSN
# The environment to build with
ARG MIX_ENV=prod
# Set this to true if this release is not a Phoenix app
ARG SKIP_PHOENIX=true
# If you are using an umbrella project, you can change this
# argument to the directory the Phoenix app is in so that the assets
# can be built
ARG PHOENIX_SUBDIR=.

ENV SKIP_PHOENIX=${SKIP_PHOENIX} \
APP_NAME=${APP_NAME} \
APP_VSN=${APP_VSN} \
MIX_ENV=${MIX_ENV}

# By convention, /opt is typically used for applications
WORKDIR /opt/app

# This step installs all the build tools we'll need
RUN apk update && \
apk upgrade --no-cache && \
apk add --no-cache \
nodejs \
yarn \
git \
build-base && \
mix local.rebar --force && \
mix local.hex --force

# This copies our app source code into the build container
COPY . .

RUN mix do deps.get, compile

# This step builds assets for the Phoenix app (if there is one)
# If you aren't building a Phoenix app, pass `--build-arg SKIP_PHOENIX=true`
# This is mostly here for demonstration purposes
RUN if [ ! "$SKIP_PHOENIX" = "true" ]; then \
cd ${PHOENIX_SUBDIR}/assets && \
yarn install && \
yarn deploy && \
cd - && \
mix phx.digest; \
fi

RUN \
mkdir -p /opt/built && \
mix distillery.release --name ${APP_NAME} && \
cp _build/${MIX_ENV}/rel/${APP_NAME}/releases/${APP_VSN}/${APP_NAME}.tar.gz /opt/built && \
cd /opt/built && \
tar -xzf ${APP_NAME}.tar.gz && \
rm ${APP_NAME}.tar.gz

# From this line onwards, we're in a new image, which will be the image used in production
FROM erlang:22-alpine

# The name of your application/release (required)
ARG APP_NAME

RUN apk update && \
apk add --no-cache \
bash \
openssl-dev ca-certificates

ENV REPLACE_OS_VARS=true \
APP_NAME=${APP_NAME}

WORKDIR /opt/app

COPY --from=builder /opt/built .

CMD trap 'exit' INT; /opt/app/bin/${APP_NAME} foreground
28 changes: 28 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.PHONY: help

GCP_PROJECT ?= piazza-247002
APP_NAME ?= chartmart
APP_VSN ?= `cat VERSION`
BUILD ?= `git rev-parse --short HEAD`

help:
@perl -nle'print $& if m{^[a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

build: ## Build the Docker image
ifeq ($(APP_NAME), www)
cd www && docker build -t $(APP_NAME):`cat ../VERSION` \
-t $(APP_NAME):latest \
-t gcr.io/$(GCP_PROJECT)/$(APP_NAME):`cat ../VERSION` .
else
docker build --build-arg APP_NAME=$(APP_NAME) \
--build-arg APP_VSN=$(APP_VSN) \
-t $(APP_NAME):$(APP_VSN) \
-t $(APP_NAME):latest \
-t gcr.io/$(GCP_PROJECT)/$(APP_NAME):$(APP_VSN) .
endif

push: ## push to gcr
docker push gcr.io/$(GCP_PROJECT)/$(APP_NAME):$(APP_VSN)

testup: ## sets up dependent services for test
docker-compose up -d
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.1.0
13 changes: 6 additions & 7 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
defmodule Chartmart.MixProject do
use Mix.Project

@vsn File.read!("VERSION")

def project do
[
apps_path: "apps",
version: "0.1.0",
version: @vsn,
start_permanent: Mix.env() == :prod,
deps: deps()
]
end

# Dependencies listed here are available only for this
# project and cannot be accessed from applications inside
# the apps folder.
#
# Run "mix help deps" for examples and options.
defp deps do
[]
[
{:distillery, "~> 2.1"}
]
end
end
2 changes: 2 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
%{
"argon2_elixir": {:hex, :argon2_elixir, "2.0.5", "0073a87d755c7e63fc4f9d08b1d1646585b93f144cecde126e15061b24240b20", [:make, :mix], [{:comeonin, "~> 5.1", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
"artificery": {:hex, :artificery, "0.4.2", "3ded6e29e13113af52811c72f414d1e88f711410cac1b619ab3a2666bbd7efd4", [:mix], [], "hexpm"},
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"comeonin": {:hex, :comeonin, "5.1.2", "fbbbbbfcf0f0e9900c0336d16c8d462edf838ba1759577e29cc5fbd7c28a4540", [:mix], [], "hexpm"},
Expand All @@ -8,6 +9,7 @@
"cowlib": {:hex, :cowlib, "2.7.3", "a7ffcd0917e6d50b4d5fb28e9e2085a0ceb3c97dea310505f7460ff5ed764ce9", [:rebar3], [], "hexpm"},
"db_connection": {:hex, :db_connection, "2.1.1", "a51e8a2ee54ef2ae6ec41a668c85787ed40cb8944928c191280fe34c15b76ae5", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
"decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"},
"distillery": {:hex, :distillery, "2.1.1", "f9332afc2eec8a1a2b86f22429e068ef35f84a93ea1718265e740d90dd367814", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm"},
"ecto": {:hex, :ecto, "3.1.7", "fa21d06ef56cdc2fdaa62574e8c3ba34a2751d44ea34c30bc65f0728421043e5", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
"ecto_enum": {:hex, :ecto_enum, "1.3.2", "659f7251b6a201a236db9dceef0f713319f095a23ad1d8718efd7a3d3ef3e21b", [:mix], [{:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm"},
"ecto_sql": {:hex, :ecto_sql, "3.1.6", "1e80e30d16138a729c717f73dcb938590bcdb3a4502f3012414d0cbb261045d8", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.9.1", [hex: :mariaex, repo: "hexpm", optional: true]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14.0 or ~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
Expand Down
3 changes: 3 additions & 0 deletions rel/commands/drop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

release_ctl eval --mfa "Piazza.Ecto.ReleaseTasks.drop/1" --argv -- "$@"
3 changes: 3 additions & 0 deletions rel/commands/migrate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

release_ctl eval --mfa "Piazza.Ecto.ReleaseTasks.seed/1" --argv -- "$@"
47 changes: 47 additions & 0 deletions rel/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
~w(rel plugins *.exs)
|> Path.join()
|> Path.wildcard()
|> Enum.map(&Code.eval_file(&1))

version = File.read!("VERSION")

use Distillery.Releases.Config,
# This sets the default release built by `mix distillery.release`
default_release: :default,
# This sets the default environment used by `mix distillery.release`
default_environment: Mix.env()

environment :dev do
set dev_mode: true
set include_erts: false
set cookie: :"[0u(BUb%Eh955Mg5V>:Mgxqa8NY`de)3ikLXo:iM]pU6HUy9NC}C4T(5A=|Xau8/"
end

environment :prod do
set include_erts: true
set include_src: false
set cookie: :"apMPW^f~jR;8CVeiv`d4(6y]Rv`v_Z;ghL:~3&j!1QM)YRG5_TTpz2q2nGu)9>}l"
set vm_args: "rel/vm.args"
set config_providers: [
{Distillery.Releases.Config.Providers.Elixir, ["${RELEASE_ROOT_DIR}/etc/config.exs"]},
{Distillery.Releases.Config.Providers.Elixir, ["${RELEASE_ROOT_DIR}/etc/app.exs"]}
]
set overlays: [
{:copy, "rel/config/config.exs", "etc/config.exs"},
{:copy, "rel/config/<%= release_name %>.exs", "etc/app.exs"}
]
end

release :chartmart do
set version: version
set applications: [
:runtime_tools,
api: :permanent,
core: :permanent
]
set commands: [
migrate: "rel/commands/migrate.sh",
drop: "rel/commands/drop.sh"
]
end

2 changes: 2 additions & 0 deletions rel/config/chartmart.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Config
import System, only: [get_env: 1]
2 changes: 2 additions & 0 deletions rel/config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Config
import System, only: [get_env: 1]
3 changes: 3 additions & 0 deletions rel/plugins/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.*
!*.exs
!.gitignore
30 changes: 30 additions & 0 deletions rel/vm.args
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## This file provide the arguments provided to the VM at startup
## You can find a full list of flags and their behaviours at
## http://erlang.org/doc/man/erl.html

## Name of the node
-name <%= release_name %>@${POD_IP}

## Cookie for distributed erlang
-setcookie ${ERLANG_COOKIE}

## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive
## (Disabled by default..use with caution!)
##-heart

## Enable kernel poll and a few async threads
##+K true
##+A 5
## For OTP21+, the +A flag is not used anymore,
## +SDio replace it to use dirty schedulers
##+SDio 5

## Increase number of concurrent ports/sockets
##-env ERL_MAX_PORTS 4096

## Tweak GC to run more often
##-env ERL_FULLSWEEP_AFTER 10

# Enable SMP automatically based on availability
# On OTP21+, this is not needed anymore.
-smp auto

0 comments on commit 2a27824

Please sign in to comment.