13 min read • Guide 85 of 877
Implementing Continuous Integration Workflows
Continuous Integration (CI) transforms how teams validate code changes by automatically running tests, linting, and quality checks on every commit. When CI integrates with GitScrum through GitHub, GitLab, or Bitbucket connections, task statuses update automatically based on build results, giving the entire team visibility into code health. This creates a quality gate that prevents broken code from reaching main branches while keeping the board in sync with actual development state.
CI Fundamentals
Why CI Matters
WITHOUT CI:
┌─────────────────────────────────────────────────────────────┐
│ MANUAL VERIFICATION PROBLEMS │
├─────────────────────────────────────────────────────────────┤
│ │
│ Developer pushes code: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ "Works on my machine" ──────────────────────────────────││
│ │ │ ││
│ │ ▼ ││
│ │ ┌───────────────────────────────────────────────────┐ ││
│ │ │ PROBLEMS DISCOVERED LATER: │ ││
│ │ │ │ ││
│ │ │ • Different Node version on CI server │ ││
│ │ │ • Missing environment variable │ ││
│ │ │ • Test passes locally, fails in isolation │ ││
│ │ │ • Merge conflict not properly resolved │ ││
│ │ │ • Dependency not in package.json │ ││
│ │ │ │ ││
│ │ │ Time to debug: Hours to days │ ││
│ │ │ Context switching: Already on next task │ ││
│ │ │ Blame game: "Who broke the build?" │ ││
│ │ └───────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────┘│
│ │
└─────────────────────────────────────────────────────────────┘
WITH CI:
┌─────────────────────────────────────────────────────────────┐
│ AUTOMATED VERIFICATION FLOW │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Push │───▶│ CI Runs │───▶│ Result │ │
│ │ Commit │ │ Checks │ │ in 5min │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ CHECKS RUN: │ │
│ │ ✓ Install dependencies │ │
│ │ ✓ Lint code │ │
│ │ ✓ Type check │ │
│ │ ✓ Run unit tests │ │
│ │ ✓ Run integration tests │ │
│ │ ✓ Build production artifact │ │
│ │ │ │
│ │ All pass → ✅ Merge allowed │ │
│ │ Any fail → ❌ Merge blocked │ │
│ └─────────────────────────────────────┘ │
│ │
│ Developer finds issue: 5 minutes, not days │
│ Context: Still in the same task │
│ Accountability: Clear which commit broke what │
│ │
└─────────────────────────────────────────────────────────────┘
CI Pipeline Stages
STANDARD PIPELINE STRUCTURE:
┌─────────────────────────────────────────────────────────────┐
│ PIPELINE STAGES │
├─────────────────────────────────────────────────────────────┤
│ │
│ Stage 1: PREPARE (1-2 min) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ • Checkout code ││
│ │ • Cache dependencies ││
│ │ • Install packages ││
│ │ ││
│ │ Fail conditions: Network issues, corrupted cache ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ Stage 2: VALIDATE (2-5 min) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Run in parallel: ││
│ │ • Lint (ESLint, Prettier, etc.) ││
│ │ • Type check (TypeScript) ││
│ │ • Security audit (npm audit, Snyk) ││
│ │ ││
│ │ Fail conditions: Style violations, type errors, vulns ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ Stage 3: TEST (5-15 min) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Sequential: ││
│ │ • Unit tests ││
│ │ • Integration tests ││
│ │ • E2E tests (optional per-PR) ││
│ │ ││
│ │ Fail conditions: Test failures, coverage drop ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ Stage 4: BUILD (2-5 min) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ • Build production artifact ││
│ │ • Verify bundle size ││
│ │ • Upload artifacts ││
│ │ ││
│ │ Fail conditions: Build errors, size limits exceeded ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ Stage 5: DEPLOY (on merge to main) │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ • Deploy to staging ││
│ │ • Run smoke tests ││
│ │ • Notify team ││
│ └─────────────────────────────────────────────────────────┘│
│ │
└─────────────────────────────────────────────────────────────┘
GitScrum Integration
Connecting Git Providers
GITSCRUM + CI FLOW:
┌─────────────────────────────────────────────────────────────┐
│ AUTOMATIC BOARD UPDATES │
├─────────────────────────────────────────────────────────────┤
│ │
│ Setup: GitScrum → Integrations → GitHub/GitLab/Bitbucket │
│ │
│ WORKFLOW: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ 1. Developer creates branch: ││
│ │ git checkout -b feature/PROJ-123-user-auth ││
│ │ ^^^^ ││
│ │ Task ID ││
│ │ ││
│ │ 2. Developer opens PR referencing task: ││
│ │ PR Title: "feat: implement user auth [PROJ-123]" ││
│ │ ││
│ │ 3. GitScrum automatically: ││
│ │ • Links PR to task PROJ-123 ││
│ │ • Shows PR status on task card ││
│ │ • Updates task based on PR state ││
│ │ ││
│ │ 4. CI runs, results visible in GitScrum: ││
│ │ ┌─────────────────────────────────────────────────┐ ││
│ │ │ Task: PROJ-123 │ ││
│ │ │ │ ││
│ │ │ 🔗 PR #45: feat: implement user auth │ ││
│ │ │ ⏳ CI Running: 3 of 5 checks passed │ ││
│ │ │ │ │ ││
│ │ │ ├─ ✅ lint │ ││
│ │ │ ├─ ✅ typecheck │ ││
│ │ │ ├─ ✅ unit-tests │ ││
│ │ │ ├─ ⏳ integration-tests (running) │ ││
│ │ │ └─ ⏸️ deploy (waiting) │ ││
│ │ └─────────────────────────────────────────────────┘ ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ CI status visible without leaving GitScrum board │
│ │
└─────────────────────────────────────────────────────────────┘
Task Status Automation
STATUS AUTOMATION RULES:
┌─────────────────────────────────────────────────────────────┐
│ CONFIGURING AUTOMATIC TRANSITIONS │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ EVENT │ TASK TRANSITION ││
│ │──────────────────────────┼──────────────────────────────││
│ │ Branch created with │ → "In Progress" ││
│ │ task ID │ ││
│ │ │ ││
│ │ PR opened (draft) │ → "In Progress" ││
│ │ │ ││
│ │ PR ready for review │ → "Code Review" ││
│ │ │ ││
│ │ CI failed │ → Stay in current status ││
│ │ │ (add "CI Failed" label) ││
│ │ │ ││
│ │ CI passed, approved │ → "Ready to Merge" ││
│ │ │ ││
│ │ PR merged │ → "Done" ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ Why this matters: │
│ • Board always reflects reality │
│ • No manual status updates needed │
│ • PM can see actual progress without interrupting devs │
│ │
└─────────────────────────────────────────────────────────────┘
Sample CI Configurations
GitHub Actions
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Type check
run: npm run typecheck
test:
runs-on: ubuntu-latest
needs: validate
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test -- --coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
build:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: build
path: dist/
GitLab CI
# .gitlab-ci.yml
stages:
- validate
- test
- build
variables:
npm_config_cache: "$CI_PROJECT_DIR/.npm"
cache:
paths:
- .npm/
- node_modules/
lint:
stage: validate
script:
- npm ci
- npm run lint
- npm run typecheck
unit-tests:
stage: test
script:
- npm ci
- npm test -- --coverage
coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
build:
stage: build
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
Quality Gates
Required Checks
BLOCKING VS NON-BLOCKING CHECKS:
┌─────────────────────────────────────────────────────────────┐
│ CONFIGURING QUALITY GATES │
├─────────────────────────────────────────────────────────────┤
│ │
│ MUST PASS (block merge): │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ ✓ Lint No syntax errors, style consistent ││
│ │ ✓ Type check TypeScript compiles without errors ││
│ │ ✓ Unit tests All tests pass ││
│ │ ✓ Build Production build succeeds ││
│ │ ✓ Security No high/critical vulnerabilities ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ SHOULD PASS (warn but allow): │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ ⚠ Coverage >80% coverage (warn if lower) ││
│ │ ⚠ Bundle size <500KB (warn if larger) ││
│ │ ⚠ Performance Lighthouse >90 (warn if lower) ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ INFORMATIONAL (never block): │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ ℹ Dependency updates Dependabot/Renovate suggestions ││
│ │ ℹ Code complexity Maintainability metrics ││
│ │ ℹ Documentation Missing JSDoc warnings ││
│ └─────────────────────────────────────────────────────────┘│
│ │
└─────────────────────────────────────────────────────────────┘
Coverage Requirements
COVERAGE STRATEGY:
┌─────────────────────────────────────────────────────────────┐
│ MEANINGFUL COVERAGE THRESHOLDS │
├─────────────────────────────────────────────────────────────┤
│ │
│ OVERALL TARGETS: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Metric │ Minimum │ Target │ Rationale ││
│ │──────────────────┼─────────┼─────────┼──────────────────││
│ │ Line coverage │ 70% │ 85% │ Most code touched││
│ │ Branch coverage │ 60% │ 80% │ Edge cases tested││
│ │ Function coverage│ 80% │ 95% │ All funcs called ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ PER-PR RULES: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Rule: Coverage must not decrease ││
│ │ ││
│ │ Main branch: 82% coverage ││
│ │ PR adds new code: Must maintain ≥82% ││
│ │ ││
│ │ Exception: Documented tech debt with follow-up task ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ WHAT TO COVER: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ High priority (test thoroughly): ││
│ │ • Business logic ││
│ │ • Data transformations ││
│ │ • Error handling paths ││
│ │ • API response handling ││
│ │ ││
│ │ Lower priority (basic tests okay): ││
│ │ • UI components (visual testing better) ││
│ │ • Generated code ││
│ │ • Configuration files ││
│ └─────────────────────────────────────────────────────────┘│
│ │
└─────────────────────────────────────────────────────────────┘
Pipeline Optimization
Speed Improvements
FAST CI BEST PRACTICES:
┌─────────────────────────────────────────────────────────────┐
│ REDUCING PIPELINE TIME │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. PARALLELIZATION: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Before (sequential): 15 minutes ││
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ││
│ │ │Lint │→│Types│→│Unit │→│Integ│→│Build│ ││
│ │ │ 2m │ │ 2m │ │ 5m │ │ 4m │ │ 2m │ ││
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ ││
│ │ ││
│ │ After (parallel): 7 minutes ││
│ │ ┌─────┐ ││
│ │ │Lint │──────────────────────┐ ││
│ │ │ 2m │ │ ││
│ │ └─────┘ ▼ ││
│ │ ┌─────┐ ┌─────────┐ ┌─────┐ ││
│ │ │Types│────────────────▶│ Test │───▶│Build│ ││
│ │ │ 2m │ │ 5m │ │ 2m │ ││
│ │ └─────┘ └─────────┘ └─────┘ ││
│ │ ┌─────┐ ▲ ││
│ │ │Audit│──────────────────────┘ ││
│ │ │ 1m │ ││
│ │ └─────┘ ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ 2. CACHING: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Cache: ││
│ │ • node_modules (key: hash of package-lock.json) ││
│ │ • Build artifacts (for unchanged files) ││
│ │ • Test snapshots ││
│ │ ││
│ │ Cache hit: 2 min install → 10 sec restore ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ 3. SELECTIVE TESTING: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ • Only run tests for changed files/dependencies ││
│ │ • Full test suite on main branch only ││
│ │ • Use test sharding for large test suites ││
│ └─────────────────────────────────────────────────────────┘│
│ │
└─────────────────────────────────────────────────────────────┘
Failure Handling
DEALING WITH CI FAILURES:
┌─────────────────────────────────────────────────────────────┐
│ FAILURE WORKFLOW │
├─────────────────────────────────────────────────────────────┤
│ │
│ WHEN CI FAILS: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ 1. Developer gets notification (email, Slack, Teams) ││
│ │ 2. GitScrum task shows CI status: ││
│ │ 🔴 Build Failed - PROJ-123 ││
│ │ 3. Developer clicks through to see failure ││
│ │ 4. Fix and push ││
│ │ 5. CI reruns automatically ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ FLAKY TEST HANDLING: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ IF test fails intermittently: ││
│ │ ││
│ │ Option 1: Automatic retry ││
│ │ retry: 2 # Retry failed jobs twice ││
│ │ ││
│ │ Option 2: Quarantine ││
│ │ • Mark flaky test with tag ││
│ │ • Run in separate job (doesn't block) ││
│ │ • Create GitScrum task to fix ││
│ │ ││
│ │ Option 3: Fix immediately ││
│ │ • Flaky tests erode trust in CI ││
│ │ • Prioritize fixing over new features ││
│ └─────────────────────────────────────────────────────────┘│
│ │
└─────────────────────────────────────────────────────────────┘
Team Practices
CI Discipline
TEAM CI AGREEMENTS:
┌─────────────────────────────────────────────────────────────┐
│ CI TEAM NORMS │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ DO: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ • Run tests locally before pushing ││
│ │ • Fix broken builds immediately (priority over features)││
│ │ • Keep pipeline under 15 minutes ││
│ │ • Review CI config changes carefully ││
│ │ • Monitor for flaky tests weekly ││
│ │ • Celebrate green builds ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ ❌ DON'T: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ • Push directly to main ││
│ │ • Skip CI checks "just this once" ││
│ │ • Leave red builds overnight ││
│ │ • Ignore failing tests by skipping them ││
│ │ • Add slow tests without optimization ││
│ │ • Merge without PR review ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ BROKEN BUILD PROTOCOL: │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ 1. All work stops when main branch is red ││
│ │ 2. Person who broke it takes ownership ││
│ │ 3. If not fixable in 10 min, revert and fix in branch ││
│ │ 4. Post in Discussions: what happened, how prevented ││
│ └─────────────────────────────────────────────────────────┘│
│ │
└─────────────────────────────────────────────────────────────┘