【Github】reviewdog ~ 入門編 ~

■ はじめに

reviewdog を触ってみる

目次

【1】reviewdog
【2】reviewdog の使い方
 1)環境変数「REVIEWDOG_GITHUB_API_TOKEN」
 2)Github Actions への実装 ~ 基本 ~
【3】reviewdog コマンド
【4】サンプル
 例1:Hello world

【1】reviewdog

作者の方のブログ より抜粋

http://haya14busa.com/reviewdog/

linter などのチェックツールの結果を自動で GitHub の Pull Request にコメントしたり
ローカルでも diff の結果から新たに導入されたエラーだけを表示するように
フィルタリングできるツール

Github
https://github.com/orgs/reviewdog/repositories?type=all

【2】reviewdog の使い方

1)環境変数「REVIEWDOG_GITHUB_API_TOKEN」

* GITHUB_TOKEN シークレットを 
 環境変数「REVIEWDOG_GITHUB_API_TOKEN」に設定
* その際、「permissions」で「pull-requests: write」を付加しておく
 => GITHUB_TOKEN の詳細については、以下の関連記事を参照のこと

https://dk521123.hatenablog.com/entry/2024/04/22/221027

サンプル

jobs:
  demo-pull-request:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      env:
        REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - uses: reviewdog/action-setup@v1
        with:
          reviewdog_version: latest

2)Github Actions への実装 ~ 基本 ~

* 基本は、以下の2Stepで使える
 => この方法以外もある(詳細は、以下の関連記事を参照)

https://dk521123.hatenablog.com/entry/2024/04/18/161200
Step1: Install reviewdog

      - uses: reviewdog/action-setup@v1
        with:
          reviewdog_version: latest

Step2: Run linter(s) and reviewdog

      - name: Lint with pylint
        run: |
          pylint --rcfile=~/.pylintrc *.py | reviewdog -efm="%f:%l:%c: %m" -reporter=github-pr-review

[a] -efm: errorformat

* 今回は、Input Format の内の「errorformat」を使っている

https://github.com/reviewdog/reviewdog?tab=readme-ov-file#errorformat

-efm="%f:%l:%c: %m"
 => {file}:{line number}:{column number}: {message}
 => 以下「pylint のエラーメッセージ例」と比較すると分かりやすいかも

pylint のエラーメッセージ例

demo1.py:5:0: C0304: Final newline missing (missing-final-newline)

[b] -reporter: Reporter
https://github.com/reviewdog/reviewdog?tab=readme-ov-file#reporters

* -reporter=local: Local
* -reporter=github-pr-check: GitHub Checks
* -reporter=github-check: GitHub Checks
* -reporter=github-pr-review: GitHub PullRequest review comment
* -reporter=gitlab-mr-discussion: GitLab MergeRequest discussions
* -reporter=gitlab-mr-commit: GitLab MergeRequest commit
* -reporter=bitbucket-code-report: Bitbucket Code Insights Reports

【3】reviewdog コマンド

* reviewdog コマンドについては、資料がないので、
 「reviewdog -help」や「reviewdog -list」をみた方がいい

reviewdog -help

reviewdog -list

reviewdog -name="sqlfluff" -tee -fail-on-error -f=rdjson -reporter=github-pr-review
Options Explanations
-name="Name" ツール名を指定する
-tee tee コマンド(標準出力+ファイル出力)を指定
-fail-on-error WARNING/ERROR時にexitコードで「1」を返す
-f ="FormatName" フォーマット名(reviewdog -listで確認)を指定
-efm="ErrorFormat" エラーフォーマットを指定 (e.g. %f:%l:%c: %m)
-reporter="Reporter" どういう出力にするかを指定

【4】サンプル

例1:Hello world

.github/workflows/demo_reviewdogs.yml

name: DemoForReviewdogs

on:
  - pull_request
env:
  REVIEWDOG_GITHUB_API_TOKEN: "${{ secrets.REVIEWDOG_GITHUB_API_TOKEN }}"
jobs:
  demo-job:
    name: lint
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      env:
        REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Run checkout
        uses: actions/checkout@v4
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
            python-version: '3.10'
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pylint
          pylint --generate-rcfile > ~/.pylintrc
      # Step1: Install reviewdog
      - uses: reviewdog/action-setup@v1
        with:
          reviewdog_version: latest
      # Step2: Run linter(s) and reviewdog
      - name: Lint with pylint
        run: |
          pylint --rcfile=~/.pylintrc *.py | reviewdog -efm="%f:%l:%c: %m" -reporter=github-pr-review

demo.py

def func(is_true):
    if is_true:
        return 'Hello world!'
    else:
        return None

参考文献

https://buildersbox.corp-sansan.com/entry/2023/12/13/110000
https://kujilabo.com/2023/03/13/2023/03/python_003/

関連記事

reviewdog ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2024/04/18/161200
reviewdog ~ RDFormat ~
https://dk521123.hatenablog.com/entry/2024/04/19/121312
Github ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2019/07/18/234652
Github Actions ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2021/11/04/142835
Github Actions ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2022/06/16/151443
Github Actions ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2023/12/22/195715
Github Actions ~ pull_request / pull_request_target ~
https://dk521123.hatenablog.com/entry/2024/04/10/152101
Github Actions ~ Python関連 ~
https://dk521123.hatenablog.com/entry/2022/06/21/143624
Github Actions ~ GITHUB_TOKEN / permissions ~
https://dk521123.hatenablog.com/entry/2024/04/22/221027
GitHub CLI ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2024/02/17/233836
Python解析ツール ~ Ruff ~
https://dk521123.hatenablog.com/entry/2024/03/13/000021

【Github】Github Actions ~ pull_request / pull_request_target ~

■ はじめに

https://dk521123.hatenablog.com/entry/2024/01/28/004128

の続き。

仕事で、Github の プルリクエストが発行された際に
Linter を起動してほしいってオーダーを受けたので
on: pull_request 周辺について調べてみた

目次

【1】プルリク契機のイベント
 1)補足:pull_request_target に関する詳細
【2】構文
 1)types
【3】判定
 1)プルリクかどうかを判定するには
 2)Draft プルリクかどうかを判定するには
【4】サンプル
 例1:プルリク時にSQL linter を実行
 例2:差分だけをLintする(案1)
 例3:差分だけをLintする(案2)

【1】プルリク契機のイベント

# Events Explanations Comments
1 pull_request プルリクのアクティビティが発生した時
2 pull_request_comment プルリクのコメントが作成/編集/削除された時
3 pull_request_review プルリクのレビューが送信/編集/無視された時
4 pull_request_review_comment プルリクのレビューコメントが変更された時
5 pull_request_target プルリクのアクティビティが発生した時 「1)pull_request_target に関する詳細」参照

1)補足:pull_request_target に関する詳細

https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#pull_request_target

* pull request のベースのコンテキストで実行
 => 以下を避けられる
 + リポジトリを変更
 + ワークフローで使うシークレットを盗む
 + pull request の head から安全ではないコードが実行される

* ワークフローでは、pull request に対するラベルやコメントなどを
 フォークから行うことができる

pull_request vs pull_request_target

pull_request pull_request_target Comments
フォークしたリポジトリにも書き込み権限・Secretsを渡さない フォークしたリポジトリにも書き込み権限・Secretsを渡す フォーク 元で設定している secrets にアクセスできないとGITHUB_TOKEN / SLACK_TOKENを参照できない

使用上の注意

* pull request からコードをビルドまたは実行する必要がある場合は、
 このイベントを使わない

【2】構文

on:
  pull_request:
    types:
      - opened
      - reopened
      - synchronize
    branches:
      # プルリクエストのマージ対象がmainの場合実施
      - 'main'
    # ブランチ除外
    #branches-ignore:
    #  - 'mona/octocat'
    paths:
      # pull request に SQLファイル (.sql) への変更が含まれているときに実行
      - '**.sql'
    # paths-ignore:
    #   - 'tests/**.sql'

https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#running-your-pull_request-workflow-based-on-the-head-or-base-branch-of-a-pull-request
https://docs.github.com/ja/actions/using-workflows/triggering-a-workflow#using-filters-to-target-specific-branches-for-pull-request-events

1)types

* デフォルトは、『types: [ opened, synchronize, reopened ]』

主なTypes

types Explanations
opened プルリク(Draft pull-requestを含む)が発行時
reopened プルリク(Draft pull-requestを含む)が再Open時
synchronize プルリクにコミットが追加された時
ready_for_review プルリクが Draft から Open になった時

【3】判定

* Reusable Github workflow を使う際に、
 プルリクかどうかを判定する必要があったのでメモ。 

1)プルリクかどうかを判定するには

github.event_name == 'pull_request'

2)Draft プルリクかどうかを判定するには

github.event.pull_request.draft == true

【4】サンプル

例1:プルリク時にSQL linter を実行

Github Actions ~ SQL Linter ~
https://dk521123.hatenablog.com/entry/2024/03/04/180308

name: DemoForPullRequest

on:
  pull_request_target:
    types:
      - opened
      - reopened
      - synchronize
    paths:
      - '**.sql'
jobs:
  sample-job:
    runs-on: ubuntu-latest
    steps:
      - name: Run checkout
        uses: actions/checkout@v4
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
            python-version: '3.10'
      - name: install SQLFluff
        run: 'pip install sqlfluff'
      - name: format
        run: |
          for file in 'sqls/*.sql' 
          do
            sqlfluff lint $file --dialect snowflake --format github-annotation
          done

例2:差分だけをLintする(案1)

* 以下のサイトの方法を参考に実装。

https://qiita.com/kenz_firespeed/items/b37a6a1a7f0aff931c7c

name: DemoForPullRequest

on:
  pull_request:
    types:
      - opened
      - reopened
      - synchronize
    paths:
      - '**.sql'
env:
  base_branch: develop
jobs:
  lint-job:
    runs-on: ubuntu-latest
    steps:
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
            python-version: '3.10'
      - name: install SQLFluff
        run: 'pip install sqlfluff'
      - name: Switch to pull request branch
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - name: Fetch base branch
        run: git fetch origin ${base_branch}:${base_branch}
      - name: Run actions using diff_files
        run: |
          diff_files=$(git diff --name-only HEAD ${base_branch} -- "sqls/**.sql" \
            | tr "\n" " ")
          echo "- diff_files: ${diff_files}"

          for file in ${diff_files}
          do
            echo "- target_file: ${file}"
            sqlfluff lint $file --dialect snowflake --format github-annotation-native
          done

補足1:github.event.pull_request.head.sha
https://docs.github.com/ja/actions/using-workflows/events-that-trigger-workflows#pull_request

より抜粋
~~~~~~~~~~~~~
pull request の head ブランチへの最後のコミットのコミット ID を取得する場合は、
代わりに github.event.pull_request.head.sha を使います
~~~~~~~~~~~~~

補足2:git diff コマンド

* 以下の関連記事を参照のこと

Git ~ 基本編 / 基本コマンド ~
https://dk521123.hatenablog.com/entry/2020/10/02/000000

例3:差分だけをLintする(案2)

* 以下のサイトの方法を参考に実装。
 => 案1との主な変更点は、★部分参照。

https://zenn.dev/snowcait/articles/6d207409cb1be0

name: DemoForPullRequestV2

on:
  pull_request:
    types:
      - opened
      - reopened
      - synchronize
    paths:
      - '**.sql'
env:
  base_branch: develop
jobs:
  lint-job:
    runs-on: ubuntu-latest
    steps:
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
            python-version: '3.10'
      - name: install SQLFluff
        run: 'pip install sqlfluff'
      - name: Switch to pull request branch
        uses: actions/checkout@v4
        with:
          # ★1:分岐を特定するために fetch-depth: 0 で履歴をすべて取得する必要があ
          fetch-depth: 0
      - name: Run actions using diff_files
        run: |
          # ★2:...: 分岐からの差分(ベースブランチの変更が含まれない = PR の Files changed)
          diff_files=$(git diff --name-only origin/${base_branch}...origin/${GITHUB_HEAD_REF} -- "sqls/**.sql" \
            | tr "\n" " ")
          echo "- diff_files: ${diff_files}"

          for file in ${diff_files}
          do
            echo "- target_file: ${file}"
            sqlfluff lint $file --dialect snowflake --format github-annotation-native
          done

補足3: fetch-depth
https://dk521123.hatenablog.com/entry/2022/06/16/151443

より抜粋
~~~~~~~~~~~~~~~~~~~~~
* 0 は、全てのブランチ・タグの全ての履歴を取得することを意味する
* Default: 1 (最新のコミットのみを取得する)
~~~~~~~~~~~~~~~~~~~~~

ex. Fetch all history for all tags and branches
https://github.com/actions/checkout?tab=readme-ov-file#fetch-all-history-for-all-tags-and-branches

- uses: actions/checkout@v4
  with:
    fetch-depth: 0

参考文献

https://qiita.com/Soh1121/items/b2bc51afc933c910806c
https://til.toshimaru.net/2021-12-12
https://madogiwa0124.hatenablog.com/entry/2022/05/29/110148
https://pankona.github.io/blog/2021/03/29/github-actions-pull-request-target/

関連記事

Github Actions ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2021/11/04/142835
Github Actions ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2022/06/16/151443
Github Actions ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2023/12/22/195715
Github Actions ~ あれこれ編 ~
https://dk521123.hatenablog.com/entry/2023/12/21/155224
Github Actions ~ GITHUB_ENV ~
https://dk521123.hatenablog.com/entry/2023/12/29/000840
Github Actions ~ GITHUB_OUTPUT ~
https://dk521123.hatenablog.com/entry/2024/01/30/002943
Github Actions ~ ワークフロー制御 ~
https://dk521123.hatenablog.com/entry/2024/01/28/004128
Github Actions ~ SQL Linter ~
https://dk521123.hatenablog.com/entry/2024/03/04/180308
SQL Linter ~ SQLFluff ~
https://dk521123.hatenablog.com/entry/2024/02/28/225002
reviewdog ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2024/04/13/232832
Git ~ 基本編 / 基本コマンド ~
https://dk521123.hatenablog.com/entry/2020/10/02/000000

【AWS】Amazon ECR ~ pull through cache rules ~

■ はじめに

https://dk521123.hatenablog.com/entry/2024/04/08/184035

の続き。

現状 ECR Public の VPC エンドポイントは未サポートのため
AWS ECR Public Gallery 内のDockerイメージを
VPC エンドポイント経由で Pull はできない(※1)。

そこで、「pull through cache rules(プルスルーキャッシュルール)」
を使えば、VPC エンドポイント経由でもパブリックイメージを
Pullできそうなので調べてみた

※1:ECR Public の VPC エンドポイント未サポート
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/vpc-endpoints.html

より抜粋
~~~~~~~~~
現在、VPC エンドポイントは Amazon ECR パブリックリポジトリをサポートしていません。
プルスルーキャッシュルールを使用して、VPC エンドポイントと同じリージョンにある
プライベートリポジトリでパブリックイメージをホストすることを検討してください。
詳細については、「プルスルーキャッシュルールの使用」を参照してください。
~~~~~~~~~

目次

【1】pull through cache rules
【2】設定方法
 1)「Pull through cache」の設定手順
 2)「Permissions」の設定手順
 3)docker pull までの流れ
【3】使用上の注意

【1】pull through cache rules

* プルスルーキャッシュルールを使用すると、
 AWS ECR Public/Docker HubなどのDockerイメージを
 Amazon ECR プライベートレジストリに同期できる

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/pull-through-cache.html
https://aws.amazon.com/jp/about-aws/whats-new/2021/11/amazon-ecr-cache-repositories/

【2】設定方法

* AWSServiceRoleForECRPullThroughCache ロールが必要

1)「Pull through cache」の設定手順

[1] AWS Management Console にログイン
[2] 「Elastic Container Registry」(Amazon ECR)のページに移動
[3] 「Private registry」欄 の [Settings]を選択
[4] 「Pull through cache」欄 の [Edit]を選択
[5] 「Pull through cache configuration」ページ の「Add rule」ボタン押下
[6] 「Specify a source」ページ で「Upstream source registry」を選択し
 (ここでは「ECR public」)「Next」ボタン押下
[7] 「Specify a destination」ページ で「Amazon ECR repository namespace」の
 「Amazon ECR repository prefix」を入力し(ここでは「ecr-public」)
 「Next」ボタン押下
[8] 「Create」ボタン押下

AWS CLI の場合

aws ecr create-pull-through-cache-rule \
--region us-west-2 \
--ecr-repository-prefix ecr-public \
--upstream-registry-url public.ecr.aws

https://docs.aws.amazon.com/cli/latest/reference/ecr/create-pull-through-cache-rule.html

CloudFormation の場合
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ecr-pullthroughcacherule.html

Resources:
  DemoECRPullThroughCacheRule:
    Type: 'AWS::ECR::PullThroughCacheRule'
    Properties:
      EcrRepositoryPrefix: 'ecr-public'
      UpstreamRegistry: 'ecr-public'

2)「Permissions」の設定手順

[1] AWS Management Console にログイン
[2] 「Elastic Container Registry」(Amazon ECR)のページに移動
[3] 「Private registry」欄 の [Settings]を選択
[4] 「Permissions」欄 の [Edit]を選択
[5] 「Registry permissions」ページ の「Generate statement」ボタン押下
[6] 「Generate statement」ページ で以下を入力し「Save statement」ボタン押下
 => もしくは「JSON」を選択し、
 後述「※2:AWS ECR / Permissions JSON例」を参考に入力
 * Policy type: Pull through cache policy
 * Statement id: 任意の文字列(e.g. ForPullingThroughCachePolicy)
 * IAM entities: 対象IAMロール(今回は、EC2にAttachしているIAMロール)
 * Repository namespace: 1)の [7] で入力したAmazon ECR repository prefix
  (今回は「ecr-public」)
 * Repository names: 対象のDockerイメージ名/UpstreamRepositoryName
 (今回は「docker/library/flink」)

※2:AWS ECR / Permissions JSON

{
  "Sid": "ForPullingThroughCachePolicy",
  "Effect": "Allow",
  "Principal": {
    "AWS": "arn:aws:iam::123456789012:demo-ec2-role" <=IAMロール
  },
  "Action": [
    "ecr:CreateRepository",
    "ecr:BatchImportUpstreamImage"
  ]
  "Resource": "arn:aws:ecr:us-east-2:123456789012:repository/ecr-public/docker/library/flink" <= ECR Repository ARN
}

補足:関連するAction
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/pull-through-cache.html

より抜粋
~~~~~~~
ecr:BatchImportUpstreamImage
 – 外部イメージを取得し、プライベートレジストリにインポートする
 アクセス許可を付与します。

ecr:CreateRepository
 – プライベートレジストリにリポジトリを作成するアクセス許可を付与します。
 キャッシュされたイメージを格納するリポジトリがまだ存在しない場合には、
 この許可が必要となります。
~~~~~~~

* どうも、動き的には、pullして同じ名前のPrivte ECR repository がなかったら作成する
 => その際に「ecr:CreateRepository」が必要

* Privte ECR repository に対象Docker imageがなかったら、取得しにいく
 => その際に「ecr:BatchImportUpstreamImage」が必要

3)docker pull までの流れ

[1] AWS Management Console にログイン
[2] 「Elastic Container Registry」(Amazon ECR)のページに移動
[3] 「Private registry」欄 の [Settings]-[Pull through cache]を選択
[4] 「Pull through cache configuration」ページで
  対象のDestination namespaceを選択する (ここでは「ecr-public/」)
[5] 「Pull through cache rule detail」欄の
  右上にある「View pull command」ボタン押下
 => 「Pull command for XXX(ここでは「ecr-public」)」が表示される

例:Dockerイメージ「docker/library/flink:1.18.0」をPullする場合
https://gallery.ecr.aws/docker/library/flink

# Step1: docker login
#  => AWS Region: us-west-2 / AWS account ID: 123456789012
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-west-2.amazonaws.com

# Step2: docker pull
# => docker pull 123456789012.dkr.ecr.us-west-2.amazonaws.com/{RepositoryNamespace(ecr-public)}/{UpstreamRepositoryName(docker/library/flink)}:{ImageTag(1.18.0)}
docker pull 123456789012.dkr.ecr.us-west-2.amazonaws.com/ecr-public/docker/library/flink:1.18.0

【3】使用上の注意

* 以下の公式ドキュメントに記載。

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/pull-through-cache.html#pull-through-cache-considerations

参考文献

https://dev.classmethod.jp/articles/launch-ecs-task-from-public-image-through-vpce/
https://dev.classmethod.jp/articles/ecr-pull-through-cache-repositories/
https://qiita.com/t_tsuchida/items/d3c284aac0f84a597c70
https://qiita.com/yoshii0110/items/2cac49fc919d9a8465c7

関連記事

Amazon ECR ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/05/22/165711
Amazon ECR ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2020/05/26/142645
Amazon ECR ~ AWS CLI
https://dk521123.hatenablog.com/entry/2024/01/05/000000
Amazon ECR ~ boto3 ~
https://dk521123.hatenablog.com/entry/2024/01/31/014010
Amazon ECR ~ Dockerイメージを Pull & Push ~
https://dk521123.hatenablog.com/entry/2023/12/02/024631
Amazon ECR ~ AWS ECR Public Gallery ~
https://dk521123.hatenablog.com/entry/2024/04/08/184035
Amazon ECR ~ 脆弱性診断 / Amazon Inspector ~
https://dk521123.hatenablog.com/entry/2024/01/22/210831
Terraform ~ AWS ECR ~
https://dk521123.hatenablog.com/entry/2023/05/23/002314
Amazon ECR でのトラブルシューティング
https://dk521123.hatenablog.com/entry/2020/05/24/000000
IAM ~ Service-Linked Roles ~
https://dk521123.hatenablog.com/entry/2023/01/22/000000