はじめに
こんにちは、コンテナソリューション事業部の髙井です。今日は小ネタです。
「フォーマットすらかかっていないコードベースを、どうにかきれいにしていきたい!」
「ならばCIで自動的に弾きたい!」
「でもCIを導入すると全ファイル引っかかっちゃってしんどい!」
そんなシーンで「今回編集したファイルに関してだけCIかけたい」みたいな要望が発生すると思います。
やっていきましょう。
GitHub Actionsで変更ファイルのみCI対象にするサンプル
いきなり結論からいきます。Pythonの例です。
変更されたファイルのみフォーマットやリントをかけます。
name: Python application on: pull_request: branches: - '**' permissions: contents: read jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: | git fetch origin --depth=1 - name: Export target files to environment variables run: | echo 'FILES_UPDATED<<EOF' >> $GITHUB_ENV git diff --name-status origin/${{ github.base_ref }} HEAD --relative ./ | \ grep -E "^(R|A|M).*\.py$" | \ grep -v "/migrations/versions/" | \ sed -sr "s/^(R|A|M).*\t(.+)/\2/" >> $GITHUB_ENV echo 'EOF' >> $GITHUB_ENV - name: Print files updated if: env.FILES_UPDATED run: | echo $FILES_UPDATED - name: Set up Python 3.9 if: env.FILES_UPDATED uses: actions/setup-python@v3 with: python-version: '3.9' - name: Install dependencies if: env.FILES_UPDATED run: | python -m pip install --upgrade pip pip install black flake8 isort - name: Format check with black if: env.FILES_UPDATED run: | black --config ./pyproject.toml --check $FILES_UPDATED - name: Format check with isort if: env.FILES_UPDATED run: | isort $FILES_UPDATED --profile=black --line-length=119 --py=39 --check --src app.py - name: Lint with flake8 if: env.FILES_UPDATED run: | flake8 $FILES_UPDATED --exclude=some_file.py --ignore=E203,E501,W503,W504
変更ファイルを抽出する部分
この部分がキモですね。
git diff --name-status origin/${{ github.base_ref }} HEAD --relative ./ | \ grep -E "^(R|A|M).*\.py$" | \ grep -v "/migrations/versions/" | \ sed -sr "s/^(R|A|M).*\t(.+)/\2/" >> $GITHUB_ENV
変更ファイルの列挙
指定ディレクトリからの相対パスで、変更のあったファイル名をステータス付きで列挙します。
origin/${{ github.base_ref }}
とすることでPRのベースブランチからの差分を取ることができます。
git diff --name-status origin/${{ github.base_ref }} HEAD --relative ./
Pythonファイルの絞り込み
拡張子で絞り込みます。末尾の拡張子を変えればPythonじゃないプロジェクトでも使えますね。
| grep -E "^(R|A|M).*\.py$"
対象外ファイルの除外
grep -v
で含めない検索をします。
今回の例だとalembicで出力されるマイグレーション用のファイルはフォーマットに沿ってないので除外します。
| grep -v "/migrations/versions/"
おわりに
冒頭のシチュエーション以外でも、全ファイルを対象にしないことでCIの時間圧縮にもつながります。
公私含め何回か同じようなものを作っていて、1から作ると地味に時間がかかったりするので、ブログに起こしておきました。
誰か(未来の自分を含む)の役に立ちますように。
私達ACS事業部はAzure・AKSを活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。
また、一緒に働いていただける仲間も募集中です!
切磋琢磨しながらスキルを向上できる、エンジニアには良い環境だと思います。ご興味を持っていただけたら嬉しく思います。