なぜ作ったか
DevLoop Runner という AIエージェント自動化サービスを作っています。GitHub の Issue から Claude Code や Codex を呼び出して、自動的にプルリクエストまで持っていくツールです。
このツールは、GitHub、Codex、Claude Code といった外部サービスへの認証情報を使います。
問題は、認証が切れていても、ジョブを実行するまで気づかないことでした。
ジョブを実行して、失敗して、ログを見て、「なぜ失敗した?」と調べて、30分後に「認証が切れてた」と分かる。この無駄な時間を減らしたい。
そこで、認証情報を事前に検証する validate-credentials コマンドを追加しました。
判断の軸は「迷わせない」
実装中に考えていたのは、UI との整合性でした。
チェックを実行して出てきた結果を見て、ユーザーが迷うようでは良くない。出てきた結果を見て、適切な判断ができる状態にしたい。
そこで気をつけたのは、こういうことです。
1. セキュリティ情報は出さない
最初の実装では、検証結果に JWT トークンやメールアドレスが平文で出力されていました。
const isJsonString = authJsonPath.startsWith('{') || authJsonPath.startsWith('[');
const displayValue = isJsonString ? '[JSON content - masked for security]' : authJsonPath;
バリデーション結果は「設定されているか」「疎通できるか」が分かればいい。中身を見せる必要はありません。
2. 実行環境と検証環境を揃える
検証コマンドが CODEX_AUTH_JSON 環境変数を見ていたのに、実際の実行コマンドは ~/.codex/auth.json ファイルを使っていました。
これでは、検証が通っても実行で失敗する可能性があります。
実行コマンドと同じ条件でチェックするように変更しました。
3. 必須とオプションを区別する
OpenAI と Anthropic の API キーは、Follow-up Issue 生成用のオプション機能です。未設定でも主要機能は動きます。
でも最初の実装では status: failed と表示していました。
checks.push({
name: 'OPENAI_API_KEY',
status: 'skipped', // 'failed' から変更
message: 'Not configured (optional for follow-up issue generation)',
});
ユーザーが「失敗した」と勘違いしないように、skipped に変更しました。
4. 必要最小限のスコープだけ要求する
GitHub トークンの検証で、最初は repo、workflow、read:org の3つのスコープをチェックしていました。
でも、コードを確認したら:
read:org: どこでも使っていないworkflow: GitHub Actions のコーディング時のみ必要
結局、repo スコープだけに削減しました。
バリデーションが厳しすぎると、実際には動くのに「認証エラー」と言われてしまいます。
5. デバッグできるようにする
Jenkins 環境で Codex の疎通チェックがタイムアウトしていました。でもログが出ていないので、原因が分かりません。
await codexClient.executeTask({
prompt: 'ping',
maxTurns: 1,
verbose: true, // ログを有効化
});
setTimeout(() => reject(new Error('Timeout after 30 seconds')), 30000)
verbose logging を有効化して、次回実行時に原因が特定できるようにしました。
バリデーションツール自体がデバッグしにくかったら、本末転倒です。
今どうなっているか
マージしたばかりなので、実際にどう役立つかはこれからです。
テストで動かした感じでは、期待通りに機能していると思います。
ただ、本当に「認証エラーに早く気づける」ようになったかは、運用してみないと分かりません。
認証が切れたとき、ジョブ実行前に気づけるか。
ユーザーが結果を見て、すぐに対処できるか。
それが分かるのは、これからです。
[📦 商品リンク: moshimo-backlog-banner-728x90]