LoginSignup
2
3

More than 3 years have passed since last update.

GitHub Actions を使った Rails アプリの自動デプロイを10分で理解する

Last updated at Posted at 2020-11-25

こんにちは、駆け出しエンジニアのよしこ @k2_yoshikoukiです

CI/CDってカッコいいですよね。なんかこう、カッコいいんですよね(語彙力)

しかし「どうやって実装したらいいのかワケワカメ\(^o^)/」というエンジニアの方は多いと思います。でも実際はとても簡単なんだよということを知ってほしかったので、10分で読める記事で CI/CD のうちのCD(自動デプロイ)を実装していきたいと思います。

実作業時間は詰まらなかったら30分かからないくらいです。

ゴール

CI/CD をやってみたいがやったことがないし何から手を付けたら良いか分からないエンジニア向けに、Rails アプリ (6系) で自動デプロイを最速で実装する。

結果、GitHub Actions を使ったCI/CDの大枠を把握できて自力で実装できるようになる

実装フローを見ていく

  1. Rails アプリを作る
  2. Heroku に手動デプロイして動作確認
  3. GitHub Actions の初期設定
    • ./.github/workflows/{好きな名前}.yml の作成
    • 必要な鍵などの取得・GitHubへ設定

すでにアプリケーションがある方は 3 からです。たった2ステップで自動デプロイが実装できます。早速やっていきましょう

手順

Railsアプリの準備

  • rails new sample-rails-with-gha

    ~/tmp/sample-rails-with-gha
    ❯ rails -v
    Rails 6.0.3.4
    
    ~/tmp/sample-rails-with-gha
    ❯ ruby -v
    ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]
    # 後から2.7.2にアップデートします(デバックのため)
    
    bundle install
    rails server
    

    image.png

リポジトリの準備

  • GitHub上にリポジトリを作る
    https://github.com/new
  • ローカルにリポジトリを登録

    git remote add origin https://github.com/yoshikouki/sample-rails-with-gha.git
    

    image.png

    • アップロード

      git add -A
      git commit -m "rails new"
      git push -u origin master
      

デプロイの初期設定と初回デプロイ

  • 今回はデプロイ先に Heroku を使う(簡単なので)

    ~/tmp/sample-rails-with-gha master
    ❯ heroku --version
    
    zsh: command not found: heroku
    
  • Heroku 入ってなかった・・・

    brew tap heroku/brew && brew install heroku
    # https://devcenter.heroku.com/articles/heroku-cli
    
  • Heroku アカウントを作っておく
    https://signup.heroku.com/

  • Heroku にログイン(ターミナル上)

    heroku login --interactive
    
  • Heroku 用のアプリケーションを作る(アップロードする場所を作る)

    heroku create
    # URL を控えておく
    # https://sleepy-beyond-32826.herokuapp.com/
    # `$ heroku open` でも開ける
    

    image.png

  • Heroku は sqlite3 に対応していないため、./Gemfile を操作する

    image.png

  • Heroku へデプロイする

    git push heroku master
    
  • あらら

    image.png

    • エラーログ
    $ heroku logs
    2020-11-22T14:39:05.610528+00:00 app[web.1]: I, [2020-11-22T14:39:05.610419 #4]  INFO -- : [a6b71e5b-f13a-4224-a857-9b791da3ecc4] Started GET "/" for 133.32.232.41 at 2020-11-22 14:39:05 +0000
    2020-11-22T14:39:05.611222+00:00 app[web.1]: F, [2020-11-22T14:39:05.611152 #4] FATAL -- : [a6b71e5b-f13a-4224-a857-9b791da3ecc4]
    2020-11-22T14:39:05.611223+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] ActionController::RoutingError (No route matches [GET] "/"):
    2020-11-22T14:39:05.611224+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4]
    2020-11-22T14:39:05.611225+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] actionpack (6.0.3.4) lib/action_dispatch/middleware/debug_exceptions.rb:36:in `call'
    2020-11-22T14:39:05.611225+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] actionpack (6.0.3.4) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
    2020-11-22T14:39:05.611226+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] railties (6.0.3.4) lib/rails/rack/logger.rb:37:in `call_app'
    2020-11-22T14:39:05.611226+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] railties (6.0.3.4) lib/rails/rack/logger.rb:26:in `block in call'
    2020-11-22T14:39:05.611226+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] activesupport (6.0.3.4) lib/active_support/tagged_logging.rb:80:in `block in tagged'
    2020-11-22T14:39:05.611227+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] activesupport (6.0.3.4) lib/active_support/tagged_logging.rb:28:in `tagged'
    2020-11-22T14:39:05.611227+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] activesupport (6.0.3.4) lib/active_support/tagged_logging.rb:80:in `tagged'
    2020-11-22T14:39:05.611228+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] railties (6.0.3.4) lib/rails/rack/logger.rb:26:in `call'
    2020-11-22T14:39:05.611228+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] actionpack (6.0.3.4) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
    2020-11-22T14:39:05.611228+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] actionpack (6.0.3.4) lib/action_dispatch/middleware/request_id.rb:27:in `call'
    2020-11-22T14:39:05.611229+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] rack (2.2.3) lib/rack/method_override.rb:24:in `call'
    2020-11-22T14:39:05.611229+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] rack (2.2.3) lib/rack/runtime.rb:22:in `call'
    2020-11-22T14:39:05.611230+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] activesupport (6.0.3.4) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
    2020-11-22T14:39:05.611230+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] actionpack (6.0.3.4) lib/action_dispatch/middleware/executor.rb:14:in `call'
    2020-11-22T14:39:05.611231+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] actionpack (6.0.3.4) lib/action_dispatch/middleware/static.rb:126:in `call'
    2020-11-22T14:39:05.611231+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] rack (2.2.3) lib/rack/sendfile.rb:110:in `call'
    2020-11-22T14:39:05.611232+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] actionpack (6.0.3.4) lib/action_dispatch/middleware/host_authorization.rb:76:in `call'
    2020-11-22T14:39:05.611232+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] railties (6.0.3.4) lib/rails/engine.rb:527:in `call'
    2020-11-22T14:39:05.611232+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] puma (4.3.6) lib/puma/configuration.rb:228:in `call'
    2020-11-22T14:39:05.611233+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] puma (4.3.6) lib/puma/server.rb:713:in `handle_request'
    2020-11-22T14:39:05.611233+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] puma (4.3.6) lib/puma/server.rb:472:in `process_client'
    2020-11-22T14:39:05.611233+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] puma (4.3.6) lib/puma/server.rb:328:in `block in run'
    2020-11-22T14:39:05.611234+00:00 app[web.1]: [a6b71e5b-f13a-4224-a857-9b791da3ecc4] puma (4.3.6) lib/puma/thread_pool.rb:134:in `block in spawn_thread'
    2020-11-22T14:39:05.612663+00:00 heroku[router]: at=info method=GET path="/" host=sleepy-beyond-32826.herokuapp.com request_id=a6b71e5b-f13a-4224-a857-9b791da3ecc4 fwd="133.32.232.41" dyno=web.1 connect=1ms service=4ms status=404 bytes=1902 protocol=https
    2020-11-22T14:39:05.858618+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=sleepy-beyond-32826.herokuapp.com request_id=831fe7f9-bc01-496d-a9ac-380c9c89dd3c fwd="133.32.232.41" dyno=web.1 connect=1ms service=2ms status=200 bytes=143 protocol=https
    
    • なるほどねえ(分かっていない) ActionController::RoutingError (No route matches [GET] "/"):
        # ./config/routes
        Rails.application.routes.draw do
          # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
        end
    
    • ないものは作ればいいんだよ(ドヤ顔)

      rails generate controller Home index
      
    • ルーティング ./config/routes もイジる

      image.png

    • よしよし(手動デプロイで動作を確認)

      image.png

GitHub Actions を設定していく

  • 空の設定ファイルを作る

    mkdir -p ./.github/workflows
    tocuh -p ./.github/workflows/sample_cd.yml
    
  • 設定していく

    • 設定ファイル

      name: Deploy to sample-rails-with-gha
      
      on:
        # master ブランチにプッシュされた場合に動作する
        push:
          branches:
            - master
      
      jobs:
        deploy:
          runs-on: ubuntu-latest
          steps:
            # GitHub リポジトリからコードを引っ張ってくる
            - name: Checkout
              uses: actions/checkout@v2
            # 前回のコンテナキャッシュがあれば使用する。なければキャッシュを作る
            - name: Cache multiple paths
              uses: actions/cache@v2
              with:
                path: vendor/bundle
                key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
                restore-keys: |
                  ${{ runner.os }}-gems-
            # Ruby をインストールする
            - name: Set up Ruby 2.7
              uses: actions/setup-ruby@v1
              with:
                ruby-version: 2.7
            # バンドラーをインストールし、初期化する
            - name: Bundle install
              run: |
                gem install bundler
                bundle config path vendor/bundle
                bundle install --jobs 4 --retry 3
            # ヘロクにデプロイする
            - uses: akhileshns/heroku-deploy@v3.6.8 # This is the action
              with:
                heroku_api_key: ${{secrets.HEROKU_API_KEY}}
                heroku_app_name: "sleepy-beyond-32826"
                heroku_email: "yoshikouki@gmail.com"
      
    • 簡単な設定ファイルなので説明はファイル内のコメントを参考にしてください。

      • アクションという Ruby でいう Gem のような機能を使用しています。
    • ドキュメント

    • secrets.HEROKU_API_KEY が必要なので Heroku で取得する

    • 取得した Key をGitHub で使用できるように設定する

      • sample-rails-with-gha のリポジトリ > Settings > Secrets
      • GitHub Actions で使用する非公開環境変数の設定画面になる > New repository secret
      • Name に HEROKU_API_KEY Value に先程Herokuで取得したキーをセット > Add secret
  • 準備は整ったので、master/main ブランチにプッシュしてみる

    デバッグ

    • actions/cache のドキュメントは bundle がインストールしてある前提だったので gem install bundler を追加した
    • Gemfile に記述されている ruby-version と GitHub Actions のコンテナ内のRubyを一致させること

      uses: actions/setup-ruby@v1
      with:
        ruby-version: 2.7
      
      • GitHub Actions setup-ruby ではマイナーバージョンまでしか指定できないみたいなので、手元Rubyのメンテナンス (ビルド) バージョンをあげることになるかもしれない
      • マイナーバージョンが上がるわけではないので、素直に上げておけばいいと思う

そして...

image.png

  • 最後の push を済ませれば・・・

    image.png

  • 感極まる😂

    image.png

まとめ

以上で Rails アプリ (6系) で自動デプロイまでを最速で実装しました。

以後は、master (main) ブランチへ push するだけで heroku へ自動デプロイされます。これで2〜3コマンド分の実行の手間が省けたことになりますし、あなたはもう完全に CI/CD を習得したエンジニアです。

(実際のところ、今回はCI部分を何も扱っていませんし、デプロイに関してもデータベースを触っていないので中途半端な状態ではあるのですが、最低限は実装できたので良しとしましょう。してください。)

参考URL

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3