GitHub ActionsでCI/CDを実現できるようになった今、pushする度にワークフローがエラーとなることが多々あります。
エラーが起きる度に原因を調べたり、AIに聞いたりしていたのですが、段々と面倒になってると感じていました。
そこで、GitHub Actionsのai-inference
を使用して、エラーの原因と解消方法を自動で教えてもらうことはできないかと考え、AIと相談しながら実際に作成してみました。
CI/CDワークフロー(test-deploy.yml)が失敗した際に、エラーログを取得し、AIが自動で解析、ジョブの概要欄にて原因と解決方法を表示してくれます。
ai-failure-check.yml
ai-failure-check.yml
name: AI Failure check
on:
workflow_run:
workflows: "Test and Deploy"
types:
- completed
jobs:
on-success:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: success
run: |
echo "trigger build workflow success"
on-failure:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
permissions:
actions: read
contents: read
models: read
steps:
- name: failure
run: |
echo "trigger build workflow failed"
- name: Checkout code
uses: actions/checkout@v4
- name: Get error info
id: get-error
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "::error::ワークフロー失敗"
echo "branch: ${{ github.event.workflow_run.head_branch }}"
# ワークフローの実行IDを取得
RUN_ID=${{ github.event.workflow_run.id }}
echo "RUN_ID: $RUN_ID"
# ワークフロー情報を環境変数に保存
echo "WORKFLOW_NAME=${{ github.event.workflow_run.name }}" >> $GITHUB_ENV
echo "BRANCH_NAME=${{ github.event.workflow_run.head_branch }}" >> $GITHUB_ENV
echo "COMMIT_SHA=${{ github.event.workflow_run.head_sha }}" >> $GITHUB_ENV
# ジョブの一覧を取得
JOBS=$(gh api repos/${{ github.repository }}/actions/runs/${RUN_ID}/jobs --jq '.jobs')
# 失敗したジョブのログを取得
echo "FAILED_LOGS> $GITHUB_ENV
for job in $(echo "$JOBS" | jq -r '.[] | select(.conclusion == "failure") | .id'); do
echo "=== Job ID: $job ===" >> $GITHUB_ENV
gh api repos/${{ github.repository }}/actions/jobs/${job}/logs >> $GITHUB_ENV 2>&1 || echo "ログの取得に失敗しました" >> $GITHUB_ENV
echo "" >> $GITHUB_ENV
done
echo "EOF" >> $GITHUB_ENV
- name: Run AI check
id: ai-check
uses: actions/ai-inference@v1
with:
model: "openai/gpt-4o"
prompt: |
あなたは、エラー解決のプロです。初心者に向けてわかりやすくなぜエラーになったのか、どうすればエラーを解決できるかを教えてください。
以下の形式で簡潔に(全体で10行以内)説明してください。
エラーの内容は以下です。
**失敗したワークフロー:**
- ワークフロー名: ${{ env.WORKFLOW_NAME }}
- ブランチ: ${{ env.BRANCH_NAME }}
- コミットSHA: ${{ env.COMMIT_SHA }}
- 使用技術: Vite, Supabase, Firebase
**エラーログ:**
```
${{ env.FAILED_LOGS }}
```
**回答形式フォーマット:**
【原因】1-2行で説明
【解決方法】具体的な手順を1-2個
【予防策】1つだけ
- name: Save AI response to summary
if: always()
run: |
# GitHub Actionsのサマリーに出力(Web UIで確認可能)
echo "## 分析結果" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '${{ steps.ai-check.outputs.response }}' | base64 | base64 -d >> $GITHUB_STEP_SUMMARY
実際の流れ
①ワークフローエラー発生
test-deploy.yml実行時、project_testジョブでテストが失敗しています。
②AIにてワークフローエラー解析
test-deploy.yml実行後、ai-failure-check.ymlのワークフローが自動で起動、エラーログを取得します。
③分析した結果の表示
AI分析した結果(原因と対処方法)が概要欄に表示されます。
1. ワークフロー実行後をトリガーとする新規ワークフローの作成
ワークフローの完了をトリガーに別のワークフローを実行するために、workflow_run
を使用しました。
ai-failure-check
name: AI Failure check
on:
workflow_run:
workflows: "Test and Deploy"
types:
- completed
jobs:
on-success:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: success
run: |
echo "trigger build workflow success"
on-failure:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
steps:
- name: failure
run: |
echo "trigger build workflow failed"
workflows
:トリガーにするワークフロー名types:- completed
:ワークフロー実行後を指定
${{ github.event.workflow_run.conclusion == 'success' }}
:ワークフローの実行結果を取得
動作確認
下記の画像はtest-deploy.yml(ワークフロー名:Test and Deploy)実行後です。job名変えたよ
のコメントでpush後、エラーなくワークフローが完了しています。
その後、ai-failure-check.yml(ワークフロー名:AI Failure check)の結果を確認、Test and Deployがエラーなく完了しているため、on-success
ジョブが実行されました。
コンソールにもメッセージが表示されています。
2. エラーログ取得とAI解析の実装
1.で作成したワークフロー失敗時に実行されるジョブ(on-failure
)にて、以下を追加しました。
-
permissions
:ワークフローが他のリソースなどにアクセスする際の権限設定 steps
steps
は以下を追加
-
failure
:コンソールに失敗した旨を表示 -
Checkout code
:チェックアウトとリポジトリのアクセス許可 -
Get error info
:エラーログの取得 -
Run AI check
:AIの分析 -
Save AI response to summay
:分析結果を表示
ai-failure-check.yml
name: AI Failure check
on:
workflow_run:
workflows: "Test and Deploy"
types:
- completed
jobs:
on-success:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: success
run: |
echo "trigger build workflow success"
on-failure:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
permissions:
actions: read
contents: read
models: read
steps:
- name: failure
run: |
echo "trigger build workflow failed"
- name: Checkout code
uses: actions/checkout@v4
- name: Get error info
id: get-error
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "::error::ワークフロー失敗"
echo "branch: ${{ github.event.workflow_run.head_branch }}"
# ワークフローの実行IDを取得
RUN_ID=${{ github.event.workflow_run.id }}
echo "RUN_ID: $RUN_ID"
# ワークフロー情報を環境変数に保存
echo "WORKFLOW_NAME=${{ github.event.workflow_run.name }}" >> $GITHUB_ENV
echo "BRANCH_NAME=${{ github.event.workflow_run.head_branch }}" >> $GITHUB_ENV
echo "COMMIT_SHA=${{ github.event.workflow_run.head_sha }}" >> $GITHUB_ENV
# ジョブの一覧を取得
JOBS=$(gh api repos/${{ github.repository }}/actions/runs/${RUN_ID}/jobs --jq '.jobs')
# 失敗したジョブのログを取得
echo "FAILED_LOGS> $GITHUB_ENV
for job in $(echo "$JOBS" | jq -r '.[] | select(.conclusion == "failure") | .id'); do
echo "=== Job ID: $job ===" >> $GITHUB_ENV
gh api repos/${{ github.repository }}/actions/jobs/${job}/logs >> $GITHUB_ENV 2>&1 || echo "ログの取得に失敗しました" >> $GITHUB_ENV
echo "" >> $GITHUB_ENV
done
echo "EOF" >> $GITHUB_ENV
- name: Run AI check
id: ai-check
uses: actions/ai-inference@v1
with:
model: "openai/gpt-4o"
prompt: |
あなたは、エラー解決のプロです。初心者に向けてわかりやすくなぜエラーになったのか、どうすればエラーを解決できるかを教えてください。
以下の形式で簡潔に(全体で10行以内)説明してください。
エラーの内容は以下です。
**失敗したワークフロー:**
- ワークフロー名: ${{ env.WORKFLOW_NAME }}
- ブランチ: ${{ env.BRANCH_NAME }}
- コミットSHA: ${{ env.COMMIT_SHA }}
- 使用技術: Vite, Supabase, Firebase
**エラーログ:**
```
${{ env.FAILED_LOGS }}
```
**回答形式フォーマット:**
【原因】1-2行で説明
【解決方法】具体的な手順を1-2個
【予防策】1つだけ
- name: Save AI response to summary
if: always()
run: |
# GitHub Actionsのサマリーに出力(Web UIで確認可能)
echo "## 分析結果" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '${{ steps.ai-check.outputs.response }}' | base64 | base64 -d >> $GITHUB_STEP_SUMMARY
permissions
permissions
:ワークフローがGitHubのリソースやAPIにアクセスする際の権限を設定する
permissions:
actions: read
contents: read
models: read
公式ドキュメントより引用
permissions を使用して GITHUB_TOKEN に付与された既定のアクセス許可を変更し、必要に応じてアクセスを追加または削除することで、必要最小限のアクセスのみを許可することができます。
read (該当する場合)、write、または none のいずれかのアクセス レベルを割り当てることができます。
actions
:GitHub Actions を操作します。contents
:リポジトリの内容を操作します。models
:GitHub Models を使用して AI 推論応答を生成します。たとえば、models: read は、GitHub Models 推論 API を使用するアクションを許可します。
steps
name: failure
コンソール上にtrigger build workflow failed
を表示する
steps:
- name: failure
run: |
echo "trigger build workflow failed"
name: Checkout code
チェックアウトとリポジトリのアクセスをできるようにする
- name: Checkout code
uses: actions/checkout@v4
READMEより引用
このアクションは$GITHUB_WORKSPACE配下のリポジトリをチェックアウトし、ワークフローがリポジトリにアクセスできるようにします。
name: Get error info
id
:ステップの一意な識別子
- name: Get error info
id: get-error
env
:ワークフロー内で使用できる変数を定義
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
公式ドキュメントより引用
env:ワークフロー中のすべてのジョブのステップで使うことができる変数の map です
GITHUB_TOKEN
はワークフロー開始時に自動で作成してくれます。${{ secrets.GITHUB_TOKEN }}
で定義し、使用します。
各ワークフロー ジョブの開始時に、GitHub によって、ワークフローで使用する一意の GITHUB_TOKEN シークレットが自動的に作成されます。
${{ secrets.GITHUB_TOKEN }} を使って、GITHUB_TOKEN を使用できます。
ワークフローの実行IDを取得
github.event.workflow_run.~
:workflow_run:
で指定したワークフロー情報(今回の場合はTest and Deploy
の実行結果を格納してくれる)head_branch
:実行されたブランチ名id
:ワークフロー実行ID
run: |
echo "::error::ワークフロー失敗"
echo "branch: ${{ github.event.workflow_run.head_branch }}"
# ワークフローの実行IDを取得
RUN_ID=${{ github.event.workflow_run.id }}
echo "RUN_ID: $RUN_ID"
ワークフロー情報を環境変数に保存
github.event.workflow_run.~
:workflow_run:
で指定したワークフロー情報(今回の場合はTest and Deploy
の実行結果を格納してくれる)name
:ワークフロー名head_branch
:実行されたブランチ名head_sha
:コミットしたときのハッシュ値
echo "WORKFLOW_NAME=${{ github.event.workflow_run.name }}" >> $GITHUB_ENV
>>
:ファイルに追記するシェルコマンド(>
の場合は上書き)
-
$GITHUB_ENV
ファイルを作成、WORKFLOW_NAME=${{ github.event.workflow_run.name }}
を記載、保存 -
WORKFLOW_NAME=${{ github.event.workflow_run.head_branch }}
を追記 -
WORKFLOW_NAME=${{ github.event.workflow_run.head_sha }}
を追記
# ワークフロー情報を環境変数に保存
echo "WORKFLOW_NAME=${{ github.event.workflow_run.name }}" >> $GITHUB_ENV
echo "BRANCH_NAME=${{ github.event.workflow_run.head_branch }}" >> $GITHUB_ENV
echo "COMMIT_SHA=${{ github.event.workflow_run.head_sha }}" >> $GITHUB_ENV
ジョブの一覧を取得
GitHub CLI(gh)を使ってapiを呼び出す
gh api repos/${{ github.repository }}/actions/runs/${RUN_ID}/jobs
# ジョブの一覧を取得
JOBS=$(gh api repos/${{ github.repository }}/actions/runs/${RUN_ID}/jobs --jq '.jobs')
gh
: GitHub CLIを使用するコマンドapi
: APIを呼び出すrepos/\\${{ github.repository }}/actions/runs/${RUN_ID}/jobs
: エンドポイント、実行したワークフローのjobを取得
失敗したジョブのログを取得
# 失敗したジョブのログを取得
echo "FAILED_LOGS> $GITHUB_ENV
for job in $(echo "$JOBS" | jq -r '.[] | select(.conclusion == "failure") | .id'); do
echo "=== Job ID: $job ===" >> $GITHUB_ENV
gh api repos/${{ github.repository }}/actions/jobs/${job}/logs >> $GITHUB_ENV 2>&1 || echo "ログの取得に失敗しました" >> $GITHUB_ENV
echo "" >> $GITHUB_ENV
done
echo "EOF" >> $GITHUB_ENV
echo "FAILED_LOGS> $GITHUB_ENV
:$GITHUB_ENVファイルにFAILED_LOGS
FAILED_LOGS:環境変数FAILED_LOGSを設定
:ヒアドキュメント、EOFという文字列が現れるまで、複数行の値として扱う
for job in $(echo "$JOBS" | jq -r '.[] | select(.conclusion == "failure") | .id'); do
echo "=== Job ID: $job ===" >> $GITHUB_ENV
gh api repos/${{ github.repository }}/actions/jobs/${job}/logs >> $GITHUB_ENV 2>&1 || echo "ログの取得に失敗しました" >> $GITHUB_ENV
echo "" >> $GITHUB_ENV
done
echo "EOF" >> $GITHUB_ENV
$JOBS
:ジョブ一覧を格納jq -r '.[]
:jq
jsonを取り扱うコマンド、-r
オプションを直接取り扱う、.[]
JSON配列の各要素をループして取り出すselect(.conclusion == "failure")
:conclusionが”failure”のもののみ取得.id
:idだけ取り出す
取り出したものはjob
に格納
echo "=== Job ID: $job ===" >> $GITHUB_ENV
:=== Job ID: $job ===取り出したjob(id)をGITHUB_ENVに追記
gh api repos/${{ github.repository }}/actions/jobs/${job}/logs >> $GITHUB_ENV 2>&1 || echo "ログの取得に失敗しました" >> $GITHUB_ENV
idのlogsをGITHUB_ENVに追記、2>&1
は2は標準エラー出力、>&1は標準出力にリダイレクトする(エラーメッセージも通常の出力としてファイルに書き込む)
|| はOR演算子、左側のコマンドが失敗したら(false)の右側の処理を行う
|
:YAMLの複数行記法
name: Run AI check
uses
: actions/ai-inference@v1
を指定model
: AIのモデルを指定prompt
:プロンプトを指定
- name: Run AI check
id: ai-check
uses: actions/ai-inference@v1
with:
model: "openai/gpt-4o"
prompt: |
あなたは、エラー解決のプロです。初心者に向けてわかりやすくなぜエラーになったのか、どうすればエラーを解決できるかを教えてください。
以下の形式で簡潔に(全体で10行以内)説明してください。
エラーの内容は以下です。
**失敗したワークフロー:**
- ワークフロー名: ${{ env.WORKFLOW_NAME }}
- ブランチ: ${{ env.BRANCH_NAME }}
- コミットSHA: ${{ env.COMMIT_SHA }}
- 使用技術: Vite, Supabase, Firebase
**エラーログ:**
```
${{ env.FAILED_LOGS }}
```
**回答形式フォーマット:**
【原因】1-2行で説明
【解決方法】具体的な手順を1-2個
【予防策】1つだけ
name: Save AI response to summary
if: always()
前のステップに関係なくステップを実行できる
GITHUB_STEP_SUMMARY
に追加することでジョブの概要に出力することができる
- name: Save AI response to summary
if: always()
run: |
# GitHub Actionsのサマリーに出力(Web UIで確認可能)
echo "## 分析結果" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo '${{ steps.ai-check.outputs.response }}' | base64 | base64 -d >> $GITHUB_STEP_SUMMARY
GitHub Actionsの新しいトリガーやGitHubCLI、シェルスクリプトなど新しい知識を得ることができました。
自分のリサーチだけでは今回の仕組みはできなかったです。AIの助けを借りながら知識を得ることができ、良い機会になりました。
Views: 3