[GitHub] Dependabot security updatesのPull Requestが未CloseならCI/CDをFailさせる

2022.05.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、CX事業本部 IoT事業部の若槻です。

前回は、Dependabot security updatesがOpenしたPull Requestを自動でMergeする方法を確認しました。

しかし、修正をMergeは自動で行いたくないが、脆弱性を含んだコードを本番環境やステージング環境へリリースはさせたくないので、未CloseならCI/CDをFailさせたい、という場合もあるかと思います。

今回は、GitHubでDependabot security updatesのPull Requestが未Close(Open中)ならCI/CDをFailさせる方法を確認してみました。

やってみる

RepositoryのPull Requestには、下記のようにユーザーが機能開発のためにOpenしたものと、DependabotがOpenしたものが混在することになります。

よって下記のような処理をCI/CDで実装する必要があります。

  1. DependabotがOpenしたPull Requestの一覧を取得する
  2. 上記が1個以上あればNon-Zero Exit Codeを出力する

1.については、GitHub CLIを次のように使用すれば取得できます。

$ gh pr list --author app/dependabot

Showing 1 of 1 pull request in cm-rwakatsuki/aws-cdk-app that matches your search

#1  Bump moment from 2.24.0 to 2.29.2  dependabot/npm_and_yarn/moment-2.29.2

取得結果のPull Request数のカウントは、jsonオプションとjqを使えばできます。

# jsonオプションを指定すればJson形式で出力される
$ gh pr list --author app/dependabot --json title
[
  {
    "title": "Bump moment from 2.24.0 to 2.29.2"
  }
]

# Json形式の出力に対して、jqを使ったカウントを行う
$ dependabot_pr_length=$(gh pr list -l dependencies --json title | jq '. | length')
$ echo $dependabot_pr_length
1

CI/CD Workflow(GitHub Actions)の作成

次のようなWorkflow Config fileを作成します。今回はGitHub Actionsのものです。

.github/workflows/check-dependabot-alert.yml

on: push

jobs:
  dependabot_alert_check:
    runs-on: ubuntu-latest
    steps:
      - name: Count Unclosed Pull Request
        id: id_count_unclosed_pr
        env:
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
        run: |
          unclosed_pr_length=$(gh pr list --repo $GITHUB_REPOSITORY --author app/dependabot --json title | jq '. | length')
          echo "::set-output name=unclosed_pr_length::$unclosed_pr_length"

      - name: Fail Workflow Run
        if: ${{ steps.id_count_unclosed_pr.outputs.unclosed_pr_length != 0 }}
        run: exit 1

  # some_ci_cd_job:
  • 最初のStepでは、Dependabot security updatesの未CloseのPull Request数を取得してOutputしています。
  • 次のStepでは、前StepのOutputが0以外なら、Non-Zero Exit Codeを出力してWorkflowをFailさせるようにしています。

動作確認

Dependabot security updatesのPull Requestが1つ以上未Closeの場合。

Non-Zero Exit Codeが出力され、Workflow実行をFailさせられました。

Dependabot security updatesのPull Requestが1つもOpen中でない場合。

Workflow実行はSuccessしました!

ハマった箇所

DependabotがOpenしたPull Requestのみを取得する方法

DependabotがOpenしたPull Requestのauthor.dependabotは、CLIで確認するとdependabotとなっています。

$ gh pr list --json title,author
[
  {
    "author": {
      "login": "cm-rwakatsuki"
    },
    "title": "機能hoge追加"
  },
  {
    "author": {
      "login": "dependabot"
    },
    "title": "Bump moment from 2.24.0 to 2.29.2"
  }
]

ユーザー(cm-rwakatsuki)がOpenしたPull Requestのみを取得したいなら、次のようにAuthorオプションを使用します。

$ gh pr list --author "cm-rwakatsuki"

Showing 1 of 1 pull request in cm-rwakatsuki/aws-cdk-app that matches your search

#6  機能hoge追加  feature/hoge1

同じ要領で、DependabotがOpenしたPull Requestのみを取得できそうですが、Authorオプションにdependabotと指定したも取得できませんでした。

$ gh pr list --author dependabot

No pull requests match your search in cm-rwakatsuki/aws-cdk-app

結論としては、app/dependabotと指定すれば取得できました。

$ gh pr list --author app/dependabot

Showing 1 of 1 pull request in cm-rwakatsuki/aws-cdk-app that matches your search

#1  Bump moment from 2.24.0 to 2.29.2  dependabot/npm_and_yarn/moment-2.29.2

結構ハマりましたが、Pull Requestの画面でDependabotのアカウントにマウスフォーカスすると`https://github.com/**app/dependabot**`となっていたため、気づくことが出来ました。

GitHub Actions上でのGitHub CLI実行ではRepositoryを明示的に指定する必要がある

ローカルRepository内で実行した時はえらーとならなかったgh pr listコマンドをGitHub Actions上で実行すると、次のようなエラーとなりました。

fatal: not a git repository (or any of the parent directories): .git
/usr/bin/git: exit status 128
Error: Process completed with exit code 1.

これはRunner環境がRepositoryではない(.gitが無い)ためです。よって、gh pr list --repo $GITHUB_REPOSITORYのようにRepoオプションで対象Repositoryを明示的に指定する必要がありました。

GraphQL APIを直接叩けばPull Requestで判断する必要が無くなりそう

もしDependabot version updates(非セキュリティのアップデート)も有効であれば、Dependabot security updatesがOpenしたPull Requestとの区別が付かないため、双方を有効にしている場合後者のみ今回のFailの対象にしたいなら何らかの工夫が必要です。GitHub CLIでDependabotのAPIが叩ければよいのですが、それが可能なサブコマンドは無さそうでした。

ただ調べてみるとGraphQL APIであればDependabotのAPIを叩くことが出来そうでした。場合によってはこちらの利用を検討すると良さそうです。

追記:下記試してみました。

参考

以上