Skip to content

Codex CLI × GitHub Actions Integration | Complete PR Review Automation Guide

This article is a follow-up to the morning article

Morning article: Codex CLI Plan Mode Practical Guide

Goals

  • Auto-execute Codex plan mode via PR comments and present execution plans to reviewers
  • Integrate GitHub approval flow to automate codex execution after review approval
  • Implement rollback strategies and error notifications for production-level reliability

Prerequisites and Security Configuration

Required Setup

  • Codex CLI 0.45.0 or later installed
  • GitHub Actions GITHUB_TOKEN permissions: contents: write, pull-requests: write
  • Codex API key registered as CODEX_API_KEY in Repository Secrets

Security Best Practices

ConfigurationRecommended ValueRationale
Trigger Conditionif: github.event.issue.pull_request && contains(github.event.comment.body, '/codex-plan')Prevent execution from malicious comments
Permission ScopeMinimum privilege (write only for PR updates)Restrict unnecessary operations
API Key StorageSecrets (Environment Secrets recommended)Prevent log leakage

Basic Workflow Implementation

.github/workflows/codex-plan.yml:

name: Codex Plan Mode Auto-Review

on:
  issue_comment:
    types: [created]

jobs:
  generate-plan:
    if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/codex-plan') }}
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.issue.pull_request.head.ref }}

      - name: Setup Codex CLI
        run: |
          curl -fsSL https://codex.cli/install.sh | sh
          echo "$HOME/.codex/bin" >> $GITHUB_PATH

      - name: Generate execution plan
        env:
          CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }}
          COMMENT_BODY: ${{ github.event.comment.body }}
        run: |
          PROMPT="${COMMENT_BODY#/codex-plan }"
          codex --plan "$PROMPT" > plan_output.txt 2>&1 || echo "Plan generation failed" > plan_output.txt

      - name: Post plan as comment
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const plan = fs.readFileSync('plan_output.txt', 'utf8');
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `## Codex Execution Plan\n\n\`\`\`\n${plan}\n\`\`\`\n\nAfter review approval, execute this plan with \`/codex-execute\`.`
            });

Operation Flow: 1. Enter /codex-plan refactor implementation in PR comment 2. GitHub Actions auto-starts and executes plan mode 3. Execution plan is auto-posted as PR comment 4. Reviewer verifies plan content

Approval Flow Integration

.github/workflows/codex-execute.yml:

name: Codex Execute After Approval

on:
  issue_comment:
    types: [created]

jobs:
  execute-plan:
    if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/codex-execute') }}
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write

    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.issue.pull_request.head.ref }}

      - name: Check approval status
        id: check-approval
        uses: actions/github-script@v7
        with:
          script: |
            const reviews = await github.rest.pulls.listReviews({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.issue.number
            });
            const approved = reviews.data.some(r => r.state === 'APPROVED');
            if (!approved) {
              core.setFailed('PR is not approved');
            }
            return approved;

      - name: Execute Codex
        if: steps.check-approval.outputs.result == 'true'
        env:
          CODEX_API_KEY: ${{ secrets.CODEX_API_KEY }}
        run: |
          PROMPT=$(git log -1 --grep="codex-plan" --format=%B | sed 's/\/codex-plan //g')
          codex "$PROMPT"

      - name: Commit changes
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add .
          git commit -m "chore: apply codex changes [skip ci]" || echo "No changes"
          git push

Safety Mechanisms: - Mandatory approval status check (fails immediately if not approved) - Original prompt restoration from git log (ensures consistency with execution plan) - [skip ci] prevents infinite loops

Error Handling and Failure Patterns

SymptomCauseImmediate ActionPrevention
Plan generation timeoutLarge codebase analysisSet timeout-minutes: 10Limit file scope in prompt
Merge conflict during executionBase branch updated by other PR mergeAdd git pull --rebase before executionRestrict base updates via branch protection rules
API Key authentication failureSecrets expirationCheck error logs with manual executionSet up periodic Secret renewal alerts
Execution plan/result mismatchPrompt string modificationSave prompt to artifact for reuseImplement accurate extraction logic from PR comment body

Rollback Strategy:

- name: Create rollback point
  run: git tag "rollback-${{ github.run_id }}"

- name: Execute with rollback
  run: |
    codex "$PROMPT" || {
      git reset --hard "rollback-${{ github.run_id }}"
      exit 1
    }

Benchmark

Manual vs Automated time comparison (medium-sized repo, 10-file change scenario):

ProcessManualAutomatedReduction
Execution plan generation3 min (incl. local setup)1.5 min50%
Share with reviewers5 min (Slack post + explanation)0 min (auto-comment)100%
Post-approval execution2 min (manual execution + push)1 min (automated)50%
Total10 min2.5 min75% reduction

Additional Benefits: - Zero human errors (prompt typos, forgotten pushes) - History traceability (all execution plans recorded in PR comments)

Automation Extension Ideas

Slack Notification Integration

- name: Notify Slack
  if: always()
  uses: slackapi/slack-github-action@v1
  with:
    payload: |
      {
        "text": "Codex Plan: ${{ job.status }}",
        "blocks": [
          {
            "type": "section",
            "text": {"type": "mrkdwn", "text": "Review execution plan for PR #${{ github.event.issue.number }}"}
          }
        ]
      }
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

Multi-Branch Support

  • Parallel execution across multiple branches using matrix strategy
  • Dynamic Codex configuration switching by branch name (different approval policies for staging/production)

Cost Monitoring

  • Send CODEX_API_KEY usage metrics to CloudWatch
  • Set monthly execution count threshold alerts

Next Steps