なぜ作ったか

DevLoop Runner という AIエージェント自動化サービスを作っています。GitHub の Issue から Claude Code や Codex を呼び出して、自動的にプルリクエストまで持っていくツールです。

このツールは、GitHub、Codex、Claude Code といった外部サービスへの認証情報を使います。

問題は、認証が切れていても、ジョブを実行するまで気づかないことでした。

ジョブを実行して、失敗して、ログを見て、「なぜ失敗した?」と調べて、30分後に「認証が切れてた」と分かる。この無駄な時間を減らしたい。

そこで、認証情報を事前に検証する validate-credentials コマンドを追加しました。

🔗 https://devloop-runner.app/


判断の軸は「迷わせない」

実装中に考えていたのは、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 トークンの検証で、最初は repoworkflowread:org の3つのスコープをチェックしていました。

でも、コードを確認したら:

結局、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]