|
| 1 | +--- |
| 2 | +description: Automatically fix tests in CI using an AI Agent and the MCP Server |
| 3 | +sidebar_position: 2 |
| 4 | +--- |
| 5 | + |
| 6 | +# Self-healing Pipelines |
| 7 | + |
| 8 | +This page shows how to implement self-healing CI pipelines using an AI agent and the [Semaphore MCP server](./mcp-server). If you need a more tailored solution, please get in touch with support, and we can help you set up a self-healing workflow for your projects. |
| 9 | + |
| 10 | +## Overview |
| 11 | + |
| 12 | +AI Agents such as OpenAI Codex or Claude Code can diagnose and fix test errors inside your CI. When coupled with Semaphore's MCP server, these agents can implement, push fixes, and create pull requests automatically when a build fails. |
| 13 | + |
| 14 | +Self-healing pipelines solve the often tedious process of figuring out why tests run in your machine but fail in the CI. If the build fails, you can expect to have a PR with the fix ready to merge. |
| 15 | + |
| 16 | +The self-healing process works in this way: |
| 17 | + |
| 18 | +1. You have a regular CI pipeline that builds and tests your application |
| 19 | +2. You add a [promotion](../promotions) that triggers the self-heal pipeline when the CI fails |
| 20 | +3. The self-heal pipeline spins up an AI agent. The agent pulls the job logs using Semaphore's MCP and implements a fix |
| 21 | +4. The self-heal pipeline pushes the fixed code into a separate branch |
| 22 | +5. The push triggers a new CI build. If the pipeline passes, a PR is automatically submitted to GitHub for your evaluation |
| 23 | + |
| 24 | + |
| 25 | + |
| 26 | +## Prerequisites |
| 27 | + |
| 28 | +- Semaphore [MCP Server](./mcp-server) enabled and configured in your organization |
| 29 | +- A [GitHub Personal Access Token](https://github.com/settings/tokens) with write permissions on the repository |
| 30 | +- An API token for your AI Agent of choice |
| 31 | + |
| 32 | +## Preventing build loops |
| 33 | + |
| 34 | +Whenever we push into the repository from inside the CI environment, we risk entering into a loop. In this solution, we present two mechanisms: |
| 35 | + |
| 36 | +- Always run the self-heal pipeline manually, i.e., without [autopromotion](../promotions#automatic-promotions) |
| 37 | +- Enable autopromotions, but use [conditions](../../reference/conditions-dsl) to avoid triggering on branches created by previous self-heal runs |
| 38 | + |
| 39 | +## Preparation |
| 40 | + |
| 41 | +Before you can set up self-healing pipelines, there are a few preparation tasks. |
| 42 | + |
| 43 | +### Enable MCP Server |
| 44 | + |
| 45 | +1. Enable the [MCP Server](./mcp-server) in your Semaphore organization, so the agent can pull build data and job logs. |
| 46 | + |
| 47 | +2. Create or obtain a Semaphore API token to connect with the MCP Server. Both [personal tokens](../user-management#profile-token) and [service accounts](../service-accounts) work as API tokens |
| 48 | + |
| 49 | +3. Create a [secret](../secrets) called `semaphore-mcp` with the environment variable `SEMAPHORE_API_TOKEN` to store your Semahore token |
| 50 | + |
| 51 | +### Obtain API Token and configure Codex |
| 52 | + |
| 53 | +In this example, we'll use OpenAI Codex, but you can easily swap the agent if you're using a different service. |
| 54 | + |
| 55 | +1. Obtain an OpenAI API Token |
| 56 | + |
| 57 | +2. Create a [secret](../secrets) named `openai-api` with the environment variable `OPENAI_API_KEY` to store your OpenAI API token |
| 58 | + |
| 59 | +3. Create a directory in your repository called `selfheal/codex`: `mkdir -p selfheal/codex` |
| 60 | + |
| 61 | +4. Add the following Codex configuration file to `selfheal/codex/config.toml` |
| 62 | + |
| 63 | + ```toml title="Codex configuration" |
| 64 | + full-auto = true |
| 65 | + bypass-approvals = true |
| 66 | + bypass-sandbox = true |
| 67 | + trusted-workspace = true |
| 68 | + |
| 69 | + [mcp_servers.semaphore] |
| 70 | + url = "https://mcp.semaphoreci.com/mcp" |
| 71 | + bearer_token_env_var = "SEMAPHORE_API_TOKEN" |
| 72 | + startup_timeout_sec = 30 |
| 73 | + tool_timeout_sec = 300 |
| 74 | + ``` |
| 75 | + |
| 76 | +5. Create a prompt template file. This is a basic prompt that can be augmented to fit your project's needs |
| 77 | + |
| 78 | + ```text title="Minimal prompt template for the AI Agent" |
| 79 | + Find out why the Semaphore in the following pipeline has failed and implement a fix. Analyze all the jobs that have failed and fix all the errors one at a time. |
| 80 | + |
| 81 | + Organization ID: $SEMAPHORE_ORGANIZATION_ID |
| 82 | + Project ID: $SEMAPHORE_PROJECT_ID |
| 83 | + Pipeline ID: $SEMAPHORE_PIPELINE_ID |
| 84 | + Workflow ID: $SEMAPHORE_WORKFLOW_ID |
| 85 | + |
| 86 | + When done, create a file called `commit-message.txt` with a one-line summary of changes suitable for a Git commit message. |
| 87 | + ``` |
| 88 | + |
| 89 | +6. Push the `selfheal` directory and its contents to your GitHub repository |
| 90 | + |
| 91 | +### Obtain a GitHub Access Token |
| 92 | + |
| 93 | +By default, the CI machine does not have write access to the repository. We need an additional API token to write from inside the CI environment. |
| 94 | + |
| 95 | +1. Create a [Personal Access Token](https://github.com/settings/tokens) (classic) in GitHub with: |
| 96 | + |
| 97 | + - write permissions to the repository |
| 98 | + - permissions to create pull requests in the repository |
| 99 | + |
| 100 | +  |
| 101 | + |
| 102 | +2. Create a [secret](../secrets) called `github-pat` with the environment variable `GITHUB_TOKEN` to store your GitHub token |
| 103 | + |
| 104 | +## Set up Self-healing Pipelines |
| 105 | + |
| 106 | +The setup of self-healing pipelines can be split into two parts: |
| 107 | + |
| 108 | +- Agentic fix: here we use an AI agent to diagnose the problem and push a potential solution |
| 109 | +- Validation and PR: here we validate the solution in CI and, if effective, create a pull request for review |
| 110 | + |
| 111 | +Once the two pipelines are configured, use your CI as usual. The setup is complete and will work on any branch that doesn't start with the name `selfheal-`. |
| 112 | + |
| 113 | +### Agentic Fix Pipeline |
| 114 | + |
| 115 | +In this first step, we'll configure OpenAI's Codex to diagnose the problem and propose a solution when the CI pipeline fails. This self-healing pipeline creates a branch called `selfheal-${GIT_SHA}` to track changes made by the AI agent. |
| 116 | + |
| 117 | +<Steps> |
| 118 | + |
| 119 | +1. Open the project in the workflow editor |
| 120 | + |
| 121 | +2. Press **+Add Promotion** |
| 122 | + |
| 123 | +3. Optionally, enable **Automatic promotion** and type `result = 'failed' AND branch !~ '^selfheal-.*'`. |
| 124 | + |
| 125 | + :::note |
| 126 | + |
| 127 | + This makes the self-healing pipeline start automatically when the main CI fails for any reason. |
| 128 | + |
| 129 | + ::: |
| 130 | + |
| 131 | +  |
| 132 | + |
| 133 | +4. Type the following commands in the **prologue** of the first block in the new pipeline. These commands create the solution branch and configure the repository to be writable |
| 134 | + |
| 135 | + |
| 136 | + ```shell title="Configuring Git to be writable and setting up the solution branch" |
| 137 | + export SELFHEAL_BRANCH=selfheal-${SEMAPHORE_GIT_SHA} |
| 138 | + checkout |
| 139 | + git config --global user.email "[email protected]" |
| 140 | + git config --global user.name "Semaphore CI" |
| 141 | + git remote set-url origin https://$GITHUB_TOKEN:[email protected]/${SEMAPHORE_GIT_REPO_SLUG}.git |
| 142 | + git checkout -b "$SELFHEAL_BRANCH" |
| 143 | + ``` |
| 144 | + |
| 145 | +5. In the job, add the following commands. These configure Codex and push the solution to the repository |
| 146 | + |
| 147 | + |
| 148 | + ```shell title="Configuring and running Codex to solve build errors" |
| 149 | + mkdir -p $HOME/.codex |
| 150 | + cp selfheal/codex/config.toml $HOME/.codex |
| 151 | + npm install -g @openai/codex |
| 152 | + printenv OPENAI_API_KEY | codex login --with-api-key |
| 153 | + codex exec --dangerously-bypass-approvals-and-sandbox "$(envsubst < selfheal/prompt-template.txt)" |
| 154 | + mv commit-message.txt /tmp |
| 155 | + cache store commit-message-$SELFHEAL_BRANCH /tmp/commit-message.txt |
| 156 | + git add -A |
| 157 | + git commit -m "selfheal CI: $(cat /tmp/commit-message.txt)" |
| 158 | + git push origin "$SELFHEAL_BRANCH" |
| 159 | + ``` |
| 160 | + |
| 161 | +6. Save the changes |
| 162 | + |
| 163 | +</Steps> |
| 164 | + |
| 165 | +### Validate and Create PR Pipeline |
| 166 | + |
| 167 | +The second pipeline only creates a pull request if the AI agent successfully fixed the CI. |
| 168 | + |
| 169 | +<Steps> |
| 170 | + |
| 171 | +1. Open the project in the workflow editor |
| 172 | + |
| 173 | +2. Press **+Add Promotion** |
| 174 | + |
| 175 | +3. Optionally, enable **Automatic promotion** and type `result = 'passed' AND branch =~ '^selfheal-.*'` |
| 176 | + |
| 177 | + :::note |
| 178 | + |
| 179 | + This makes the PR pipeline start automatically when the main CI builds successfully on a self-healed workflow. |
| 180 | + |
| 181 | + ::: |
| 182 | + |
| 183 | +  |
| 184 | + |
| 185 | +4. Type the following commands in the **prologue** of the first block in the new pipeline. These commands check out the solution branch and configure the repository to be writable |
| 186 | + |
| 187 | + ```shell title="Checkout the self-healed branch and make the repository writeable" |
| 188 | + checkout |
| 189 | + git config --global user.email "[email protected]" |
| 190 | + git config --global user.name "Semaphore CI" |
| 191 | + git remote set-url origin https://$GITHUB_TOKEN:[email protected]/${SEMAPHORE_GIT_REPO_SLUG}.git |
| 192 | + git fetch origin "$SEMAPHORE_GIT_BRANCH" |
| 193 | + git checkout "$SEMAPHORE_GIT_BRANCH" |
| 194 | + git pull origin "$SEMAPHORE_GIT_BRANCH" |
| 195 | + cache restore commit-message-$SEMAPHORE_GIT_BRANCH |
| 196 | + ``` |
| 197 | + |
| 198 | +5. In the job, add the following commands. These create the pull request on GitHub using the gh CLI |
| 199 | + |
| 200 | + ```shell title="Create Pull Request on GitHub" |
| 201 | + gh pr create --base master --title "Selfheal CI: $(cat /tmp/commit-message.txt)" --body "PR created by self-heal CI: $(cat /tmp/commit-message.txt)" |
| 202 | + ``` |
| 203 | + |
| 204 | +6. Save your changes and use your pipeline as usual |
| 205 | + |
| 206 | +</Steps> |
| 207 | + |
| 208 | +## See also |
| 209 | + |
| 210 | +- [MCP Server](./mcp-server) |
| 211 | + |
| 212 | + |
| 213 | + |
| 214 | + |
| 215 | + |
| 216 | + |
| 217 | + |
| 218 | + |
| 219 | + |
| 220 | + |
0 commit comments