はじめに
基幹システムグループ 湊谷です。
突然ですが、皆さんGithub Actionsって使っていますか?
GitHub Actions は、ビルド、テスト、デプロイのパイプラインを自動化できる継続的インテグレーションと継続的デリバリー (CI/CD) のプラットフォームです。 リポジトリに対するすべての pull request をビルドしてテストしたり、マージされた pull request を運用環境にデプロイしたりするワークフローを作成できます。
https://docs.github.com/ja/actions/learn-github-actions/understanding-github-actions
私の所属しているチームではCI/CDツールとして使ったり、プルリクエスト作成時に自動でテストを走らせたり、Issueを作成したら特定のプロジェクトに紐づけたり、と多くの面で活用しています。
「プルリクエストを作成した時にESLintを実行し、引っかかったらプルリクエストを承認できないようにする」というワークフローを作成していたのですが、一つ気になる点がありました。Github Actionsの仕様として、Warningが出た場合も失敗扱いにはならず、StatusはSuccessとなります。そのため、プルリクエストも承認できてしまいます。
eslintコマンドには–max-warningsというオプションが用意されており、これに0を指定して実行すると「出て良いWarningの数は0=一つもWarningを許容しない」となり、ESLintの実行結果もFailureとなります。
しかし、その様なオプションが無い場合や、Warning以外にも特定の文字列が出力されている時にそれを検知する方法はあるのか?と疑問に思ったため、Github Actionsの中でやる方法を探してみました。
特定の文字列を含む時にエラーになるようにする
コードの完成形を見てみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
name: pr-test on: pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [16.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: npm ci run: npm ci - name: npm run build run: npm run build --if-present - name: npm test run: npm test - name: npm run lint id: lint run: | result=$(npm run lint | tr '\n' ' ') echo "result=$result" >> $GITHUB_OUTPUT echo "$result" | tr ' ' '\n' - name: check lint if: contains(steps.lint.outputs.result, 'Warning') run: | echo 'lintでWarningが出ています。修正をお願いします' exit 1 |
色々なことをやっていますが、今回関わってくるのは以下の部分です。
1 2 3 4 5 6 7 8 9 10 11 |
- name: npm run lint id: lint run: | result=$(npm run lint | tr '\n' ' ') echo "result=$result" >> $GITHUB_OUTPUT echo "$result" | tr ' ' '\n' - name: check lint if: contains(steps.lint.outputs.result, 'Warning') run: | echo 'lintでWarningが出ています。修正をお願いします' exit 1 |
まず、name: npm run lintのジョブではESlintを実行しています。
ESLintを実行した結果をresultに入れます。改行があると最初の一行しか取得できなかったため、改行を無くしています。
1 |
result=$(npm run lint | tr '\n' ' ') |
ESLintの結果を後続のジョブで使うため、$GITHUB_OUTPUT
で値をセットします。
1 |
echo "result=$result" >> $GITHUB_OUTPUT |
そして、ESLintを実行結果も確認したいため、出力します。改行が無いと読みづらいため元に戻しています。
1 |
echo "$result" | tr ' ' '\n' |
次に、name: check lintのジョブではESLintの実行結果をチェックしています。
今回は、ESLintの結果にWarningの文字列があったらエラーを返すようにし、ワークフローを失敗としましょう。
contains( search, item )を使います。searchの中にitemがあればtrueを返し、そうでない場合はfalseを返します。
1 |
if: contains(steps.lint.outputs.result, 'Warning') |
「id:lintで指定したstepsの中のoutputsの中にセットしたresultの値の中にWarningが入っている場合」という条件を設定し、trueであればrun以降書かれた内容を実行します。
今回は「lintでWarningが出ています。修正をお願いします」という文章を出力し、exit 1を実行してジョブを終了させています。
実際に、ESLintを実行した際にWarningが出るようなファイルをわざと用意すると、以下のようになります。
ESLintを実行したところでは失敗とはなりませんが、その後のWarningが含まれているかどうかチェックするところで失敗となり、修正しないとプルリクエストを承認できない状態にできました!
最後に
今回は「特定の要素が含まれているかどうか」をチェックするcontainsを使ってみました。
これを使うと「ブランチ名に特定の文字列が含まれている場合」だけジョブを実行したい、といったこともできそうです。もっとGithub Actionsを活用していきたいです!