APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

【リファクタリング】変更したファイルだけCIの対象にする

はじめに

こんにちは、コンテナソリューション事業部の髙井です。今日は小ネタです。

「フォーマットすらかかっていないコードベースを、どうにかきれいにしていきたい!」
「ならば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を活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!
切磋琢磨しながらスキルを向上できる、エンジニアには良い環境だと思います。ご興味を持っていただけたら嬉しく思います。

www.ap-com.co.jp

本記事の投稿者: 髙井 比文
AKSをメインにしたインフラとアプリの領域際をご支援することが多いです。Azureは11冠です。
Hifumi Takai - Credly