|
| 1 | +{ |
| 2 | + "cells": [ |
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "id": "e2884696", |
| 6 | + "metadata": {}, |
| 7 | + "source": [ |
| 8 | + "# Autofix CI failures on GitHub with Codex CLI\n", |
| 9 | + "\n", |
| 10 | + "## Purpose of this cookbook\n", |
| 11 | + "\n", |
| 12 | + "This cookbook shows you how to embed the OpenAI Codex CLI into your CI/CD pipeline so that when your builds or tests fail, codex automatically generates & proposes fixes. The following is an example in a node project with CI running in GitHub Actions. \n", |
| 13 | + "\n", |
| 14 | + "## End to End Flow\n", |
| 15 | + "\n", |
| 16 | + "Below is the pipeline flow we’ll implement:\n", |
| 17 | + "\n", |
| 18 | + "\n", |
| 19 | + "<img src=\"../../images/ci-codex-workflow.png\" width=\"700\"/>" |
| 20 | + ] |
| 21 | + }, |
| 22 | + { |
| 23 | + "cell_type": "markdown", |
| 24 | + "id": "f83ce964", |
| 25 | + "metadata": {}, |
| 26 | + "source": [ |
| 27 | + "## Prerequisites\n", |
| 28 | + "\n", |
| 29 | + "- A GitHub Repo with Actions workflows\n", |
| 30 | + "\n", |
| 31 | + "- You’ll need to create `OPENAI_API_KEY` as an environment variable in GitHub settings under https://github.com/{org-name}/{repo-name}/settings/secrets/actions. You can also set this at org level(for sharing secrets across multiple repos) \n", |
| 32 | + "\n", |
| 33 | + "- Codex requires python as a prerequisite to use `codex login`\n", |
| 34 | + "\n", |
| 35 | + "- You’ll need to check the setting to enable actions to create PRs on your repo, and also in your organization:\n", |
| 36 | + "\n", |
| 37 | + "\n", |
| 38 | + "<img src=\"../../images/github-pr-settings.png\" width=\"700\"/>\n" |
| 39 | + ] |
| 40 | + }, |
| 41 | + { |
| 42 | + "cell_type": "markdown", |
| 43 | + "id": "99f5bed1", |
| 44 | + "metadata": {}, |
| 45 | + "source": [ |
| 46 | + "\n", |
| 47 | + "## Step 1: Add the Github Action to your CI Pipeline\n", |
| 48 | + "\n", |
| 49 | + "The following YAML shows a GitHub action that auto triggers when CI fails, installs Codex, uses codex exec and then makes a PR on the failing branch with the fix. Replace \"CI\" with the name of the workflow you want to monitor. " |
| 50 | + ] |
| 51 | + }, |
| 52 | + { |
| 53 | + "cell_type": "markdown", |
| 54 | + "id": "a9f9b368", |
| 55 | + "metadata": {}, |
| 56 | + "source": [ |
| 57 | + "```yaml\n", |
| 58 | + "name: Codex Auto-Fix on Failure\n", |
| 59 | + "\n", |
| 60 | + "on:\n", |
| 61 | + " workflow_run:\n", |
| 62 | + " # Trigger this job after any run of the primary CI workflow completes\n", |
| 63 | + " workflows: [\"CI\"]\n", |
| 64 | + " types: [completed]\n", |
| 65 | + "\n", |
| 66 | + "permissions:\n", |
| 67 | + " contents: write\n", |
| 68 | + " pull-requests: write\n", |
| 69 | + "\n", |
| 70 | + "jobs:\n", |
| 71 | + " auto-fix:\n", |
| 72 | + " # Only run when the referenced workflow concluded with a failure\n", |
| 73 | + " if: ${{ github.event.workflow_run.conclusion == 'failure' }}\n", |
| 74 | + " runs-on: ubuntu-latest\n", |
| 75 | + " env:\n", |
| 76 | + " OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\n", |
| 77 | + " FAILED_WORKFLOW_NAME: ${{ github.event.workflow_run.name }}\n", |
| 78 | + " FAILED_RUN_URL: ${{ github.event.workflow_run.html_url }}\n", |
| 79 | + " FAILED_HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}\n", |
| 80 | + " FAILED_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}\n", |
| 81 | + " steps:\n", |
| 82 | + " - name: Check OpenAI API Key Set\n", |
| 83 | + " run: |\n", |
| 84 | + " if [ -z \"$OPENAI_API_KEY\" ]; then\n", |
| 85 | + " echo \"OPENAI_API_KEY secret is not set. Skipping auto-fix.\" >&2\n", |
| 86 | + " exit 1\n", |
| 87 | + " fi\n", |
| 88 | + " - name: Checkout Failing Ref\n", |
| 89 | + " uses: actions/checkout@v4\n", |
| 90 | + " with:\n", |
| 91 | + " ref: ${{ env.FAILED_HEAD_SHA }}\n", |
| 92 | + " fetch-depth: 0\n", |
| 93 | + "\n", |
| 94 | + " - name: Setup Node.js\n", |
| 95 | + " uses: actions/setup-node@v4\n", |
| 96 | + " with:\n", |
| 97 | + " node-version: '20'\n", |
| 98 | + " cache: 'npm'\n", |
| 99 | + "\n", |
| 100 | + " - name: Install dependencies\n", |
| 101 | + " run: |\n", |
| 102 | + " if [ -f package-lock.json ]; then npm ci; else npm i; fi\n", |
| 103 | + " - name: Run Codex\n", |
| 104 | + " uses: openai/codex-action@main\n", |
| 105 | + " id: codex\n", |
| 106 | + " with:\n", |
| 107 | + " openai_api_key: ${{ secrets.OPENAI_API_KEY }}\n", |
| 108 | + " prompt: \"You are working in a Node.js monorepo with Jest tests and GitHub Actions. Read the repository, run the test suite, identify the minimal change needed to make all tests pass, implement only that change, and stop. Do not refactor unrelated code or files. Keep changes small and surgical.\"\n", |
| 109 | + " codex_args: '[\"--config\",\"sandbox_mode=\\\"workspace-write\\\"\"]'\n", |
| 110 | + "\n", |
| 111 | + " - name: Verify tests\n", |
| 112 | + " run: npm test --silent\n", |
| 113 | + "\n", |
| 114 | + " - name: Create pull request with fixes\n", |
| 115 | + " if: success()\n", |
| 116 | + " uses: peter-evans/create-pull-request@v6\n", |
| 117 | + " with:\n", |
| 118 | + " commit-message: \"fix(ci): auto-fix failing tests via Codex\"\n", |
| 119 | + " branch: codex/auto-fix-${{ github.event.workflow_run.run_id }}\n", |
| 120 | + " base: ${{ env.FAILED_HEAD_BRANCH }}\n", |
| 121 | + " title: \"Auto-fix failing CI via Codex\"\n", |
| 122 | + " body: |\n", |
| 123 | + " Codex automatically generated this PR in response to a CI failure on workflow `${{ env.FAILED_WORKFLOW_NAME }}`.\n", |
| 124 | + " Failed run: ${{ env.FAILED_RUN_URL }}\n", |
| 125 | + " Head branch: `${{ env.FAILED_HEAD_BRANCH }}`\n", |
| 126 | + " This PR contains minimal changes intended solely to make the CI pass.\n", |
| 127 | + "```\n" |
| 128 | + ] |
| 129 | + }, |
| 130 | + { |
| 131 | + "cell_type": "markdown", |
| 132 | + "id": "8148024b", |
| 133 | + "metadata": {}, |
| 134 | + "source": [ |
| 135 | + "## Step 2: Actions Workflow kicked off\n", |
| 136 | + "\n", |
| 137 | + "You can navigate to the Actions tab under Repo to view the failing jobs in your Actions workflow. \n", |
| 138 | + "\n", |
| 139 | + "<img src=\"../../images/failing-workflow.png\" width=\"700\"/>\n" |
| 140 | + ] |
| 141 | + }, |
| 142 | + { |
| 143 | + "cell_type": "markdown", |
| 144 | + "id": "64671aae", |
| 145 | + "metadata": {}, |
| 146 | + "source": [ |
| 147 | + "The Codex workflow should be triggered upon completion of the failed workflow. \n", |
| 148 | + "\n", |
| 149 | + "\n", |
| 150 | + "<img src=\"../../images/codex-workflow.png\" width=\"700\"/>\n", |
| 151 | + "\n" |
| 152 | + ] |
| 153 | + }, |
| 154 | + { |
| 155 | + "cell_type": "markdown", |
| 156 | + "id": "d08a3ecc", |
| 157 | + "metadata": {}, |
| 158 | + "source": [ |
| 159 | + "## Step 3: Verify that Codex Created a PR for Review\n", |
| 160 | + "And after the Codex workflow completes execution, it should open a pull request from the feature branch codex/auto-fix. Check to see if everything looks good and then merge it.\n", |
| 161 | + "\n", |
| 162 | + "<img src=\"../../images/codex-pr.png\" width=\"700\"/>\n", |
| 163 | + "\n" |
| 164 | + ] |
| 165 | + }, |
| 166 | + { |
| 167 | + "cell_type": "markdown", |
| 168 | + "id": "f4c1f3a0", |
| 169 | + "metadata": {}, |
| 170 | + "source": [ |
| 171 | + "## Conclusion\n", |
| 172 | + "\n", |
| 173 | + "This automation seamlessly integrates OpenAI Codex CLI with GitHub Actions to automatically propose fixes for failing CI runs.\n", |
| 174 | + "\n", |
| 175 | + "By leveraging Codex, you can reduce manual intervention, accelerate code reviews, and keep your main branch healthy. The workflow ensures that test failures are addressed quickly and efficiently, letting developers focus on higher-value tasks. Explore more about codex-cli and its capabilities [here](https://github.com/openai/codex/)." |
| 176 | + ] |
| 177 | + } |
| 178 | + ], |
| 179 | + "metadata": { |
| 180 | + "kernelspec": { |
| 181 | + "display_name": "Python 3", |
| 182 | + "language": "python", |
| 183 | + "name": "python3" |
| 184 | + }, |
| 185 | + "language_info": { |
| 186 | + "codemirror_mode": { |
| 187 | + "name": "ipython", |
| 188 | + "version": 3 |
| 189 | + }, |
| 190 | + "file_extension": ".py", |
| 191 | + "mimetype": "text/x-python", |
| 192 | + "name": "python", |
| 193 | + "nbconvert_exporter": "python", |
| 194 | + "pygments_lexer": "ipython3", |
| 195 | + "version": "3.13.7" |
| 196 | + } |
| 197 | + }, |
| 198 | + "nbformat": 4, |
| 199 | + "nbformat_minor": 5 |
| 200 | +} |
0 commit comments