RubyGemsリリースを自動化した話


TL;DR

Github上でv1.2.3のようなreleaseタグを作るだけで、
あとはCircleCIが自動で
version.rbの更新→Gemビルド→RubyGemsへリリースする仕組みを作りました。
サンプルはこちらにあります。
https://github.com/NA070/release_test

RubyGems公開手順

RubyGems公開には以下の手順が必要です。

  1. RubyGems APIキーを~/.gem/credentialsへ書き込む
  2. ./lib/{package_name}/version.rbの更新( 更新箇所: VERSION = '1.2.3'
  3. gemのパッケージ化 ( コマンド例: gem build package_name.gemspec )
  4. RubyGemsでの公開 ( コマンド例: gem push package_name-1.2.3.gem)

運用の要求

releaseタグを使って管理したいという要求がありました。
理由としては以下の要点があります

  • 更新内容を明記したい
    • masterブランチが更新されるたびにリリースすることもできるがそれだと更新内容がわかりづらい
    • releaseごとの更新情報を管理できない
  • コード実装完了=リリースしてOKではない
    • ドキュメント更新がある場合もあるので、それも整備し終えてからリリースしたい
    • masterブランチ更新でリリースだと↑は満たされない

自動化したフロー

releaseタグ作成を入れて、自動化した公開手順は以下です。

※ 1だけ手動であとは自動実行されます。
1. 新しいreleaseタグをgithub上で作成
2. ./lib/{package_name}/version.rbのバージョンナンバー更新
3. masterブランチへpush
4. gemのパッケージ化
5. RubyGemsでの公開

次にどのように自動化しているかを説明していきます

設定方法

CircleCIを使って自動化しました。
設定を進める前に空のジョブでいいので、リポジトリとCircleCIを連携させておく必要があります。

① RubyGemsのAPIキーをCircleCIプロジェクトの環境変数に設定する

CicleCIのプロジェクトセッティングから環境変数を設定します。
サンプルではRUBYGEMS_API_KEYとしました。
APIキーはRubygemsのプロフィール編集ページで確認できます。(要ログイン)

② Checkout SSH keysに鍵を追加する

version.rbを更新したあとにリポジトリへpushsする必要があります。
そのためにwrite権限が必要です。

  1. Githubの認証を許可します

  2. 鍵を作成します

    追加されました!

③ CircleCIの設定ファイルを追加

リポジトリへpushするための設定は add_ssh_keys で設定します。
先程追加したsshキーのfinger printを記述します。

version: 2
jobs:
  publish:
    docker:
      - image: circleci/ruby:2.4.1
    steps:
      - add_ssh_keys:
          finerprints:
            - "b8:3b:3a:5b:4b:0b:50:73:bf:92:e0:e3:ac:00:01:c1"
      - checkout
      - run:
          name: Setup Rubygems
          command: bash .circleci/setup_rubygems.sh
      - run:
          name: Update vresion.rb and publish on RubyGems
          command: bash .circleci/deploy_to_rubygems.sh
workflows:
  version: 2
  deploy:
    jobs:
      - publish:
          filters:
            tags:
              only: /^v[0-9]{1,}(\.[0-9]{1,}){2}$/
            branches:
              ignore: /.*/

④ ジョブで使うshellスクリプトを追加

1. RubyGemsのcredentialファイル作成処理

環境変数 $RUBYGEMS_API_KEY に設定されたAPIキーをファイルへ書き込みます。
https://github.com/NA070/release_test/blob/master/.circleci/setup_rubygems.sh

mkdir ~/.gem
echo -e "---\r\n:rubygems_api_key: $RUBYGEMS_API_KEY" > ~/.gem/credentials
chmod 0600 /home/circleci/.gem/credentials

2. version.rb更新→gemビルド→gem pushする処理

役割が多いですが、1ファイルにしています。(責任が多いので分けるのが良いかもです。)
↓では説明のために分割しています。

タグを取得します。
また、git操作するための設定を行います。
メールアドレスにはgithubが用意しているダミーアドレスを使いました。
(参考:https://help.github.com/en/articles/about-commit-email-addresses)


VERSION=$(git describe --tags | sed -e 's/^v//')
git config user.email "[email protected]"
git config user.name "2687752+NA070"

version.rbを更新し、commitします。

# Update version.rb
sed -i '' -e "s/VERSION = '[0-9]\{1,\}.[0-9]\{1,\}.[0-9]\{1,\}'/VERSION = '$VERSION'/" lib/release_test_nao/version.rb
git diff
git checkout master
git add lib/release_test_nao/version.rb
git commit -m "Version $VERSION"

ビルドし、gem push(RubyGemsへリリース)します

# Build and release gem
gem build release_test_nao.gemspec
gem push "release_test_nao-$VERSION.gem"

最後にリポジトリへpushします。
最後に行うのはそれまでの処理で何らかのエラーがあった場合に誤った状態でのpushを防ぐためです。


# Push to master
git push origin master

設定は以上です。

リリースしてみる

リリースタグを作ります。


v0.1.32 でリリースします。


こんな感じにログが出ます。

無事リリースされました!(この記事を書いたあとにRubyGemsからは削除したので現在は見れません)

リポジトリにもpushされています。

無事うまくいきました。
要求を満たした自動化が実現できました

実現はできたもののの、OSSの経験が少ないので、何が最適なのかは探求する必要がありそうです。
アドバイスなどがありましたらコメントいただけると嬉しいです。

参考にさせていただいた記事