長い文字列を GitHub Actions の step 間で受け渡す

背景

Terraform でインフラを管理していると、Pull Request に terraform plan の結果をコメントしたり、別ステップで整形して扱いたい場面があると思います。
ところが、この plan の出力は数千行に及ぶことも珍しくなく、GitHub Actions の $GITHUB_ENV や $GITHUB_OUTPUT を使った変数の受け渡しには向かないという問題にぶつかります。
GitHub Actions では環境変数やステップ出力のサイズに上限(おおむね 1MB 程度)があり、長すぎる環境変数の受け渡しによりジョブが失敗することがあるためです。

本記事では、Terraform plan のような「とにかく長いテキスト」をgithub actionsのステップ間で受け渡す方法を紹介します。

悪い例

長すぎる文字列が$GITHUB_ENVで受け渡しされた場合、どのような挙動になるのか確認します。

pull requestをトリガーとする簡単なgithub actionsのコードを作成しました。
わざと長い文字列を生成して$GITHUB_ENVに保存するステップと、環境変数を出力するだけのステップを作成しています。

name: BAD - ENV handoff

on:
  pull_request:

jobs:
  demo:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # 長文を生成して環境変数に突っ込む
      - name: Generate Big Text
        run: |
          yes "これはとても長い文字列です。" | tr -d '\n' | head -c 2000000 > big.txt
          wc -c big.txt
          BIG=$(cat big.txt)
          echo "BIG<<EOF" >> "$GITHUB_ENV"
          echo "$BIG" >> "$GITHUB_ENV"
          echo "EOF" >> "$GITHUB_ENV"

      # ENVから読み出して実際の長さを確認
      - name: Check length from ENV
        run: |
          python - << 'PY'
          import os
          v = os.environ.get("BIG","")
          print("ENV length:", len(v))
          PY

実際にPRを出してみると、画像のようなエラーが出てしまいました。
(Argument list too longというエラーで、一見環境変数が原因のエラーと直感的にわかりづらいかもしれません。)
詳しくはこちらのissueが参考になると思います。
https://github.com/actions/runner/issues/1733

このように、長い文字列をGithub Actionsのstep間でやりとりをするためには、エラーを回避するための工夫が必要となります。

改善案

上記のエラーに対処済みのコードを以下に記載します。
単純に、環境変数に受け渡しをせず、ワークフローの実行環境でファイルを直接参照しています。

name: GOOD - File handoff

on:
  pull_request:

permissions:
  contents: read
  issues: write
  pull-requests: write


jobs:
  demo:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      # 長文を生成してファイルに保存
      - name: Generate Big Text
        run: |
          yes "これはとても長い文字列です。" | tr -d '\n' | head -c 2000000 > big.txt
          wc -c big.txt

      # ファイルから読み出して実際の長さを確認
      - name: Check length from FILE
        run: |
          python - << 'PY'
          from pathlib import Path
          p = Path("big.txt")
          data = p.read_bytes() 
          print("FILE length:", len(data))
          PY

      # PRコメントでプレビューを出す
      - name: Post preview from file
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const fs = require('fs');
            const content = fs.readFileSync('big.txt', 'utf8');
            const preview = content.slice(0, 200) + "\n...省略...";
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: [
                "### 受け渡し(ファイル方式)プレビュー",
                "",
                "```",
                preview,
                "```"
              ].join("\n")
            });

さきほどエラーになってしまったstepも無事に成功しました。

改善バージョンのgithub actionsのyamlではPRにプレビューをだすstepも追加しています。
こちらも正しく動作しており、ワークフローも成功していることが確認できました。

これまで環境変数でしか受け渡せないと思い込んでいたので、シンプルですが大きな気づきでした。

コメント

タイトルとURLをコピーしました