tj-actions/changed-filesで日本語ファイル名の差分検知が失敗する問題とその解決法

Cover Image for tj-actions/changed-filesで日本語ファイル名の差分検知が失敗する問題とその解決法
monotalkのプロフィール画像
monotalk

tj-actions/changed-filesで日本語ファイル名の差分検知が失敗する問題とその解決法

はじめに

GitHub Actionsでtj-actions/changed-filesを使用してファイル差分を取得するワークフローを運用していたところ、日本語を含むファイルが適切に検知されない問題に遭遇しました。この記事では、その問題と解決方法について解説します。

この問題は主に以下の2つの要因が重なって発生しました:

  • Gitのcore.quotepath設定による日本語ファイル名のエスケープ処理
  • tj-actions/changed-filesのv41.0.0以降で導入されたsafe_outputオプションによるセキュリティ対策

日本語のファイルの差分が検知されない問題

このブログのCI/CDパイプラインではtj-actions/changed-files@v46を使用して変更ファイルを検知するワークフローを構築していました。しかし、ファイル名に日本語が含まれるPull Requestでは、対象のファイルの差分検知がうまくできませんでした。

_posts/drafts/2025-06-08_Javaのマルチプロジェクトのセットアップ方法について.md

原因

ローカルでdiffコマンドを実行してみると以下のアウトプットが出力されました。

  • diffコマンド
diff diff --name-only f80c8594aea45f9af4da49b9c878048d989917cd..f12a70f4d8a634d2344cf936d3da6b5490290bba
  • Output
.github/workflows/blog-review-ai.yml
.github/workflows/build-test.yml
.github/workflows/code-review-ai.yml
"_posts/drafts/2025-06-08_Java\343\201\256\343\203\236\343\203\253\343\203\201\343\203\227\343\203\255\343\202\270\343\202\247\343\202\257\343\203\210\343\201\256\343\202\273\343\203\203\343\203\210\343\202\242\343\203\203\343\203\227\346\226\271\346\263\225\343\201\253\343\201\244\343\201\204\343\201\246.md"
package-lock.json
package.json
  • アクション定義
    ファイルの末尾がmd"になっており、tj-actions/changed-filesのアクション定義では、.mdでファイルのフィルタリングを行っているため、うまく変更が検知できていなかったようです。
      # 変更されたファイルをJSON形式で取得する
      - name: Get changed files in the drafts folder
        id: changed-files-specific
        uses: tj-actions/changed-files@v46
        with:
          files: |
            **.md

対処方法

以下の処理をGitHub Actionsに記載したところうまく差分が検知できるようになりました。

# UTF-8エンコーディングとGit設定を調整
- name: Configure Git for Japanese filenames
  run: |
    git config --local core.quotepath false
    git config --global core.quotepath false
    export LC_ALL=C.UTF-8
    export LANG=C.UTF-8

この設定により、Gitが日本語をエスケープせずにそのまま出力するようになります。

matrixジョブのJSON形式に関するエラー

ファイル差分が検知できるようになった後、後続処理でエラーが発生しました。

原因

以下のエラーが発生しました。

Blog Review with AI
Error when evaluating 'strategy' for job 'review'. .github/workflows/blog-review-ai.yml (Line: 48, Col: 15): Error from function 'fromJSON': String contains invalid escape code: '\�'. Located at line 1 position 2 within JSON., .github/workflows/blog-review-ai.yml (Line: 48, Col: 15): Unexpected value ''

tj-actions/changed-filesには、matrixジョブのインプットとするためのmatrix: true というプロパティがありますが、そのアウトプットの形式に問題がありそうでした。

safe_outputオプションの詳細

safe_outputtj-actions/changed-filesv41.0.0で導入されたセキュリティ機能で、true|falseの切り替えにより以下の挙動を示します。

設定値 動作 用途
true(デフォルト) ファイル名をBash用にエスケープ セキュリティ重視の環境
false エスケープ処理なし 日本語など非ASCII文字を含むファイル名

日本語を正しく処理するためには、safe_output: falseの設定が必要です。

対策

safe_output: falseを追加したところ、日本語を含むファイルの差分検知が正常に動作するようになりました。

jobs:
  # 準備ジョブ: 変更されたファイル一覧をJSON形式で取得
  prepare:
    permissions:
      contents: read
    runs-on: ubuntu-latest
    outputs:
      changed_files: >-
        ${{ steps.changed-files-specific.outputs.all_changed_files }}
      has_changes: ${{ steps.changed-files-specific.outputs.any_changed }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      # UTF-8エンコーディングを明示的に設定
      - name: Set UTF-8 encoding
        run: |
          git config --local core.quotepath false  
          git config --global core.quotepath false
          export LC_ALL=C.UTF-8
          export LANG=C.UTF-8

      # 変更されたファイルをJSON形式で取得する
      - name: Get changed files in the drafts folder
        id: changed-files-specific
        uses: tj-actions/changed-files@v46
        with:
          files: |
            **.md
          matrix: true
          # 文字エンコーディング問題を回避するオプション
          safe_output: false

  # レビュージョブ: matrixストラテジーで各ファイルを個別処理
  review:
    needs: prepare
    if: needs.prepare.outputs.has_changes == 'true'
    permissions:
      models: read # GitHub Models を読み取るための権限
      contents: read # ファイルをプロンプトとして渡すために必要な権限
      pull-requests: write # プルリクエストにコメントを投稿するための権限
    runs-on: ubuntu-latest
    strategy:
      matrix:
        file: ${{ fromJSON(needs.prepare.outputs.changed_files) }}
      max-parallel: 3 # レート制限対策として並列実行数を制限
      fail-fast: false # 一部失敗時も他のファイル処理を継続
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # UTF-8エンコーディングを明示的に設定
      - name: Set UTF-8 encoding
        run: |
          git config --local core.quotepath false
          git config --global core.quotepath false
          export LC_ALL=C.UTF-8
          export LANG=C.UTF-8

      # AI によるレビューを実行(各ファイル個別)
      - name: AI Blog Review for ${{ matrix.file }}
        id: inference
        uses: actions/ai-inference@v1.1.0
        with:
          system-prompt-file: '.github/prompts/blog-review-ai.prompt.md'
          # 個別ファイルの内容をプロンプトとして渡す
          prompt-file: '${{ matrix.file }}'
          model: openai/gpt-4o
          max-tokens: '2000'

注意点

tj-actions/changed-filesの将来バージョンでは、日本語ファイル名を安全に処理できるオプションが追加される可能性があります。定期的にリリースノートを確認し、よりセキュアな解決方法が利用可能になった場合は移行を検討した方が良い気がしています。
"付きのファイルを処理できるようになるか、もしくは現状でも、"付きのファイル名を考慮したパターンマッチングをした方が、後続処理を考えるとよりセキュリティ面で堅牢になるのかもしれません。

参考リンク

関連記事

コメント