Continuous Integration
Continuous integration requires daily code integration to trunk with automated testing. Learn CI best practices, testing strategies, and team workflows that improve software quality and delivery speed.
Definition
Continuous Integration (CI) is the activity of each developer integrating work to the trunk of version control at least daily and verifying that the work is, to the best of our knowledge, releasable.
CI is not just about tooling—it’s fundamentally about team workflow and working agreements.
The minimum activities required for CI
- Trunk-based development - all work integrates to trunk
- Work integrates to trunk at a minimum daily (each developer, every day)
- Work has automated testing before merge to trunk
- Work is tested with other work automatically on merge
- All feature work stops when the build is red
- New work does not break delivered work
Why This Matters
Without CI, Teams Experience
- Integration hell: Weeks or months of painful merge conflicts
- Late defect detection: Bugs found after they’re expensive to fix
- Reduced collaboration: Developers work in isolation, losing context
- Deployment fear: Large batches of untested changes create risk
- Slower delivery: Time wasted on merge conflicts and rework
- Quality erosion: Without rapid feedback, technical debt accumulates
With CI, Teams Achieve
- Rapid feedback: Know within minutes if changes broke something
- Smaller changes: Daily integration forces better work breakdown
- Better collaboration: Team shares ownership of the codebase
- Lower risk: Small, tested changes are easier to diagnose and fix
- Faster delivery: No integration delays blocking deployment
- Higher quality: Continuous testing catches issues early
Team Working Agreements
While CI depends on tooling, the team workflow and working agreement are more important:
- Define testable work: Work includes testable acceptance criteria that drive testing efforts
- Tests accompany commits: No work committed to version control without required tests
- Incremental progress: Committed work may not be “feature complete”, but must not break existing work
- Trunk-based workflow: All work begins from trunk and integrates to trunk at least daily
- Stop-the-line: If CI detects an error, the team stops feature work and collaborates to fix the build immediately
The stop-the-line practice is critical for maintaining an always-releasable trunk. For detailed guidance on implementing this discipline, see Stop-the-Line Culture.
Example Implementations
Anti-Pattern: Feature Branch Workflow Without CI
Problems
- Long-lived branches accumulate merge conflicts
- Integration issues discovered late
- No early feedback on compatibility
- Large batches of untested changes
- Team blocked while resolving conflicts
Good Pattern: Continuous Integration to Trunk
Benefits
- Changes tested within minutes
- Team gets immediate feedback
- Small changes are easy to debug
- Integration is never a surprise
- Quality maintained continuously
Evolutionary Coding Practices
To integrate code daily while building large features, use patterns like branch by abstraction, feature flags, and connect-last. These techniques allow you to break down large changes into small, safe commits that integrate to trunk daily without breaking existing functionality.
For detailed guidance and code examples, see Evolutionary Coding Practices.
Testing in CI
A comprehensive testing strategy balances fast feedback with thorough validation. Run different test types at different stages of the pipeline:
- Pre-merge tests (< 10 minutes): Unit tests, linting, static security scans, dependency audits
- Post-merge tests (< 30 minutes): All pre-merge tests plus integration tests, functional tests, performance tests (validate response time and throughput requirements), and dynamic security tests
- Deployment tests: End-to-end and smoke tests belong in the deployment pipeline, not CI
For detailed guidance on test strategy, the test pyramid, deterministic testing, and test quality, see Testing Strategies.
What is Improved
Teamwork
CI requires strong teamwork to function correctly. Key improvements:
- Pull workflow: Team picks next important work instead of working from assignments
- Code review cadence: Quick reviews (< 4 hours) keep work flowing
- Pair programming: Real-time collaboration eliminates review delays
- Shared ownership: Everyone maintains the codebase together
- Team goals over individual tasks: Focus shifts from “my work” to “our progress”
Anti-pattern: “Push” workflow where work is assigned creates silos and delays.
Work Breakdown
CI forces better work decomposition:
- Definition of Ready: Every story has testable acceptance criteria before work starts
- Small batches: If the team can complete work in < 2 days, it’s refined enough
- Vertical slicing: Each change delivers a thin, tested slice of functionality
- Incremental delivery: Features built incrementally, each step integrated daily
See Work Breakdown for detailed guidance.
Testing
CI requires a shift in testing approach:
From: Writing tests after code is “complete”
To: Writing tests before/during coding (TDD/BDD)
From: Testing implementation details
To: Testing behavior and outcomes
From: Manual testing before deployment
To: Automated testing on every commit
From: Separate QA phase
To: Quality built into development
CI teams build a comprehensive test suite with the goal of detecting issues as close to creation as possible. See Behavior-Driven Development.
Common Challenges
“What are the main problems to overcome?”
- Poor teamwork: Usually driven by assigning work instead of using a pull system
- Lack of testable acceptance criteria: Made worse by individual assignments instead of team goals. BDD provides declarative functional tests everyone understands
- Lack of evolutionary coding knowledge: “I can’t commit until the feature is complete!” Use branch by abstraction, feature flags, or plan changes so the last change integrates the feature
“How do I complete a large feature in less than a day?”
You probably don’t complete it in a day, but you integrate progress every day. See Evolutionary Coding Practices for detailed patterns and code examples.
“What code coverage level is needed before we can do CI?”
You don’t need tests in existing code to begin CI. You need to test new code without exception.
Starting point: “We will not go lower than the current level of code coverage.”
“What code coverage percentage should we have?”
“I’m confident.” Are you confident you’ve covered enough positive and negative cases?
Better question: “Do we trust our tests?” Test coverage percentage doesn’t indicate test quality.
“Should we set a code coverage standard for all teams?”
No. Code coverage mandates incentivize meaningless tests that hide the fact that code is not tested.
It is better to have no tests than to have tests you do not trust.
Instead: Focus on test quality, behavior coverage, and team discipline. See Code Coverage for detailed guidance.
Monitoring CI Health
Track these key metrics to understand CI effectiveness and drive improvement:
- Commits per day per developer: ≥ 1 (team average)—indicates integration discipline
- Development cycle time: < 2 days average—shows effective work breakdown
- Build success rate: > 95%—reflects pre-merge testing quality
- Time to fix broken build: < 1 hour—demonstrates stop-the-line commitment
- Defect rate: Stable or decreasing—ensures speed doesn’t sacrifice quality
Make pipeline status visible to everyone through dashboards, notifications, and build radiators. Visibility drives faster response, shared accountability, and continuous improvement.
For detailed guidance on metrics, dashboards, and using data for improvement, see Pipeline Visibility & Health Metrics.
Additional Resources
Learn how to integrate code daily while building large features using branch by abstraction, feature flags, and connect-last patterns.
Learn what tests should run in CI, when they should run, and how to optimize for fast feedback while maintaining comprehensive validation.
Monitor CI health through key metrics including commit frequency, build success rate, and time to fix failures. Learn what to measure and why it matters.
Build quality discipline by stopping all feature work when the build breaks. Learn why this practice is essential for continuous integration and how to implement it effectively.