LoginSignup
10
11

More than 1 year has passed since last update.

【GitHub Actions】ReactプロジェクトのCI/CDパイプラインを構築してみた

Last updated at Posted at 2021-04-03

GitHub Actions学習のまとめとして、Create React AppのプロジェクトのCI/CDパイプラインを構築してみました。

使用したnpmパッケージについては以下の記事でまとめています。

プロジェクトの作成

npx create-react-app react-app --use-npmでプロジェクトを作成します。

ワークフローの構成

Git-flowでの運用を想定して、以下のタイミングで実行するワークフローを作成します。

  1. featureからdevelop向けのプルリクを作成したとき
  2. プルリクが承認されてfeatureがdevelopへマージされたとき
  3. developからmaster向けのプルリクを作成したとき
  4. プルリクが承認されてdevelopがmasterへマージされたとき

スクリーンショット 2021-04-02 22.05.56.png

スクリーンショット 2021-04-02 22.12.45.png

加えて、リリースされたらSlackに通知するワークフローも作成します。

ワークフローの作成

前項の図でワークフローが4つありましたが、これらを1つのymlファイルに記述します。

ワークフロー①の作成(一部分)

まずは①(featureからdevelop向けのプルリクを作成したとき)のワークフローの内容を記述します。

ci.yml
name: CI
on:
  pull_request:
    branches: [develop] #develop向けのプルリクが作成されたときにジョブを実行

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2 #チェックアウトするアクション
      - name: Use NodeJS
        uses: actions/setup-node@v1 #特定バージョンのnodeを設定するアクション
        with:
          node-version: "12.x"
      - run: npm ci #dependencyのインストール
      - run: npm run format:check #コードフォーマットチェック
      - run: npm test -- --coverage #テスト実行
        env:
          CI: true #現在の環境がCI環境であることを仮定

ここではdependencyのインストール、コードフォーマットチェック、テスト実行を記述しています。
CIにおいては、npm installではなくnpm ciでdependencyのインストールを行います。
npm ciでは、依存関係の更新をせずに整合性チェックと依存パッケージのダウンロードのみを行うため、npm installより高速に動作し、CIで必要なことだけを行うことができます。

CI: trueではテストがCI環境で実行されることを仮定しています。

ワークフロー②の作成

developからworkflowというfeatureブランチをきって、git pushしてdevelop向けのプルリクをつくるとワークフローが実行されます。
スクリーンショット 2021-03-28 9.49.35.png

ワークフロー②(プルリクが承認されてfeatureがdevelopへマージされたとき)の内容のステップを追記します。

ci.yml
name: CI
on:
  pull_request:
    branches: [develop]
  push:
    branches: [develop] #developにマージされたときに実行

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Use NodeJS
        uses: actions/setup-node@v1
        with:
          node-version: "12.x"
      - run: npm ci
      - run: npm run format:check
      - run: npm test -- --coverage
        env:
          CI: true
      - name: Build Project #ステージング用のビルドを行うステップ
        if: github.event_name == 'push' #pushイベントのときだけ実行
        run: npm run build #ビルド実行
      - run: npm install -g surge #surgeのインストール
      - name: Deploy to Staging #ステージングデプロイを行うステップ
        if: github.event_name == 'push' #pushイベントのときだけ実行
        run: npx surge --project ./build --domain awesome-quiet.surge.sh #デプロイ
        env: #surgeの認証
          SURGE_LOGIN: ${{ secrets.SURGE_LOGIN }} #surge whoamiで取得
          SURGE_TOKEN: ${{ secrets.SURGE_TOKEN }} #surge tokenで取得

developへのマージをトリガにするために、develop向けのpushイベントを追加します。
また、ワークフローは①と②で共有されているので、ビルドやデプロイがpull_requestイベントで実行されないように、if: github.event_name == 'push'という実行条件を追加します。

今回、デプロイにはsurgeというnpmパッケージを使用しています。ログイン名とパスワード(token)を予め作成して、GitHubリポジトリのsecretsに環境変数として登録しておきます。

ワークフローの実行内容を確認すると、developへのプルリク時点ではbuild, deployステップを飛ばしています。
スクリーンショット 2021-03-28 10.33.37.png

developへマージ(push)するとbuild, deployが実行されています。
スクリーンショット 2021-03-28 10.49.50.png

dependencyのキャッシュ

ワークフローごとにnpm ci行うのは無駄なので、dependenciesのキャッシュ用のアクションをステップに追加します。

    steps:
      - uses: actions/checkout@v2
      - name: Cache node_modules
        uses: actions/cache@v1
        with:
          path: ~/.npm #キャッシュしたファイルとキーを格納する場所(OSによって異なる)
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} #キャッシュのリストアや保存をするためのキー
          restore-keys: | #キャッシュをリストアするためのキーのリスト
            ${{ runner.os }}-node-

hashFilesを使用することで、depencencyに変更があったときに新しいキャッシュをつくることができます。

最初のワークフローを実行すると、以下のようにキーが生成されます。
スクリーンショット 2021-03-28 21.11.23.png

Artifact(テストカバレッジ、ビルドファイル)のアップロード

テストとビルドの後にGitHubのActionsタブからArtifactをダウンロードできるようにするため、これらをアップロードするアクションをステップを追加します。

ci.yml
      - run: npm test -- --coverage
        env:
          CI: true
      - name: Upload Test Coverage
        uses: actions/upload-artifact@v1 #artifactをアップロードするアクション
        with:
          name: code-coverage #ダウンロード時の表示名
          path: coverage #アップロードするフォルダのパス
      - name: Build Project
        if: github.event_name == 'push'
        run: npm run build
      - name: Upload Build Coverage
        if: github.event_name == 'push'
        uses: actions/upload-artifact@v1
        with:
          name: build
          path: build

ワークフローを実行すると以下のようにArtifactがアップロードされます。
スクリーンショット 2021-03-28 21.55.09.png

masterにマージされたときだけ実行するステップ

ワークフロー④(プルリクが承認されてdevelopがmasterへマージされたとき)のときだけ実行されるステップを作成します。

リリースの作成

masterにマージされたときにリリースを作成するステップを追加します。
リリースの作成にはsemantic-releaseを使います。

ci.yml
      - name: Create a Release
        if: github.event_name == 'push' && github.ref == 'refs/heads/master'
        run: npx semanic-release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

また、リリースの画面からbuild.zip, coverage.zipをダウンロードできるようにします。

ci.yml
      - name: ZIP Assets
        if: github.event_name == 'push' && github.ref == 'refs/heads/master'
        run: |
          zip -r build.zip ./build
          zip -r coverage.zip ./coverage

リリースの設定は以下のようになります。

release.config.js
module.exports = {
  branches: "master",
  repositoryUrl: "https://github.com/suzuki0430/react-app",
  plugins: [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    [
      "@semantic-release/github",
      {
        assets: [
          {path: "build.zip", label: "Build"},
          {path: "coverage.zip", label: "Coverage"},
        ],
      },
    ],
  ],
};

codecovへのテストカバレッジのアップロード

codecovはコードのカバレッジを計測し、可視化したりslackに通知したりできる外部サービスです。
envでcodecovで作成したTOKENを指定するだけで、カバレッジレポートをアップロードすることができます。

ci.yml
      - name: Upload Coverage Reports
        if: github.event_name == 'push' && github.ref == 'refs/heads/master'
        run: npx code-coverage
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

Slack通知用のワークフローの作成

リリースが作成されたときにSlack通知を行うワークフローを作成します。
ci.ymlのCreate releaseステップをトリガにするため、CUSTOM_TOKENを新しくつくります。

スクリーンショット 2021-03-29 21.27.59.png

リリースの作成(published)をトリガにしたワークフローを以下のように作成します。

release.yml
name: Notify on Release
on:
  release:
    types: [published]

jobs:
  slack-message:
    runs-on: ubuntu-latest
    steps:
      - name: Slack Message
        run: |
          curl -X POST -H 'Content-type: application/json' --data '{"text":"New release ${{ github.event.release.tag_name }} is out, <${{ github.event.release.html_url }}|check it out now.>"}' ${{ secrets.SLACK_WEBHOOK }}

おわりに

GitHub Actionsの使い方が大体わかったので、今度は社内業務で役に立つようなワークフローを作成してみたいと思います。

参考資料

10
11
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
10
11