QiitaTrend という Ruby の gem を開発していく中で導入した CircleCI の設定がどういう理由でどう変わっていったのか当時の状況を思い出しつつまとめてみたいと思います
QiitaTrend は Qiitaのトレンド情報(Daily、Weekly、Monthly)を10秒で取得することができる gem になります。
config.yml の大まかな年表
CircleCI の config.yml を今まででたくさん更新してきました。
運用してきた config.yml は厳密にはもっと修正が細かいですが大まかに分けると以下のような修正履歴になります。
年月 | 変更内容 |
---|---|
2019/08 | CircleCIの導入 |
2019/08 | YARD でドキュメントが自動生成されるように変更 |
2019/08 | ワークフローを導入 |
2019/12 | CircleCI2.1へバージョンアップ |
2020/02 | workspace 機能の導入 |
2020/04 | slack 通知・デプロイ承認機能追加 |
2020/08 | 毎日テストを実行させるワークフローを追加 |
2020/10 | CircleCI のイメージを次世代のものに変更 |
2020/11 | Ruby の orb の導入 |
2019年8月:初じめてのCircleCI
自分の勉強のために Ruby の gem を作成しようというところから始まります。
テストとデプロイを自動化したい という思いから業務でも使用していた CircleCI を導入すること にしました。
そもそもこの時点では CI/CDの構築を一回もしたことがなく ほぼ知識がない状態からの導入です。
導入方法
そもそも知識がない状態でどうやって導入したんだっけ?
思い出してみると初導入に関しては Qiita に記事 として残してあります。
基本的には 公式のドキュメントを読んでそのままコピペしたものに不必要なものを削除、必要な機能を追加していき作成 しました。詳しくは Qiita の記事を読んでください。
config.yml
初めて導入した config.yml は以下です。今、見るととても簡素なものですね(笑)
version2.1 ではないし、workflow も組んでいませんね。
config.yml
# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/ruby:2.6.0-node-browsers
environment:
BUNDLER_VERSION: 2.0.1
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/postgres:9.4
working_directory: ~/repo
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
# install Bundler!
# ref:https://discuss.circleci.com/t/using-bundler-2-0-during-ci-fails/27411
- run:
name: install bundler
command: |
sudo gem update --system
sudo gem uninstall bundler
sudo rm /usr/local/bin/bundle
sudo rm /usr/local/bin/bundler
sudo gem install bundler
# install gem!
- run:
name: install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
# run rubocop!
- run:
name: run rubocop
command: |
bundle exec rubocop
# run tests!
- run:
name: run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$TEST_FILES
# collect reports
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
# deploy RubyGems
- deploy:
command: |
if [ "${CIRCLE_BRANCH}" == "master" ]; then
mkdir ~/.gem
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
fi
追加した内容
キャッシュ以外の処理について説明します。基本的には CircleCI のドキュメントに載っていたものをそのまま持ってきただけのものが多いです。
Bundler のインストール
- Bundler のインストールを行っている処理
- こちらは CircleCI のドキュメントに書かれていたものをコピペして実装
- ちなみに Bundler とは gem のバージョンや gem の依存関係を管理してくれる gem のこと
- run:
name: install bundler
command: |
sudo gem update --system
sudo gem uninstall bundler
sudo rm /usr/local/bin/bundle
sudo rm /usr/local/bin/bundler
sudo gem install bundler
依存関係のインストール
- gem で使用する依存関係をインストールする処理
- こちらも CircleCI のドキュメントに書かれていたものをコピペして実装
- run:
name: install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
RuboCop の実行
- 静的解析ツールの RuboCop を実行している処理
- run:
name: run rubocop
command: |
bundle exec rubocop
RSpec の実行
- RSpec を実行している処理(テストの実行)
- こちらも CircleCI のドキュメントに書かれていたものをコピペして実装
- run:
name: run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$TEST_FILES
成果物のアップロード
- テスト結果、カバレッジの結果を CircleCI にアップロードして結果を見れるようにしている処理
- こちらも CircleCI のドキュメントを参考に実装したものです
# collect reports
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
RubyGems へデプロイ
- master ブランチの時に RubyGems へのデプロイをする処理
- RubygemsへのデプロイをCircleCIで自動化してみた | WEB EGG を参考に実装
- deploy:
command: |
if [ "${CIRCLE_BRANCH}" == "master" ]; then
mkdir ~/.gem
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
fi
初めて導入してみてどうだったか?
- CI/CD がよくわからない難しいものだと思っていたが実際に順を追って導入すると そんなに難しくないこと がわかった
- CircleCI の キャッシュについてある程度、理解することができた
2019年8月:ドキュメントの自動作成
gem のドキュメントを RubyDoc.info に公開するために YARD を導入しドキュメントを自動生成する処理を追加。 実際に公開しているドキュメントはこちらになります。
config.yml
ドキュメントを自動生成する処理を追加した config.yml です。
config.yml
# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/ruby:2.6.0-node-browsers
environment:
BUNDLER_VERSION: 2.0.1
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/postgres:9.4
working_directory: ~/repo
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
# install Bundler!
# ref:https://discuss.circleci.com/t/using-bundler-2-0-during-ci-fails/27411
- run:
name: install bundler
command: |
sudo gem update --system
sudo gem uninstall bundler
sudo rm /usr/local/bin/bundle
sudo rm /usr/local/bin/bundler
sudo gem install bundler
# install gem!
- run:
name: install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
# run rubocop!
- run:
name: run rubocop
command: |
bundle exec rubocop
# run tests!
- run:
name: run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$TEST_FILES
# create document
- run:
name: create document
command: |
bundle exec yard
# collect reports
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
# deploy RubyGems
- deploy:
command: |
if [ "${CIRCLE_BRANCH}" == "master" ]; then
mkdir ~/.gem
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
fi
更新内容
YARD の作成処理と作成した YARD のアップロード機能を追加。
YARD の作成
- YARD のドキュメントを参考に実装
# create document
- run:
name: create document
command: |
bundle exec yard
作成した YARD のアップロード
- 以前同じようなことをしているので特に何も考えなくても実装できた
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
2019年8月:ワークフローの導入
ワークフローという機能があることに気づき、 ワークフローの導入を行う。
config.yml
ワークフローの設定を追加した config.yml です。
config.yml
# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2
jobs:
build:
docker:
- image: circleci/ruby:2.6.0
environment:
BUNDLE_PATH: vendor/bundle
working_directory: ~/repo
steps:
- checkout
# Install Bundler
# ref:https://discuss.circleci.com/t/using-bundler-2-0-during-ci-fails/27411
- run:
name: Install Bundler
command: |
echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
source $BASH_ENV
gem install bundler
# Which version of bundler?
- run:
name: Which bundler?
command: bundle -v
# Restore bundle cache
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
# Install gem
- run:
name: Install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
# Store bundle cache for Ruby dependencies
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
# Run RuboCop
- run:
name: Run RuboCop
command: |
bundle exec rubocop
# Run tests
- run:
name: Run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$TEST_FILES
# Create document
- run:
name: Create document
command: |
bundle exec yard
# Collect Reports
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
deploy:
docker:
- image: circleci/ruby:2.6.0
steps:
- checkout
# Install Bundler
# ref:https://discuss.circleci.com/t/using-bundler-2-0-during-ci-fails/27411
- run:
name: install Bundler
command: |
echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
source $BASH_ENV
gem install bundler
# Which version of bundler?
- run:
name: Which bundler?
command: bundle -v
# Restore bundle cache
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
- v1-dependencies-
# Install gem
- run:
name: Install gem
command: bundle check --path vendor/bundle || bundle install
# Store bundle cache for Ruby dependencies
- save_cache:
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
paths:
- vendor/bundle
# Deploy RubyGems
- run:
name: Deploy RubyGems
command: |
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
workflows:
version: 2
build-and-deploy:
jobs:
- build
- deploy:
requires:
- build
filters:
branches:
only: master # masterブランチの時だけDeployJobを実行するようにする
更新内容
build の一部を切り離し deploy という job を作成しそれぞれを workflows で順番を担保させるように改修。
追加した workflow 設定
- build → deploy の順番で処理されるように設定
- deploy は master ブランチのみ実行されるように設定。
workflows:
version: 2
build-and-deploy:
jobs:
- build
- deploy:
requires:
- build
filters:
branches:
only: master # masterブランチの時だけDeployJobを実行するようにする
2019年12月:CircleCI 2.1 の導入
CircleCI のバージョンを 2.0 から 2.1 に変更し冗長な書きぶりを排除。
この改修をしてた時は AWS 認定 ソリューションアーキテクト – アソシエイト を受けて落ちてやけくそになっていた時でした(笑)
これが完成した時は少しだけいい気分になりました……。CircleCI のおかげです。
AWS 認定 ソリューションアーキテクト – アソシエイト は1ヶ月後に無事受かりました。
config.yml
バージョンを 2.0 から 2.1 に変更した config.yml です。
config.yml
version: 2.1
executors:
base:
docker:
- image: circleci/ruby:2.6.0
environment:
BUNDLE_PATH: vendor/bundle
working_directory: ~/repo
commands:
# ref:https://discuss.circleci.com/t/using-bundler-2-0-during-ci-fails/27411
install-bundler:
steps:
- run:
name: Install Bundler
command: |
echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
source $BASH_ENV
gem install bundler
# Which version of bundler?
bundle -v
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
restore-gem-cache:
steps:
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
install-gem:
steps:
- run:
name: Install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
save-gem-cache:
steps:
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
run-rubocop:
steps:
- run:
name: Run RuboCop
command: |
bundle exec rubocop
run-tests:
steps:
- run:
name: Run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$TEST_FILES
create-document:
steps:
- run:
name: Create document
command: |
bundle exec yard
collect-reports:
steps:
# ref:https://circleci.com/docs/ja/2.0/configuration-reference/#store_test_results
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
# Deploy RubyGems
deploy-rubygems:
steps:
- run:
name: Deploy RubyGems
command: |
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
jobs:
setup:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- install-gem
- save-gem-cache
lint:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- run-rubocop
test:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- run-tests
- create-document
- collect-reports
deploy:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- deploy-rubygems
workflows:
version: 2.1
main:
jobs:
- setup
- lint:
requires:
- setup
- test:
requires:
- setup
- deploy:
requires:
- lint
- test
filters:
branches:
only: master # masterブランチの時だけDeployJobを実行するようにする
更新内容
この時の改修が一番変更箇所が多くて中身がガラッと変わった時です。
executor と command 機能を使用することで冗長な部分がなくなりかなりスッキリとした改修になりました。
まだ 2.0 を使っているなら はやく 2.1 にバージョンアップすることをオススメ します。
executors
- executors を使用しそれぞれの job で image を使い回すことができるようになった
executors:
base:
docker:
- image: circleci/ruby:2.6.0
environment:
BUNDLE_PATH: vendor/bundle
working_directory: ~/repo
commands
- commands に必要な処理をそれぞれ実装し使い回せるようにする
commands:
# ref:https://discuss.circleci.com/t/using-bundler-2-0-during-ci-fails/27411
install-bundler:
steps:
- run:
name: Install Bundler
command: |
echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV
source $BASH_ENV
gem install bundler
# Which version of bundler?
bundle -v
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
restore-gem-cache:
steps:
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
install-gem:
steps:
- run:
name: Install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
save-gem-cache:
steps:
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
run-rubocop:
steps:
- run:
name: Run RuboCop
command: |
bundle exec rubocop
run-tests:
steps:
- run:
name: Run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$TEST_FILES
create-document:
steps:
- run:
name: Create document
command: |
bundle exec yard
collect-reports:
steps:
# ref:https://circleci.com/docs/ja/2.0/configuration-reference/#store_test_results
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
# Deploy RubyGems
deploy-rubygems:
steps:
- run:
name: Deploy RubyGems
command: |
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
jobs
- executor と command を使用し jobs をスッキリと記述
- 細かい単位で job を定義する
jobs:
setup:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- install-gem
- save-gem-cache
lint:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- run-rubocop
test:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- run-tests
- create-document
- collect-reports
deploy:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- deploy-rubygems
workflows
- 細かくした job を反映させる
workflows:
version: 2.1
main:
jobs:
- setup
- lint:
requires:
- setup
- test:
requires:
- setup
- deploy:
requires:
- lint
- test
filters:
branches:
only: master # masterブランチの時だけDeployJobを実行するようにする
2020年2月:workspace 機能の導入
workspace という job 間で使用できるキャッシュ機能 を知り、実装する
config.yml
workspace を追加し job 間でキャッシュを使えるようにした config.yml です。
config.yml
version: 2.1
executors:
base:
docker:
- image: circleci/ruby:2.6.0
environment:
# Bundlerのパス設定が書き換えられ`vendor/bundle`ではなくて`/usr/local/bundle`を参照してしまい`bundle exec`でエラーになる
# Bundlerのconfigファイル(pathの設定がされたもの)をworkspaceで永続化し`vendor/bundle`を参照するようにするための設定
BUNDLE_APP_CONFIG: .bundle
working_directory: ~/dodonki1223/qiita_trend
commands:
install-bundler:
steps:
- run:
name: Install bundler(2.1.0)
command: gem install bundler:2.1.0
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
restore-gem-cache:
steps:
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
install-gem:
steps:
- run:
name: Install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
save-gem-cache:
steps:
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
save-workspace:
steps:
- persist_to_workspace:
# working_directory からの相対パスか絶対パスを指定します
root: .
paths: .
using-workspace:
steps:
- attach_workspace:
# working_directory からの相対パスか絶対パスを指定します
at: .
run-rubocop:
steps:
- run:
name: Run RuboCop
command: |
bundle exec rubocop
run-tests:
steps:
- run:
name: Run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$TEST_FILES
create-document:
steps:
- run:
name: Create document
command: |
bundle exec yard
collect-reports:
steps:
# ref:https://circleci.com/docs/ja/2.0/configuration-reference/#store_test_results
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
deploy-rubygems:
steps:
# ref:https://support.circleci.com/hc/ja/articles/115015628247-%E6%8E%A5%E7%B6%9A%E3%82%92%E7%B6%9A%E8%A1%8C%E3%81%97%E3%81%BE%E3%81%99%E3%81%8B-%E3%81%AF%E3%81%84-%E3%81%84%E3%81%84%E3%81%88-
# read/write両方の権限が必要
- add_ssh_keys:
fingerprints:
- "38:d2:72:5e:9f:67:93:9a:ec:95:94:a2:0e:bf:41:9e"
# ref:https://circleci.com/docs/2.0/gh-bb-integration/#establishing-the-authenticity-of-an-ssh-host
- run:
name: Avoid hosts unknown for github
command: |
mkdir -p ~/.ssh
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
' >> ~/.ssh/known_hosts
- run:
name: Deploy RubyGems
command: |
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials
chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
jobs:
setup:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- install-gem
- save-gem-cache
- save-workspace
lint:
executor: base
steps:
- using-workspace
- install-bundler
- run-rubocop
test:
executor: base
steps:
- using-workspace
- install-bundler
- run-tests
- create-document
- collect-reports
deploy:
executor: base
steps:
- using-workspace
- install-bundler
- deploy-rubygems
workflows:
version: 2.1
main:
jobs:
- setup
- lint:
requires:
- setup
- test:
requires:
- setup
- deploy:
requires:
- lint
- test
filters:
branches:
only: master # masterブランチの時だけDeployJobを実行するようにする
更新内容
workspace の保存と適用の command を追加しそれを job で使用するように更新。
workspace の保存と適用の command を追加
command に workspace の保存と適用のコマンドをそれぞれ追加する。
save-workspace:
steps:
- persist_to_workspace:
# working_directory からの相対パスか絶対パスを指定します
root: .
paths: .
using-workspace:
steps:
- attach_workspace:
# working_directory からの相対パスか絶対パスを指定します
at: .
job で workspace を使用する
- setup の job で workspace に保存する
- setup で作成した資材をそれぞれの job で使用する
jobs:
setup:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- install-gem
- save-gem-cache
- save-workspace
lint:
executor: base
steps:
- using-workspace
- install-bundler
- run-rubocop
test:
executor: base
steps:
- using-workspace
- install-bundler
- run-tests
- create-document
- collect-reports
deploy:
executor: base
steps:
- using-workspace
- install-bundler
- deploy-rubygems
workspace の導入でわかったこと
画像は CircleCIのドキュメント より参照
- CircleCI で使用できるキャッシュについて理解できた
- job のキャッシュ と workflow で使い回せるキャッシュ(workspace) があることを知った
2020年4月:Slack通知・デプロイ承認機能の追加
初めて orb を導入し slack 通知とデプロイの承認機能を追加。
config.yml
slack 通知とデプロイの承認機能を追加した config.yml です。
config.yml
version: 2.1
orbs:
slack: circleci/slack@3.4.2
executors:
base:
docker:
- image: circleci/ruby:2.6.0
environment:
# Bundlerのパス設定が書き換えられ`vendor/bundle`ではなくて`/usr/local/bundle`を参照してしまい`bundle exec`でエラーになる
# Bundlerのconfigファイル(pathの設定がされたもの)をworkspaceで永続化し`vendor/bundle`を参照するようにするための設定
BUNDLE_APP_CONFIG: .bundle
working_directory: ~/dodonki1223/qiita_trend
commands:
install-bundler:
steps:
- run:
name: Install bundler(2.1.0)
command: gem install bundler:2.1.0
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
restore-gem-cache:
steps:
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
install-gem:
steps:
- run:
name: Install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
save-gem-cache:
steps:
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
save-workspace:
steps:
- persist_to_workspace:
# working_directory からの相対パスか絶対パスを指定します
root: .
paths: .
using-workspace:
steps:
- attach_workspace:
# working_directory からの相対パスか絶対パスを指定します
at: .
run-rubocop:
steps:
- run:
name: Run RuboCop
command: |
bundle exec rubocop
run-tests:
steps:
- run:
name: Run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec.xml \
--format progress \
$TEST_FILES
collect-reports:
steps:
# ref:https://circleci.com/docs/ja/2.0/configuration-reference/#store_test_results
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
create-document:
steps:
- run:
name: Create document
command: |
bundle exec yard
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
deploy-rubygems:
steps:
# ref:https://support.circleci.com/hc/ja/articles/115015628247-%E6%8E%A5%E7%B6%9A%E3%82%92%E7%B6%9A%E8%A1%8C%E3%81%97%E3%81%BE%E3%81%99%E3%81%8B-%E3%81%AF%E3%81%84-%E3%81%84%E3%81%84%E3%81%88-
# read/write両方の権限が必要
- add_ssh_keys:
fingerprints:
- "38:d2:72:5e:9f:67:93:9a:ec:95:94:a2:0e:bf:41:9e"
# ref:https://circleci.com/docs/2.0/gh-bb-integration/#establishing-the-authenticity-of-an-ssh-host
- run:
name: Avoid hosts unknown for github
command: |
mkdir -p ~/.ssh
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
' >> ~/.ssh/known_hosts
- run:
name: Deploy RubyGems
command: |
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials
chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
deploy-notification:
steps:
- slack/status:
success_message: ':circleci-pass: RubyGemsにデプロイが完了しました\n:github_octocat: User: $CIRCLE_USERNAME'
failure_message: ':circleci-fail: RubyGemsにデプロイが失敗しました\n:github_octocat: User: $CIRCLE_USERNAME'
jobs:
setup:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- install-gem
- save-gem-cache
- save-workspace
lint:
executor: base
steps:
- using-workspace
- install-bundler
- run-rubocop
test:
executor: base
steps:
- using-workspace
- install-bundler
- run-tests
- collect-reports
document:
executor: base
steps:
- using-workspace
- install-bundler
- create-document
deploy:
executor: base
steps:
- using-workspace
- install-bundler
- deploy-rubygems
- deploy-notification
workflows:
version: 2.1
main:
jobs:
- setup
- lint:
requires:
- setup
- test:
requires:
- setup
- document:
requires:
- setup
- slack/approval-notification:
message: ':circleci-pass: RubyGemsへのデプロイ準備が整っています\n:github_octocat: User: $CIRCLE_USERNAME\nデプロイを実行する場合は *Approve* を押してください'
requires:
- lint
- test
filters:
branches:
only: master
- approval-job:
type: approval
requires:
- slack/approval-notification
- deploy:
requires:
- approval-job
filters:
branches:
only: master
更新内容
orbs に slack を追加し承認のプロセスを slack に通知したり、デプロイ完了後に slack に通知させる機能を追加した。
orbs に slack を追加
version: 2.1
orbs:
slack: circleci/slack@3.4.2
デプロイ完了通知を追加
- command にデプロイの完了を slack に通知させる
deploy-notification:
steps:
- slack/status:
success_message: ':circleci-pass: RubyGemsにデプロイが完了しました\n:github_octocat: User: $CIRCLE_USERNAME'
failure_message: ':circleci-fail: RubyGemsにデプロイが失敗しました\n:github_octocat: User: $CIRCLE_USERNAME'
- deploy の job の最後に slack 通知を追加
deploy:
executor: base
steps:
- using-workspace
- install-bundler
- deploy-rubygems
- deploy-notification
承認プロセスを追加
- workflow に承認のプロセスを追加
- master ブランチの時のみ実行されるようにする
workflows:
version: 2.1
main:
jobs:
・
・
・
- slack/approval-notification:
message: ':circleci-pass: RubyGemsへのデプロイ準備が整っています\n:github_octocat: User: $CIRCLE_USERNAME\nデプロイを実行する場合は *Approve* を押してください'
requires:
- lint
- test
filters:
branches:
only: master
・
・
・
2020年8月:毎日テストを実行させるワークフローを追加
QiitaTrend という gem は Qiita のサイトをスクレイピングしているため、DOM の構成が変わるとエラーで落ちてしまいます。
いつの間にかテストが落ちていることが何度かあり gem が使用できなくなることがあった。
DOM の構成が変わったことをいち早く検知 する必要があったため 毎日テストを実行する ように修正。
config.yml
テストが定期実行するように設定を追加した config.yml です。
config.yml
version: 2.1
orbs:
slack: circleci/slack@3.4.2
executors:
base:
docker:
- image: circleci/ruby:2.6.0
auth:
username: dodonki1223
password: $DOCKERHUB_PASSWORD
environment:
# Bundlerのパス設定が書き換えられ`vendor/bundle`ではなくて`/usr/local/bundle`を参照してしまい`bundle exec`でエラーになる
# Bundlerのconfigファイル(pathの設定がされたもの)をworkspaceで永続化し`vendor/bundle`を参照するようにするための設定
BUNDLE_APP_CONFIG: .bundle
# ref: https://circleci.com/docs/2.0/faq/#how-can-i-set-the-timezone-in-docker-images
TZ: "Asia/Tokyo"
working_directory: ~/dodonki1223/qiita_trend
commands:
install-bundler:
steps:
- run:
name: Install bundler(2.1.0)
command: gem install bundler:2.1.0
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
restore-gem-cache:
steps:
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
install-gem:
steps:
- run:
name: Install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
save-gem-cache:
steps:
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
save-workspace:
steps:
- persist_to_workspace:
# working_directory からの相対パスか絶対パスを指定します
root: .
paths: .
using-workspace:
steps:
- attach_workspace:
# working_directory からの相対パスか絶対パスを指定します
at: .
run-rubocop:
steps:
- run:
name: Run RuboCop
command: |
bundle exec rubocop
run-tests:
steps:
- run:
name: Run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec/rspec.xml \
--format progress \
$TEST_FILES
collect-reports:
steps:
# ref:https://circleci.com/docs/ja/2.0/configuration-reference/#store_test_results
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
create-document:
steps:
- run:
name: Create document
command: |
bundle exec yard
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
deploy-rubygems:
steps:
# ref:https://support.circleci.com/hc/ja/articles/115015628247-%E6%8E%A5%E7%B6%9A%E3%82%92%E7%B6%9A%E8%A1%8C%E3%81%97%E3%81%BE%E3%81%99%E3%81%8B-%E3%81%AF%E3%81%84-%E3%81%84%E3%81%84%E3%81%88-
# read/write両方の権限が必要
- add_ssh_keys:
fingerprints:
- "38:d2:72:5e:9f:67:93:9a:ec:95:94:a2:0e:bf:41:9e"
# ref:https://circleci.com/docs/2.0/gh-bb-integration/#establishing-the-authenticity-of-an-ssh-host
- run:
name: Avoid hosts unknown for github
command: |
mkdir -p ~/.ssh
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
' >> ~/.ssh/known_hosts
- run:
name: Deploy RubyGems
command: |
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials
chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
deploy-notification:
steps:
- slack/status:
success_message: ':circleci-pass: RubyGemsにデプロイが完了しました\n:github_octocat: User: $CIRCLE_USERNAME'
failure_message: ':circleci-fail: RubyGemsにデプロイが失敗しました\n:github_octocat: User: $CIRCLE_USERNAME'
jobs:
setup:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- install-gem
- save-gem-cache
- save-workspace
lint:
executor: base
steps:
- using-workspace
- install-bundler
- run-rubocop
test:
executor: base
steps:
- using-workspace
- install-bundler
- run-tests
- collect-reports
document:
executor: base
steps:
- using-workspace
- install-bundler
- create-document
deploy:
executor: base
steps:
- using-workspace
- install-bundler
- deploy-rubygems
- deploy-notification
workflows:
version: 2.1
main:
jobs:
- setup
- lint:
requires:
- setup
- test:
requires:
- setup
- document:
requires:
- setup
- slack/approval-notification:
message: ':circleci-pass: RubyGemsへのデプロイ準備が整っています\n:github_octocat: User: $CIRCLE_USERNAME\nデプロイを実行する場合は *Approve* を押してください'
requires:
- lint
- test
filters:
branches:
only: master
- approval-job:
type: approval
requires:
- slack/approval-notification
- deploy:
requires:
- approval-job
filters:
branches:
only: master
# 定期でテストを実行する
# ref:https://circleci.com/docs/ja/2.0/triggers/
nightly:
triggers:
- schedule:
cron: "0 22 * * *" # UTCで記述
filters:
branches:
only:
- master
jobs:
- setup
- test:
requires:
- setup
更新内容
RSpec を毎日実行しテストが落ちない限りは Qiita のトレンド情報を取得できることを担保する。
テストを毎日実行させる
- triggers を使用し毎日、朝の7時にテストが実行されるようにする
workflows:
version: 2.1
# 定期でテストを実行する
# ref:https://circleci.com/docs/ja/2.0/triggers/
nightly:
triggers:
- schedule:
cron: "0 22 * * *" # UTCで記述
filters:
branches:
only:
- master
jobs:
- setup
- test:
requires:
- setup
毎日実行するようになってどうなった?
- テストが何度か落ちて、DOMの構成が変わったことをいち早く検知することができるようになった
- テストが落ちた時は CircleCI と slack を連携させているため通知が来てすぐに検知が可能
こんな感じでエラーが slack に通知される
2020年10月:CircleCI のイメージを次世代ものに変更
CircleCI実践入門──CI/CDがもたらす開発速度と品質の両立 の本が発売されたので読んでみると cimg という次世代の image があることを知り、こちらを導入することにした。
config.yml
cimg に変更した config.yml
config.yml
version: 2.1
orbs:
slack: circleci/slack@3.4.2
executors:
base:
docker:
- image: cimg/ruby:2.6.6
auth:
username: dodonki1223
password: $DOCKERHUB_PASSWORD
environment:
# Bundlerのパス設定が書き換えられ`vendor/bundle`ではなくて`/usr/local/bundle`を参照してしまい`bundle exec`でエラーになる
# Bundlerのconfigファイル(pathの設定がされたもの)をworkspaceで永続化し`vendor/bundle`を参照するようにするための設定
BUNDLE_APP_CONFIG: .bundle
# ref: https://circleci.com/docs/2.0/faq/#how-can-i-set-the-timezone-in-docker-images
TZ: "Asia/Tokyo"
working_directory: ~/dodonki1223/qiita_trend
commands:
install-bundler:
steps:
- run:
name: Install bundler(2.1.0)
command: gem install bundler:2.1.0
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
restore-gem-cache:
steps:
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
install-gem:
steps:
- run:
name: Install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
save-gem-cache:
steps:
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
save-workspace:
steps:
- persist_to_workspace:
# working_directory からの相対パスか絶対パスを指定します
root: .
paths: .
using-workspace:
steps:
- attach_workspace:
# working_directory からの相対パスか絶対パスを指定します
at: .
run-rubocop:
steps:
- run:
name: Run RuboCop
command: |
bundle exec rubocop
run-tests:
steps:
- run:
name: Run tests
command: |
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
bundle exec rspec \
--format progress \
--format RspecJunitFormatter \
--out test_results/rspec/rspec.xml \
--format progress \
$TEST_FILES
collect-reports:
steps:
# ref:https://circleci.com/docs/ja/2.0/configuration-reference/#store_test_results
- store_test_results:
path: test_results
- store_artifacts:
# テスト結果をtest-resultsディレクトリに吐き出す
path: test_results
destination: test-results
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
create-document:
steps:
- run:
name: Create document
command: |
bundle exec yard
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
deploy-rubygems:
steps:
# ref:https://support.circleci.com/hc/ja/articles/115015628247-%E6%8E%A5%E7%B6%9A%E3%82%92%E7%B6%9A%E8%A1%8C%E3%81%97%E3%81%BE%E3%81%99%E3%81%8B-%E3%81%AF%E3%81%84-%E3%81%84%E3%81%84%E3%81%88-
# read/write両方の権限が必要
- add_ssh_keys:
fingerprints:
- "38:d2:72:5e:9f:67:93:9a:ec:95:94:a2:0e:bf:41:9e"
# ref:https://circleci.com/docs/2.0/gh-bb-integration/#establishing-the-authenticity-of-an-ssh-host
- run:
name: Avoid hosts unknown for github
command: |
mkdir -p ~/.ssh
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
' >> ~/.ssh/known_hosts
- run:
name: Deploy RubyGems
command: |
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials
chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
deploy-notification:
steps:
- slack/status:
success_message: ':circleci-pass: RubyGemsにデプロイが完了しました\n:github_octocat: User: $CIRCLE_USERNAME'
failure_message: ':circleci-fail: RubyGemsにデプロイが失敗しました\n:github_octocat: User: $CIRCLE_USERNAME'
jobs:
setup:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- install-gem
- save-gem-cache
- save-workspace
lint:
executor: base
steps:
- using-workspace
- install-bundler
- run-rubocop
test:
executor: base
steps:
- using-workspace
- install-bundler
- run-tests
- collect-reports
document:
executor: base
steps:
- using-workspace
- install-bundler
- create-document
deploy:
executor: base
steps:
- using-workspace
- install-bundler
- deploy-rubygems
- deploy-notification
workflows:
version: 2.1
main:
jobs:
- setup
- test:
requires:
- setup
- document:
requires:
- setup
- slack/approval-notification:
message: ':circleci-pass: RubyGemsへのデプロイ準備が整っています\n:github_octocat: User: $CIRCLE_USERNAME\nデプロイを実行する場合は *Approve* を押してください'
requires:
- lint
- test
filters:
branches:
only: master
- approval-job:
type: approval
requires:
- slack/approval-notification
- deploy:
requires:
- approval-job
filters:
branches:
only: master
# 定期でテストを実行する
# ref:https://circleci.com/docs/ja/2.0/triggers/
nightly:
triggers:
- schedule:
cron: "0 22 * * *" # UTCで記述
filters:
branches:
only:
- master
jobs:
- setup
- test:
requires:
- setup
更新内容
次世代の image を使用して executors を作成するように修正。
cimg に変更
- cimg/ruby:2.6.6 を使用するように修正
version: 2.1
orbs:
slack: circleci/slack@3.4.2
executors:
base:
docker:
- image: cimg/ruby:2.6.6
auth:
username: dodonki1223
password: $DOCKERHUB_PASSWORD
environment:
# Bundlerのパス設定が書き換えられ`vendor/bundle`ではなくて`/usr/local/bundle`を参照してしまい`bundle exec`でエラーになる
# Bundlerのconfigファイル(pathの設定がされたもの)をworkspaceで永続化し`vendor/bundle`を参照するようにするための設定
BUNDLE_APP_CONFIG: .bundle
# ref: https://circleci.com/docs/2.0/faq/#how-can-i-set-the-timezone-in-docker-images
TZ: "Asia/Tokyo"
working_directory: ~/dodonki1223/qiita_trend
2020年11月:Ruby の orb を導入
Ruby の orb を使用することで自前で実装していた処理を orb で提供された command 使用することができるようになり記述の簡略化ができるようになった。
config.yml
Ruby の orb に寄せた config.yml です。
config.yml
version: 2.1
orbs:
ruby: circleci/ruby@1.1.2
slack: circleci/slack@3.4.2
executors:
base:
docker:
- image: cimg/ruby:2.6.6
auth:
username: dodonki1223
password: $DOCKERHUB_PASSWORD
environment:
# Bundlerのパス設定が書き換えられ`vendor/bundle`ではなくて`/usr/local/bundle`を参照してしまい`bundle exec`でエラーになる
# Bundlerのconfigファイル(pathの設定がされたもの)をworkspaceで永続化し`vendor/bundle`を参照するようにするための設定
BUNDLE_APP_CONFIG: .bundle
# ref: https://circleci.com/docs/2.0/faq/#how-can-i-set-the-timezone-in-docker-images
TZ: "Asia/Tokyo"
working_directory: ~/dodonki1223/qiita_trend
commands:
save-workspace:
steps:
- persist_to_workspace:
# working_directory からの相対パスか絶対パスを指定します
root: .
paths: .
using-workspace:
steps:
- attach_workspace:
# working_directory からの相対パスか絶対パスを指定します
at: .
collect-reports:
steps:
- store_artifacts:
# カバレッジの結果をcoverage-resultsディレクトリに吐き出す
path: coverage
destination: coverage-results
create-document:
steps:
- run:
name: Create document
command: |
bundle exec yard
- store_artifacts:
# ドキュメントの結果をyard-resultsディレクトリに吐き出す
path: ./doc
destination: yard-results
deploy-rubygems:
steps:
# https://discuss.circleci.com/t/the-authenticity-of-github-host-cant-be-stablished/33133 と同じ現象で job が進まなくなるので以下の記事を参考に実装
# ref:https://circleci.com/docs/ja/2.0/gh-bb-integration/#ssh-%E3%83%9B%E3%82%B9%E3%83%88%E3%81%AE%E4%BF%A1%E9%A0%BC%E6%80%A7%E3%81%AE%E7%A2%BA%E7%AB%8B
- run:
name: Avoid hosts unknown for github
command: |
mkdir -p ~/.ssh
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
' >> ~/.ssh/known_hosts
- run:
name: Deploy RubyGems
command: |
curl -u dodonki1223:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials
chmod 0600 ~/.gem/credentials
git config user.name dodonki1223
git config user.email $RUBYGEMS_EMAIL
bundle exec rake build
bundle exec rake release
deploy-notification:
steps:
- slack/status:
success_message: ':circleci-pass: RubyGemsにデプロイが完了しました\n:github_octocat: User: $CIRCLE_USERNAME'
failure_message: ':circleci-fail: RubyGemsにデプロイが失敗しました\n:github_octocat: User: $CIRCLE_USERNAME'
jobs:
setup:
executor: base
steps:
- checkout
- ruby/install-deps
- save-workspace
lint:
executor: base
steps:
- using-workspace
- ruby/install-deps
- ruby/rubocop-check
test:
executor: base
steps:
- using-workspace
- ruby/install-deps
- ruby/rspec-test:
out-path: 'test_results/rspec/'
- collect-reports
document:
executor: base
steps:
- using-workspace
- ruby/install-deps
- create-document
deploy:
executor: base
steps:
- using-workspace
- ruby/install-deps
- deploy-rubygems
- deploy-notification
workflows:
version: 2.1
main:
jobs:
- setup
- lint:
requires:
- setup
- test:
requires:
- setup
- document:
requires:
- setup
- slack/approval-notification:
message: ':circleci-pass: RubyGemsへのデプロイ準備が整っています\n:github_octocat: User: $CIRCLE_USERNAME\nデプロイを実行する場合は *Approve* を押してください'
requires:
- lint
- test
filters:
branches:
only: master
- approval-job:
type: approval
requires:
- slack/approval-notification
- deploy:
requires:
- approval-job
filters:
branches:
only: master
# 定期でテストを実行する
# ref:https://circleci.com/docs/ja/2.0/triggers/
nightly:
triggers:
- schedule:
cron: "0 22 * * *" # UTCで記述
filters:
branches:
only:
- master
jobs:
- setup
- test:
requires:
- setup
更新内容
Ruby の orb の導入
- circleci/ruby@1.1.2 を使用するように変更
version: 2.1
orbs:
ruby: circleci/ruby@1.1.2
orbs で定義されている command と同等の処理を削除
- Bundler のインストール、 gem のインストールの処理を削除
- 以下の処理は Ruby の orb で定義されているのですべて削除し代替の処理に変更する
install-bundler:
steps:
- run:
name: Install bundler(2.1.0)
command: gem install bundler:2.1.0
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
restore-gem-cache:
steps:
- restore_cache:
keys:
- v1-dependencies-{{ checksum "Gemfile.lock" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
install-gem:
steps:
- run:
name: Install gem
command: |
# jobs=4は並列処理をして高速化するための設定(4つのjobで実行するって意味)
bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
save-gem-cache:
steps:
- save_cache:
paths:
- ./vendor/bundle
key: v1-dependencies-{{ checksum "Gemfile.lock" }}
削除した処理を Ruby の orb の command に変更する
- orb に変更する前と変更後の記述
修正前
jobs:
setup:
executor: base
steps:
- checkout
- install-bundler
- restore-gem-cache
- install-gem
- save-gem-cache
- save-workspace
lint:
executor: base
steps:
- using-workspace
- install-bundler
- run-rubocop
test:
executor: base
steps:
- using-workspace
- install-bundler
- run-tests
- collect-reports
document:
executor: base
steps:
- using-workspace
- install-bundler
- create-document
deploy:
executor: base
steps:
- using-workspace
- install-bundler
- deploy-rubygems
- deploy-notification
修正後
jobs:
setup:
executor: base
steps:
- checkout
- ruby/install-deps
- save-workspace
lint:
executor: base
steps:
- using-workspace
- ruby/install-deps
- run-rubocop
test:
executor: base
steps:
- using-workspace
- ruby/install-deps
- run-tests
- collect-reports
document:
executor: base
steps:
- using-workspace
- ruby/install-deps
- create-document
deploy:
executor: base
steps:
- using-workspace
- ruby/install-deps
- deploy-rubygems
- deploy-notification
最後に
CircleCI で CI/CD を設定して運用してきたが自分の学びが多く、実装してすごく良かったと思う。
個人で CircleCI を運用することはすごく勉強になるので個人的にはすごくオススメします。
これからもこの設定ファイルを運用していき、気になった機能が増えたらすぐに実装していきたいと思います!