Migrate from CircleCI 1.0 to 2.0

Note: deployment jobs are filtered by branch, so deploy_staging won't be
tested until the merge to master and deploy_production won't be tested
until the merge to production.
pull/87/head
Luke Imhoff 7 years ago
parent 66df93faf2
commit f71e542f46
  1. 384
      .circleci/config.yml
  2. 83
      .circleci/elixir-node-ruby/Dockerfile
  3. 20
      .circleci/elixir-node-ruby/README.md
  4. 16
      .circleci/setup-heroku.sh
  5. 2
      .credo.exs
  6. 5
      .tool-versions
  7. 5
      apps/explorer/test/test_helper.exs
  8. 5
      apps/explorer_web/test/test_helper.exs
  9. 78
      circle.yml
  10. 4
      elixir_buildpack.config

@ -0,0 +1,384 @@
version: 2
jobs:
build:
docker:
# Ensure .tool-versions matches
- image: circleci/elixir:1.6.4-node-browsers
environment:
MIX_ENV: test
# match POSTGRES_PASSWORD for postgres image below
PGPASSWORD: postgres
# match POSTGRES_USER for postgres image below
PGUSER: postgres
working_directory: ~/app
steps:
- checkout
- run: mix local.hex --force
- run: mix local.rebar --force
- restore_cache:
keys:
- v2-mix-deps-get-{{ checksum "mix.lock" }}
- v2-mix-deps-get-{{ checksum "mix.exs" }}
- v2-mix-deps-get
- run: mix deps.get
- save_cache:
key: v2-mix-deps-get-{{ checksum "mix.lock" }}
paths: "deps"
- save_cache:
key: mix-deps-get-{{ checksum "mix.exs" }}
paths: "deps"
- save_cache:
key: mix-deps-get
paths: "deps"
- restore_cache:
keys:
- v2-npm-install-{{ .Branch }}-{{ checksum "apps/explorer_web/assets/package-lock.json" }}
- v2-npm-install-{{ .Branch }}
- v2-npm-install
- run:
command: npm install
working_directory: "apps/explorer_web/assets"
- save_cache:
key: v2-npm-install-{{ .Branch }}-{{ checksum "apps/explorer_web/assets/package-lock.json" }}
paths: "apps/explorer_web/assets/node_modules"
- save_cache:
key: v2-npm-install-{{ .Branch }}
paths: "apps/explorer_web/assets/node_modules"
- save_cache:
key: v2-npm-install
paths: "apps/explorer_web/assets/node_modules"
- run:
name: "ELIXIR_VERSION.lock"
command: echo "${ELIXIR_VERSION}" > ELIXIR_VERSION.lock
- run:
name: "OTP_VERSION.lock"
command: echo "${OTP_VERSION}" > OTP_VERSION.lock
- restore_cache:
keys:
- v2-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }}
- v2-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }}
- v2-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}
- run: mix compile
- save_cache:
key: v2-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }}
paths:
- _build
- save_cache:
key: v2-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }}
paths:
- _build
- save_cache:
key: v2-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}
paths:
- _build
- run:
name: Build assets
command: node node_modules/brunch/bin/brunch build
working_directory: "apps/explorer_web/assets"
- persist_to_workspace:
root: .
paths:
- _build
- apps
- config
- deps
- doc
- .credo.exs
- .dialyzer-ignore
- ELIXIR_VERSION.lock
- .formatter.exs
- .sobelow-conf
- Gemfile
- Gemfile.lock
- mix.exs
- mix.lock
- OTP_VERSION.lock
check_formatted:
docker:
# Ensure .tool-versions matches
- image: circleci/elixir:1.6.4
environment:
MIX_ENV: test
working_directory: ~/app
steps:
- attach_workspace:
at: .
- run: mix format --check-formatted
credo:
docker:
# Ensure .tool-versions matches
- image: circleci/elixir:1.6.4
environment:
MIX_ENV: test
working_directory: ~/app
steps:
- attach_workspace:
at: .
- run: mix local.hex --force
- run: mix credo
deploy_production:
docker:
# Ensure .tool-versions matches
- image: circleci/elixir:1.6.4
environment:
MIX_ENV: test
working_directory: ~/app
steps:
- attach_workspace:
at: .
- add_ssh_keys:
fingerprints:
- "c4:fd:a8:f8:48:a8:09:e5:3e:be:30:62:4d:6f:6f:36"
- run:
name: Setup Heroku
command: bash .circleci/setup-heroku.sh
- run:
name: Deploy Production to Heroku
command: bin/deploy poa-explorer-production
deploy_staging:
docker:
# Ensure .tool-versions matches
- image: circleci/elixir:1.6.4
environment:
MIX_ENV: test
working_directory: ~/app
steps:
- attach_workspace:
at: .
- add_ssh_keys:
fingerprints:
- "c4:fd:a8:f8:48:a8:09:e5:3e:be:30:62:4d:6f:6f:36"
- run:
name: Setup Heroku
command: bash .circleci/setup-heroku.sh
- run:
name: Deploy Staging to Heroku
command: bin/deploy poa-explorer-staging
dialyzer:
docker:
# Ensure .tool-versions matches
- image: circleci/elixir:1.6.4
environment:
MIX_ENV: test
working_directory: ~/app
steps:
- attach_workspace:
at: .
- run: mix local.hex --force
- restore_cache:
keys:
- v2-mix-dailyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }}
- v2-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }}
- v2-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}
- run:
name: Unpack PLT cache
command: |
mkdir -p _build/test
cp plts/dialyxir*.plt _build/test/ || true
mkdir -p ~/.mix
cp plts/dialyxir*.plt ~/.mix/ || true
- run: mix dialyzer --plt
- run:
name: Pack PLT cache
command: |
mkdir -p plts
cp _build/test/dialyxir*.plt plts/
cp ~/.mix/dialyxir*.plt plts/
- save_cache:
key: v2-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }}
paths:
- plts
- save_cache:
key: v1-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }}
paths:
- plts
- save_cache:
key: v1-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}
paths:
- plts
- run: mix dialyzer
eslint:
docker:
# Ensure .tool-versions matches
- image: circleci/node:9.10.1
working_directory: ~/app
steps:
- attach_workspace:
at: .
- run:
name: ESLint
command: ./node_modules/.bin/eslint --format=junit --output-file="test/eslint/junit.xml" js/**/*.js
working_directory: apps/explorer_web/assets
- store_test_results:
path: apps/explorer_web/assets/test
license_finder:
docker:
# Ensure .tool-versions matches
- image: poanetwork/elixir:1.6.4-node-ruby
environment:
MIX_ENV: test
working_directory: ~/app
steps:
- attach_workspace:
at: .
- run: mix local.hex --force
- run:
name: Bundle Install
command: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
- run:
name: License Finder Action Items
command: bundle exec license_finder --project-path=. --decisions-file=doc/dependency_decisions.yml
sobelow:
docker:
# Ensure .tool-versions matches
- image: circleci/elixir:1.6.4
environment:
MIX_ENV: test
working_directory: ~/app
steps:
- attach_workspace:
at: .
- run: mix local.hex --force
- run: mix sobelow --config
test:
docker:
# Ensure .tool-versions matches
- image: circleci/elixir:1.6.4-node-browsers
environment:
MIX_ENV: test
# match POSTGRES_PASSWORD for postgres image below
PGPASSWORD: postgres
# match POSTGRES_USER for postgres image below
PGUSER: postgres
- image: circleci/postgres:10.3-alpine
environment:
# Match apps/explorer/config/test.exs config :explorerer, Explorer.Repo, database
POSTGRES_DB: explorer_test
# match PGPASSWORD for elixir image above
POSTGRES_PASSWORD: postgres
# match PGUSER for elixir image above
POSTGRES_USER: postgres
- image: circleci/redis:4.0.9-alpine
working_directory: ~/app
steps:
- attach_workspace:
at: .
- run: mix local.hex --force
- run: mix local.rebar --force
- run:
name: Wait for DB
command: dockerize -wait tcp://localhost:5432 -timeout 1m
- run:
name: Wait for Redis
command: dockerize -wait tcp://localhost:6379 -timeout 1m
- run: mix test
- store_test_results:
path: _build/test/junit
workflows:
version: 2
primary:
jobs:
- build
- check_formatted:
requires:
- build
- credo:
requires:
- build
- deploy_production:
filters:
branches:
only: production
requires:
- check_formatted
- credo
- eslint
- license_finder
- sobelow
- test
- deploy_staging:
filters:
branches:
only: master
requires:
- check_formatted
- credo
- eslint
- license_finder
- sobelow
- test
- dialyzer:
requires:
- build
- eslint:
requires:
- build
- license_finder:
requires:
- build
- sobelow:
requires:
- build
- test:
requires:
- build

@ -0,0 +1,83 @@
# MUST match base image version used in .circleci/config.yml.
# -browser variant is dropped from name because license_finder doesn't need browsers
FROM circleci/elixir:1.6.4-node
USER root
# https://github.com/CircleCI-Public/circleci-dockerfiles/blob/1da7b6007c52a166741b6e15a423e7729408070d/ruby/images/2.5.1-stretch/Dockerfile uses ruby:2.5.1-stretch, so inline ruby:2.5.1-stretch:
# https://github.com/docker-library/ruby/blob/c9644fe5c95cd71913db348baa41240f05d882b3/2.5/stretch/Dockerfile
# skip installing gem documentation
RUN mkdir -p /usr/local/etc \
&& { \
echo 'install: --no-document'; \
echo 'update: --no-document'; \
} >> /usr/local/etc/gemrc
ENV RUBY_MAJOR 2.5
ENV RUBY_VERSION 2.5.1
ENV RUBY_DOWNLOAD_SHA256 886ac5eed41e3b5fc699be837b0087a6a5a3d10f464087560d2d21b3e71b754d
ENV RUBYGEMS_VERSION 2.7.6
ENV BUNDLER_VERSION 1.16.1
# some of ruby's build scripts are written in ruby
# we purge system ruby later to make sure our final image uses what we just built
RUN set -ex \
\
&& buildDeps=' \
bison \
dpkg-dev \
libgdbm-dev \
ruby \
' \
&& apt-get update \
&& apt-get install -y --no-install-recommends $buildDeps \
&& rm -rf /var/lib/apt/lists/* \
\
&& wget -O ruby.tar.xz "https://cache.ruby-lang.org/pub/ruby/${RUBY_MAJOR%-rc}/ruby-$RUBY_VERSION.tar.xz" \
&& echo "$RUBY_DOWNLOAD_SHA256 *ruby.tar.xz" | sha256sum -c - \
\
&& mkdir -p /usr/src/ruby \
&& tar -xJf ruby.tar.xz -C /usr/src/ruby --strip-components=1 \
&& rm ruby.tar.xz \
\
&& cd /usr/src/ruby \
\
# hack in "ENABLE_PATH_CHECK" disabling to suppress:
# warning: Insecure world writable dir
&& { \
echo '#define ENABLE_PATH_CHECK 0'; \
echo; \
cat file.c; \
} > file.c.new \
&& mv file.c.new file.c \
\
&& autoconf \
&& gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
&& ./configure \
--build="$gnuArch" \
--disable-install-doc \
--enable-shared \
&& make -j "$(nproc)" \
&& make install \
\
&& apt-get purge -y --auto-remove $buildDeps \
&& cd / \
&& rm -r /usr/src/ruby \
\
&& gem update --system "$RUBYGEMS_VERSION" \
&& gem install bundler --version "$BUNDLER_VERSION" --force \
&& rm -r /root/.gem/
# install things globally, for great justice
# and don't create ".bundle" in all our apps
ENV GEM_HOME /usr/local/bundle
ENV BUNDLE_PATH="$GEM_HOME" \
BUNDLE_BIN="$GEM_HOME/bin" \
BUNDLE_SILENCE_ROOT_WARNING=1 \
BUNDLE_APP_CONFIG="$GEM_HOME"
ENV PATH $BUNDLE_BIN:$PATH
RUN mkdir -p "$GEM_HOME" "$BUNDLE_BIN" \
&& chmod 777 "$GEM_HOME" "$BUNDLE_BIN"
USER circleci

@ -0,0 +1,20 @@
# elixir-node-ruby
The `elixir-node-ruby` is a variant of `circleci/elixir` Dockerfiles that adds Ruby on top of `elixir:*-node`, so that `license_finder`, a Ruby Gem, can scan Elixir (`mix`) and Node dependencies in [POA Network](https://github.com/poanetwork) repositories, such as https://github.com/poanetwork/poa-explorer.
## Building
1. `cd .circleci/elixir-node-ruby`
2. `docker build -t poanetwork/elixir:1.6.4-node-ruby .`
## Testing
1. `docker run -it poanetwork/elixir:1.6.4-node-ruby /bin/bash`
2. Run IRB to check for ruby: `irb`
3. In IRB, quit: `quit`
4. Exit container shell: `exit`
## Publishing
1. Login to DockerHub from the Docker CLI: `docker login`
2. Push image `docker push poanetwork/elixir:1.6.4-node-ruby`

@ -0,0 +1,16 @@
#!/bin/bash
wget https://cli-assets.heroku.com/branches/stable/heroku-linux-amd64.tar.gz
sudo mkdir -p /usr/local/lib /usr/local/bin
sudo tar -xvzf heroku-linux-amd64.tar.gz -C /usr/local/lib
sudo ln -s /usr/local/lib/heroku/bin/heroku /usr/local/bin/heroku
cat > ~/.netrc << EOF
machine api.heroku.com
login $HEROKU_LOGIN
password $HEROKU_API_KEY
EOF
cat >> ~/.ssh/config << EOF
VerifyHostKeyDNS yes
StrictHostKeyChecking no
EOF

@ -33,7 +33,7 @@
# If you want to enforce a style guide and need a more traditional linting # If you want to enforce a style guide and need a more traditional linting
# experience, you can change `strict` to `true` below: # experience, you can change `strict` to `true` below:
# #
strict: false, strict: true,
# #
# If you want to use uncolored output by default, you can change `color` # If you want to use uncolored output by default, you can change `color`
# to `false` below: # to `false` below:

@ -1,4 +1,5 @@
elixir 1.6.1 elixir 1.6.4
erlang 20.2.4 erlang 20.3.2
nodejs 9.10.1
ruby 2.4.1 ruby 2.4.1
nodejs 9.10.1 nodejs 9.10.1

@ -1,3 +1,8 @@
# https://github.com/CircleCI-Public/circleci-demo-elixir-phoenix/blob/a89de33a01df67b6773ac90adc74c34367a4a2d6/test/test_helper.exs#L1-L3
junit_folder = Mix.Project.build_path() <> "/junit/#{Mix.Project.config[:app]}"
File.mkdir_p!(junit_folder)
:ok = Application.put_env(:junit_formatter, :report_dir, junit_folder)
ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter]) ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter])
ExUnit.start() ExUnit.start()

@ -1,3 +1,8 @@
# https://github.com/CircleCI-Public/circleci-demo-elixir-phoenix/blob/a89de33a01df67b6773ac90adc74c34367a4a2d6/test/test_helper.exs#L1-L3
junit_folder = Mix.Project.build_path() <> "/junit/#{Mix.Project.config[:app]}"
File.mkdir_p!(junit_folder)
:ok = Application.put_env(:junit_formatter, :report_dir, junit_folder)
ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter]) ExUnit.configure(formatters: [JUnitFormatter, ExUnit.CLIFormatter])
ExUnit.start() ExUnit.start()

@ -1,78 +0,0 @@
general:
artifacts:
- screenshots
machine:
environment:
PATH: "$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"
MIX_ENV: "test"
node:
version: 9.4.0
services:
- postgresql
- redis
pre:
- mkdir -p $CIRCLE_TEST_REPORTS/exunit
- mkdir -p $CIRCLE_TEST_REPORTS/eslint
dependencies:
pre:
- wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- sudo dpkg -i google-chrome-stable_current_amd64.deb
- sudo sed -i 's|HERE/chrome\"|HERE/chrome\" --disable-setuid-sandbox|g' /opt/google/chrome/google-chrome
- rm google-chrome-stable_current_amd64.deb
- "LATEST_RELEASE=`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE` && wget https://chromedriver.storage.googleapis.com/${LATEST_RELEASE}/chromedriver_linux64.zip"
- unzip chromedriver_linux64.zip
- sudo cp chromedriver /usr/local/bin/chromedriver
- sudo chmod +x /usr/local/bin/chromedriver
- if ! asdf | grep version; then git clone https://github.com/HashNuke/asdf.git ~/.asdf; fi
- if ! asdf plugin-list | grep erlang; then asdf plugin-add erlang https://github.com/HashNuke/asdf-erlang.git; fi
- if ! asdf plugin-list | grep elixir; then asdf plugin-add elixir https://github.com/HashNuke/asdf-elixir.git; fi
- if ! asdf plugin-list | grep ruby; then asdf plugin-add ruby https://github.com/HashNuke/asdf-ruby.git; fi
- awk '/erlang/ { print $2 }' .tool-versions | xargs asdf install erlang:
timeout: 3600
- awk '/elixir/ { print $2 }' .tool-versions | xargs asdf install elixir:
timeout: 3600
- awk '/ruby/ { print $2 }' .tool-versions | xargs asdf install ruby:
timeout: 3600
- gem install bundler
- mix local.hex --force:
timeout: 3600
- mix local.rebar --force:
timeout: 3600
override:
- mix do deps.get, deps.compile, compile
- bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
- mix dialyzer --plt:
timeout: 3600
- cd apps/explorer_web/assets && yarn install && yarn build && cd -
cache_directories:
- ~/.asdf
- _build
- deps
- apps/explorer_web/assets/node_modules
- vendor/bundle
test:
pre:
- mix format --check-formatted
- mix credo
- mix sobelow --config
- mix dialyzer --halt-exit-status
- bundle exec license_finder --project-path=. --decisions-file=doc/dependency_decisions.yml
- cd apps/explorer_web/assets && bundle exec license_finder --decisions-file=../../..//doc/dependency_decisions.yml && cd -
- cd apps/explorer_web/assets && yarn eslint --format=junit --output-file="$CIRCLE_TEST_REPORTS/eslint/junit.xml" && cd -
override:
- mix test
post:
- cp _build/test/lib/explorer/test-junit-report.xml $CIRCLE_TEST_REPORTS/exunit
deployment:
staging:
branch: master
commands:
- bin/deploy poa-explorer-staging
production:
branch: production
commands:
- bin/deploy poa-explorer-production

@ -1,3 +1,3 @@
erlang_version=20.2 erlang_version=20.3.2
elixir_version=1.6.1 elixir_version=1.6.4
always_rebuild=true always_rebuild=true

Loading…
Cancel
Save