日本語

CI/CD で Codex アカウント認証を維持する(上級者向け)

Codex の組み込み更新フローを使用し、信頼できる CI/CD ランナーで auth.json を継続して利用する

このガイドでは、OAuth トークンエンドポイントを自分で呼び出すことなく、信頼できる CI/CD ランナーで ChatGPT が管理する Codex 認証を維持する方法を説明します。

自動化の適切な認証方法は、API key を使用することです。このガイドは、ワークフローを自分の Codex アカウントとして実行する必要がある場合にのみ使用してください。

このパターンは次のとおりです。

  1. 信頼できるマシンで codex login を使用して auth.json を一度作成します。
  2. そのファイルをランナーに配置します。
  3. Codex を通常どおり実行します。
  4. セッションが古くなったら、Codex に更新させます。
  5. 更新された auth.json を次回の実行用に保持します。

これは、エンタープライズ環境などの信頼できるプライベートな自動化向けの高度なワークフローです。ほとんどの CI/CD ジョブでは、引き続き API key が推奨されます。

この方法が機能する理由

Codex には、ChatGPT が管理するセッションを更新する仕組みがすでに備わっています。

現在のオープンソースクライアントでは、次のように動作します。

  • Codex は auth.json からローカルの認証キャッシュを読み込みます
  • last_refresh が約 8 日より古い場合、Codex は実行を続ける前にトークンバンドルを更新します
  • 更新に成功すると、Codex は新しいトークンと新しい last_refreshauth.json に書き戻します
  • リクエストで 401 が返された場合も、Codex には更新して再試行する組み込みパスがあります

つまり、サポートされている CI/CD 戦略は「更新 API を自分で呼び出す」ことではありません。「Codex を実行し、更新された auth.json を永続化する」ことです。

使用する場面

このガイドは、次の条件をすべて満たす場合にのみ使用してください。

  • API key ではなく、ChatGPT が管理する Codex 認証が必要である
  • リモートランナーで codex login を実行できない
  • ランナーが信頼できるプライベートインフラストラクチャである
  • 更新された auth.json を実行間で保持できる
  • 特定の auth.json のコピーを使用するのが、1 台のマシンまたは直列化された 1 つのジョブストリームだけである

このガイドは、Codex が管理する ChatGPT 認証(auth_mode: "chatgpt")に適用されます。

次の認証には適用されません。

  • API key 認証
  • 外部トークンを使用するホスト統合(auth_mode: "chatgptAuthTokens"
  • Codex 外部の汎用 OAuth クライアント

認証情報が OS のキーチェーンに保存されている場合は、まずファイルベースのストレージに切り替えてください。認証情報の保存を参照してください。

auth.json を一度だけ初期設定する

ブラウザでログインできる信頼済みマシンで、次の操作を行います。

  1. 認証情報をファイルに保存するよう Codex を設定します。
cli_auth_credentials_store = "file"
  1. 次を実行します。
codex login
  1. ファイルが ChatGPT 管理の認証形式になっていることを確認します。
AUTH_FILE="${CODEX_HOME:-$HOME/.codex}/auth.json"

jq '{
  auth_mode,
  has_tokens: (.tokens != null),
  has_refresh_token: ((.tokens.refresh_token // "") != ""),
  last_refresh
}' "$AUTH_FILE"

次の条件を満たす場合のみ続行してください。

  • auth_mode"chatgpt" である
  • has_refresh_tokentrue である

次に、auth.json の内容を CI/CD のシークレットマネージャーに保存するか、信頼できる永続ランナーにコピーします。

推奨パターン:セルフホスト GitHub Actions ランナー

完全自動化された最もシンプルな構成は、永続的な CODEX_HOME を持つセルフホスト GitHub Actions ランナーです。

このパターンが適している理由は次のとおりです。

  • ランナーはジョブ間で auth.json をディスクに保持できます
  • Codex はファイルをその場で更新できます
  • 後続のジョブは、更新されたトークンを自動的に使用します
  • 元のシークレットが必要なのは、初期設定または再初期設定の場合だけです

重要なのは、auth.json が存在しない場合にのみ初期設定することです。実行のたびに元のシークレットからファイルを書き直すと、Codex が書き込んだばかりの更新済みトークンが失われます。

スケジュール実行ワークフローの例:

name: Keep Codex auth fresh

on:
  schedule:
    - cron: "0 9 * * 1"
  workflow_dispatch:

jobs:
  keep-codex-auth-fresh:
    runs-on: self-hosted
    steps:
      - name: Bootstrap auth.json if needed
        shell: bash
        env:
          CODEX_AUTH_JSON: ${{ secrets.CODEX_AUTH_JSON }}
        run: |
          export CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
          mkdir -p "$CODEX_HOME"
          chmod 700 "$CODEX_HOME"

          if [ ! -f "$CODEX_HOME/auth.json" ]; then
            printf '%s' "$CODEX_AUTH_JSON" > "$CODEX_HOME/auth.json"
            chmod 600 "$CODEX_HOME/auth.json"
          fi

      - name: Run Codex
        shell: bash
        run: |
          codex exec --json "Reply with the single word OK." >/dev/null

このワークフローでは、次の処理を行います。

  • 最初の実行で auth.json を初期設定します
  • 2 回目以降は同じファイルを再利用します
  • キャッシュ済みセッションが十分に古くなると、通常の codex exec ステップ中に Codex が更新します
  • 更新されたファイルは、次回のワークフロー実行用にディスク上に残ります

現在のオープンソースクライアントでは、Codex は約 8 日後にセッションを古いとみなすため、通常は週 1 回のスケジュールで十分です。

一時的なランナー:復元し、Codex を実行して、更新済みファイルを永続化する

GitHub ホストランナー、GitLab 共有ランナー、またはその他の一時的な環境を使用する場合、ランナーのファイルシステムはジョブごとに消去されます。この構成では、次の往復処理が必要です。

  1. セキュアストレージから現在の auth.json を復元する
  2. Codex を実行する
  3. 更新された auth.json をセキュアストレージに書き戻す

一般的な GitHub Actions の構成:

name: Run Codex with managed auth

on:
  workflow_dispatch:

jobs:
  codex-job:
    runs-on: ubuntu-latest
    steps:
      - name: Restore auth.json
        shell: bash
        run: |
          export CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
          mkdir -p "$CODEX_HOME"
          chmod 700 "$CODEX_HOME"

          # Replace this with your secret manager or secure storage command.
          my-secret-cli read codex-auth-json > "$CODEX_HOME/auth.json"
          chmod 600 "$CODEX_HOME/auth.json"

      - name: Run Codex
        shell: bash
        run: |
          codex exec --json "summarize the failing tests"

      - name: Persist refreshed auth.json
        if: always()
        shell: bash
        run: |
          # Replace this with your secret manager or secure storage command.
          my-secret-cli write codex-auth-json < "$CODEX_HOME/auth.json"

重要なのは、元の初期設定ファイルではなく、実行中に Codex が生成した更新済みファイルを書き戻しステップで保存することです。

個別の更新コマンドは不要

通常の Codex 実行でセッションを更新できます。

したがって、次の 2 つの方法を選択できます。

  • 既存の CI/CD Codex ジョブでファイルを自然に更新する
  • 実際のジョブの実行頻度が十分でない場合は、上記の GitHub Actions の例のように、軽量なスケジュール済みメンテナンスジョブを追加する

セッションが古くなった後の最初の Codex 実行で、auth.json が更新されます。

重要な運用ルール

  • ランナーごと、または直列化されたワークフローストリームごとに 1 つの auth.json を使用してください。
  • 同じファイルを複数の並行ジョブや複数のマシンで共有しないでください。
  • 永続ランナーの更新済みファイルを、実行のたびに元の初期設定ファイルで上書きしないでください。
  • auth.json をリポジトリ、ログ、または公開アーティファクトストレージに保存しないでください。
  • 組み込みの更新が機能しなくなった場合は、信頼できるマシンから再初期設定してください。

更新が機能しなくなった場合の対処

このフローは手作業を減らしますが、同じセッションが永久に継続することを保証するものではありません。

次の場合は、新しい auth.json でランナーを再初期設定してください。

  • Codex が 401 を返し始め、ランナーで更新できなくなった
  • リフレッシュトークンが失効または期限切れになった
  • 別のマシンまたは並行ジョブが先にトークンをローテーションした
  • セキュアストレージとの往復処理に失敗し、古いファイルが復元された

再初期設定するには、次の手順を実行します。

  1. 信頼できるマシンで codex login を実行します。
  2. CI/CD に保存されている auth.json のコピーを置き換えます。
  3. 次のランナージョブで Codex の組み込み更新フローを引き続き使用します。

ランナーがセッションを維持していることを確認する

ランナーに ChatGPT 管理の認証トークンがまだ存在し、last_refresh が記録されていることを確認します。

AUTH_FILE="${CODEX_HOME:-$HOME/.codex}/auth.json"

jq '{
  auth_mode,
  last_refresh,
  has_access_token: ((.tokens.access_token // "") != ""),
  has_id_token: ((.tokens.id_token // "") != ""),
  has_refresh_token: ((.tokens.refresh_token // "") != "")
}' "$AUTH_FILE"

永続ランナーの場合は、同じファイルが実行間でも存在し続けることを確認してください。一時的なランナーの場合は、書き戻しステップで前回のジョブから更新されたファイルが保存されていることを確認してください。

ソースリファレンス

オープンソースクライアントでこの動作を確認する場合は、次を参照してください。

  • codex-rs/core/src/auth.rs では、古いトークンの検出、自動更新、401 発生時の更新と再試行による復旧、および更新済みトークンの永続化を扱っています
  • codex-rs/core/src/auth/storage.rs では、ファイルベースの auth.json ストレージを扱っています