Skip to content

What is continuous integration (CI)?

Continuous integration is merging every developer's changes into the main branch often, with an automated build and tests run on each merge.

Last updated , 8 min read

What is continuous integration (CI)?

Continuous integration (CI) is a team practice in which each developer's work joins the main branch often and is built and tested automatically. Because each merge is small, a failed build points to a change made hours ago, not weeks ago. CI is the first half of CI/CD.

The International Software Testing Qualifications Board (ISTQB) defines continuous integration as an automated procedure that merges, integrates, and tests all changes as soon as they are committed. Martin Fowler defines it as a team habit instead, in which each member of a team merges their work with everyone else's at least daily. Under Fowler's definition, a server that builds feature branches kept apart for days runs automated builds, but the team is not doing continuous integration.

The habit keeps integration cheap. When branches merge only after weeks, their conflicts appear together at merge time, and it is hard to tell which change caused a failure.

Continuous integration is not the same as integration testing, which checks that separate parts of a system work together, although a CI build often runs integration tests.

How does continuous integration work?

Continuous integration repeats the same loop for each change:

  1. A developer or a coding agent starts a short branch from the main branch and makes one small change.
  2. The author runs the fast tests locally and opens a pull request.
  3. A CI server checks out the change, usually on a fresh machine, builds it, and runs the unit tests and other checks.
  4. The CI server reports the result on the pull request, and the author fixes any failure.
  5. The change merges, and the CI server builds and tests the main branch again.
  6. If that build fails, the team fixes it or reverts the change before anyone merges more work.

A CI server, also called a CI service, is the software that runs these builds and reports their results, e.g. GitHub Actions.

Small branches merged and tested often main Developer a few hours Coding agent under an hour Developer a few hours Build, test passes Build, test passes Build, test fails Fix or revert before more work
Each branch lives for a few hours or less, and the agent's branch merges while a developer's branch is still open. The CI service builds and tests main after each merge, and a failed build is fixed or reverted before more work merges.

The loop depends on these practices:

  • One shared main branch. Each change ends up on the main branch of one repository.
  • A build that tests itself. One command builds the software and runs its tests, and each change adds tests for the behavior it changes.
  • Daily merges. Each developer merges into the main branch at least once a day. Unfinished work can merge behind a feature flag, a setting that keeps that code switched off for customers.
  • Broken builds come first. More work on a broken main branch hides later failures behind the first one.
  • A fast build. A slow build makes people merge less often, so teams run quick checks first and slow tests in a later stage.

What is an example of continuous integration?

Here is an illustrative example. Acme Co. sells furniture online, and its developers merge into main several times a day. A developer at Acme asks a coding agent to "Let customers edit their delivery address during checkout." The change reaches main in these steps:

  1. The agent starts a branch from main, edits the checkout code, and adds a test that the cart keeps its 2 items.
  2. The agent runs npm test locally, and the 52 tests pass.
  3. Meanwhile, a teammate merges a change that recalculates the delivery cost when the address changes. Its CI run passes.
  4. The agent opens a pull request, and the CI service tests the branch merged with the updated main.
  5. The agent's cart test fails on the combined code, because the cost recalculation reloads the order from the record that the agent's address code replaced. The address saved, but the cart emptied.
  6. The developer pastes the failure into the agent's session, and the agent fixes the address code.
  7. The next run passes, the change merges the same day, and the build on main passes.

The CI log showed this failure:

FAIL tests/checkout.test.js
  ● checkout › keeps the cart when the address changes
    expect(received).toHaveLength(expected)
    Expected length: 2
    Received length: 0
    Received array:  []

Git merged the two changes without a merge conflict, because they touched different files. Fowler calls this break a semantic conflict, and CI found it the same day both changes were made. This example is simplified. A real pipeline would also start the web store and test checkout in a browser.

What changes when a coding agent writes the code?

A coding agent can finish a branch in minutes, and a team can run several agents at once. Writing code can stop being the slow step, and finished branches wait for code review instead. A branch that waits for days drifts from main. When it merges, it brings back the large, late merges that continuous integration was meant to remove.

Parallel agents add to the drift. Several agents can start from the same commit of main, each in its own copy of the repository. A branch gets the other agents' changes only after they merge and the branch is updated from main. More open branches also mean more CI runs, which is why CI can become the bottleneck for AI-written code.

A practical adjustment is to give each agent a task small enough to merge the same day. A branch that waits longer gets updated from main and tested again before it merges.

What are the limits of continuous integration?

Continuous integration keeps the main branch built and tested, but it has limits:

  • A green build shows only that the checks passed. A test can pass while the software is broken, which is called a false pass. CI works as regression testing only for the behavior its tests cover.
  • A pull request check can go stale. In GitHub Actions, a pull request run tests the branch merged with main as it stood at that moment. A later change to main does not rerun it, so two green pull requests can still break main together. A merge queue closes that gap by testing each change on top of main and the changes ahead of it in the queue. Requiring each branch to be up to date with main before it merges also closes the gap, at the cost of more reruns.
  • Flaky tests hide real failures. A flaky test passes and fails on the same code. After a few false alarms, people rerun a red build without reading it, and a real failure can merge.
  • A CI server cannot enforce the habits. The server does not make people merge daily, keep the build fast, or fix a broken build first.

How is continuous integration different from continuous delivery?

Continuous integration ends when a change is merged into the main branch and tested there. Continuous delivery goes further and keeps each passing change packaged and ready to release, so a person can release it with one decision. Continuous deployment goes one step further and releases each passing change automatically. A team can practice CI without continuous delivery. Continuous delivery depends on CI, because a release can only be as ready as the tested main branch behind it.

How do you check that the integrated software works?

A green CI run shows that the build finished and its tests passed. To check the integrated software, start the software built from the main branch and try the workflows the change touched, e.g. checkout after an address change.

In the example, a cart test caught the break, but a workflow that no test covers can break and still pass CI. RunStory runs your software against the change in a separate environment, tries relevant workflows, and checks the results. It sends reproducible failures back to your coding agent while you keep working. It is in private alpha for CLIs and web apps.

Join the RunStory alpha →

FAQs

What is a CI server?

A CI server is the software that checks out each change, builds it, and runs its tests, usually on a fresh machine. It is also called a CI service, and it reports the result where the team works, e.g. on the pull request.

How often should developers integrate?

Developers should integrate at least once a day, which is part of Martin Fowler's definition of continuous integration. Smaller, more frequent merges keep each branch close to the main branch, so conflicts stay small and a failed build points to a short list of recent changes.

Is running a build server the same as doing CI?

Running a build server is not the same as doing CI. The server builds and tests what it receives. Continuous integration also needs the team to merge into the main branch at least daily and to fix a broken build first.

What should a team do when the build breaks?

When the build on the main branch breaks, the team should fix it or revert the change that broke it before anyone merges more work. Until then, each later merge is tested on a broken base, so its own failures are hard to see.