Continuous Integration
Pattern: A named solution to a recurring problem.
Merge everyone’s work into a shared mainline frequently and validate each merge automatically with builds and tests, so integration never becomes painful.
Also known as: CI
If you’ve watched a row of checks turn green on a pull request before merging it, you’ve used continuous integration. The checks are only the visible part. Underneath them is a practice older and stricter than any CI service: the shared mainline is never allowed to stay broken. Grady Booch named it in the early 1990s, and Kent Beck’s Extreme Programming turned it into a daily habit.
Understand This First
• Version Control — CI is triggered by version control events.
Context
This is an operational pattern that builds on Version Control and feeds into Deployment. Continuous integration is the practice of merging all developers’ work into a shared mainline frequently (at least daily) and validating each merge automatically with builds and tests. The idea is simple: if integrating code is painful, do it more often until it isn’t.
Agents make CI carry more weight. They generate large amounts of code quickly, and that code needs the same validation as hand-written code. It needs more when nobody has read every line.
Problem
Developers work on separate branches for days or weeks. When they finally merge, the conflicts are enormous and the interactions between changes are unpredictable. Bugs hide in the gaps between components that were developed in isolation. Integration becomes a dreaded, multi-day event. How do you keep a codebase healthy and integrated when multiple people are changing it simultaneously?
Forces
• Long-lived branches accumulate merge conflicts and hidden incompatibilities.
• Running the full test suite manually before every merge is tedious and easy to skip.
• Broken builds block everyone, creating pressure to either skip validation or delay integration.
• Different developers (and agents) may introduce changes that individually work but collectively conflict.
• A check that reports a failure isn’t the same as a check that blocks a merge, and the difference lives in repository settings that few people read.
Solution
Merge to the shared mainline frequently, ideally multiple times per day, and run automated validation on every merge. This validation typically includes compiling the code, running unit and integration tests, checking code style, and performing static analysis. If any check fails, the build is “broken” and fixing it becomes the top priority.
Set up a CI server (GitHub Actions, GitLab CI, Jenkins, CircleCI, or similar) that automatically triggers on every push or pull request. The CI pipeline should be fast enough that developers get feedback within minutes, not hours. If the full test suite takes too long, run a fast subset on every push and the full suite on a schedule.
The key discipline is that the main branch should always be in a working state. If a merge breaks the build, it gets fixed immediately, not left for someone else to deal with. This requires cultural commitment as much as tooling.
With agents in the loop, CI is the automated gate between what an agent writes and what lands on the mainline. That gate holds only when three things are true. The checks run on every change. The repository requires them to pass before it allows a merge. And the revision the checks tested is the revision that lands. Miss any one and the green check is a report, not a gate.
The second condition is the one teams most often assume rather than configure. A workflow that runs and posts a result is informational: anyone with merge rights can still merge past a red build. It becomes a gate only when the target branch’s protection rules or rulesets name that check as required.
Skips need the same deliberate design. On GitHub, a skipped or neutral result can count as passing, so a job skipped by a condition satisfies its required check without testing anything. A workflow skipped by a path filter does the opposite: its required check stays pending and the pull request can’t merge at all. One lets untested code through and the other blocks good code.
The third condition is about which code was tested. Ordinary pull-request CI tests the branch head, or a merge of that branch with the mainline as it stood when the run started. If other changes land in the meantime, the tested combination no longer exists. GitLab draws this line explicitly, separating merge-request pipelines that test the source branch from merged-results pipelines that test the combined result. When several changes wait to land at once, as they do when several agents work in parallel, a Merge Queue closes the gap by testing each candidate against the changes ahead of it. Wire your required checks to the queue as well as to pull requests: GitHub Actions workflows need the merge_group trigger, and GitLab merge trains run on merged-results pipelines.
With all three conditions in place, you can let agents work boldly. The mainline only sees code that passed the checks you chose, in the combination that actually landed.
How It Plays Out
A team with three developers and one AI agent merges to main four to six times per day. Each push triggers a GitHub Actions workflow that runs tests in under five minutes, and branch protection on main lists the test job as a required check. When the agent’s generated code introduces a failing test, the merge button stays disabled until the agent fixes it. The broken code never reaches main.
A team without CI merges a week’s worth of changes on Friday. Two developers modified the same service with incompatible assumptions. The merge succeeds (no textual conflicts) but the application crashes on startup. The team spends their weekend debugging interaction effects that would have been caught immediately if they had integrated daily.
Months later, the first team asks its agent to make that workflow faster. The agent adds a condition so the test job runs only when files under src/ change. The next week, a pull request touches nothing but a database migration. The test job is skipped, GitHub reports the skip as a success, the required check passes, and the migration breaks staging. Nothing in the pull request ever showed red. The repair keeps the required job unconditional and moves the speedup inside it, using Test Impact Analysis to choose which tests run rather than whether the job runs at all.
Tip: A good CI pipeline is fast. If it takes more than ten minutes, developers will start working around it: pushing without waiting for results, merging despite failures. Invest in making CI fast before making it comprehensive.
Example Prompt: “Create a CI workflow that runs on every pull request: install dependencies, run the linter, run the type checker, and run the test suite. Fail the PR if any step fails. Target total run time under five minutes. Then list the exact check names I need to mark as required on the main branch so a failure blocks the merge.”
Consequences
Continuous integration keeps the codebase in a consistently working state. Integration problems surface immediately, when they are small and easy to fix. The team moves faster because merging is routine rather than risky. CI also produces a stream of verified artifacts that feed into Continuous Delivery and Deployment.
The cost is building and maintaining the CI pipeline, and the discipline of keeping it green. Flaky tests (tests that pass or fail unpredictably) are the bane of CI, because they erode trust in the system. A team that ignores red builds has CI in name only, and so does a team whose red builds can still merge.
The gate is also only as good as its configuration. Required-check lists, skip conditions, and queue triggers drift as workflows change, and an agent asked to make CI faster or quieter can weaken them without touching a single test. Keep the workflow files in version control as Pipeline as Code and review changes to them as carefully as changes to the code they protect.
Related Articles
Complements: Git Checkpoint — CI validates the code at each checkpoint.
Depended on by: Pipeline Synthesis — Pipeline Synthesis depends on this.
Depends on: Version Control — CI is triggered by version control events.
Enabled by: Pipeline as Code — Pipeline as Code is part of what makes this pattern work.
Enabled by: Small Batches — Small Batches keeps each change small enough to finish and integrate at least daily.
Enables: Continuous Delivery — CI is the foundation that makes continuous delivery possible.
Enables: Continuous Deployment — CI produces the validated artifacts that continuous deployment ships automatically.
Enables: Deployment — CI produces validated artifacts ready for deployment.
Extended by: Merge Queue — A merge queue extends the always-green guarantee to concurrent changes by testing each candidate against the changes ahead of it.
Instance of: Feedback Loop
Used by: Evaluation Gate — CI supplies the per-change trigger that runs the eval suite behind an evaluation gate.
Uses: Environment — CI runs in its own dedicated environment.
Uses: Test Impact Analysis — Continuous integration is where the selected slice runs on every push.
Sources
• Grady Booch, Object-Oriented Analysis and Design with Applications (2nd ed., Benjamin/Cummings, 1994). Coined the phrase “continuous integration,” describing how micro-process releases create “a sort of continuous integration of the system.” Booch used it as an observation, not a formalized practice.
• Kent Beck, Extreme Programming Explained: Embrace Change (Addison-Wesley, 1999). Adopted continuous integration as one of the twelve core practices of Extreme Programming, developed on the Chrysler C3 project starting in 1996. Beck advocated integrating multiple times per day, turning Booch’s observation into a discipline.
• Martin Fowler and Matt Foemmel, “Continuous Integration”, martinfowler.com (first published 2000; substantially rewritten 2006; revised 2024). The seminal practitioner reference and canonical description of how CI works in practice.
• Matt Foemmel and others at ThoughtWorks, CruiseControl (2001). The first widely available CI server. CruiseControl made automated build-on-every-commit practical for ordinary teams and spawned a generation of CI tools including Hudson, Jenkins, and Travis CI.
• Jez Humble and David Farley, Continuous Delivery (Addison-Wesley, 2010). Extended CI into a complete deployment pipeline, connecting automated integration to automated testing, staging, and release.
• DORA, Continuous integration capability guide, dora.dev. The current research-program definition: trunk-based development in small batches, automated tests before and after merge, and immediate repair or reversion of a broken build.
• GitHub’s documentation on status checks and troubleshooting required status checks describes the difference between informational and required checks, when skipped and neutral results count as passing, why path-filtered workflows leave required checks pending, and the merge_group trigger that merge queues need.
• GitLab’s documentation on merge request pipelines distinguishes pipelines that test the source branch from merged-results pipelines that test the combined source and target, the basis of GitLab merge trains.