Netspective Logo

Continuous Integration

Practices for frequently integrating code changes with automated validation

Continuous Integration (CI) is the practice of frequently merging code changes into a shared repository, where each integration is verified by automated builds and tests. CI enables teams to detect problems early and deliver software more rapidly.

What is Continuous Integration?

Continuous Integration promotes frequent team integrations and automatic builds. By integrating the system more frequently, integration issues are identified earlier when they are easier to fix, and the overall integration effort is reduced via continuous feedback.

Continuous Integration Flow


CI Principles

Commit Frequently

  • Integrate changes at least daily
  • Keep commits small and focused
  • Avoid long-lived feature branches
  • Merge to main branch often

Maintain a Single Source of Truth

  • All code in version control
  • All configuration in version control
  • Build scripts checked in
  • Infrastructure as code

Automate the Build

# Example: GitHub Actions CI workflow
name: CI
on: [push, pull_request]

jobs:
  build:
    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: Build
        run: npm run build

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: build
          path: dist/

Make the Build Self-Testing

  test:
    runs-on: ubuntu-latest
    needs: build
    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 unit tests
        run: npm test -- --coverage

      - name: Upload coverage
        uses: codecov/codecov-action@v3

Keep the Build Fast

Build StageTarget Time
Checkout & Setup< 1 min
Install Dependencies< 2 min
Compile/Build< 3 min
Unit Tests< 3 min
Total< 10 min

CI Pipeline Stages

Stage 1: Build

build:
  stage: build
  script:
    - npm ci
    - npm run build
    - npm run build:docs
  artifacts:
    paths:
      - dist/
      - docs/
    expire_in: 1 day

Stage 2: Lint & Format

lint:
  stage: validate
  script:
    - npm run lint
    - npm run format:check
    - npm run typecheck

Stage 3: Unit Tests

unit-test:
  stage: test
  script:
    - npm test -- --coverage --ci
  coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
      junit: junit.xml

Stage 4: Security Scans

security-scan:
  stage: security
  parallel:
    matrix:
      - SCAN_TYPE: [sast, sca, secrets]
  script:
    - |
      case $SCAN_TYPE in
        sast) semgrep --config auto . ;;
        sca) npm audit --audit-level=high ;;
        secrets) gitleaks detect --source . ;;
      esac

Stage 5: Integration Tests

integration-test:
  stage: test
  services:
    - postgres:15
    - redis:7
  variables:
    DATABASE_URL: postgres://postgres:postgres@postgres:5432/test
    REDIS_URL: redis://redis:6379
  script:
    - npm run test:integration

Branch Strategies

Trunk-Based Development

main ────●────●────●────●────●────●────●────●────▶
          \   /      \       /
           ●         ●──────●
        feature    short-lived
         (1 day)   feature (2-3 days)

Characteristics:

  • Single main branch
  • Short-lived feature branches (< 2 days)
  • Feature flags for incomplete work
  • Continuous deployment from main

GitHub Flow

main ────●────●────────●────●────●────▶
          \          /
           ●────●───●
           feature branch
           (with PR review)

Characteristics:

  • Main branch always deployable
  • Feature branches for all changes
  • Pull request for code review
  • Deploy after merge to main

GitFlow (for regulated environments)

main     ●─────────────────●─────────────────●────▶
          \               /                 /
develop    ●────●────●───●────●────●────●──●────▶
                \   /         \       /
                 ●             ●─────●
              feature         feature

Characteristics:

  • Separate develop and main branches
  • Release branches for stabilization
  • Better for scheduled releases
  • More overhead, more control

Build Artifact Management

Versioning Strategy

# Semantic versioning with build metadata
VERSION=1.2.3+build.${CI_PIPELINE_ID}

# Or with git SHA
VERSION=1.2.3+${GIT_SHORT_SHA}

Artifact Storage

# Upload build artifacts
- name: Upload artifact
  uses: actions/upload-artifact@v4
  with:
    name: app-${{ github.sha }}
    path: |
      dist/
      package.json
    retention-days: 30

Container Images

# Build and push Docker image
- name: Build and push
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: |
      myapp:${{ github.sha }}
      myapp:latest
    cache-from: type=gha
    cache-to: type=gha,mode=max

CI Best Practices

Code Quality Gates

quality-gate:
  stage: validate
  script:
    - npm run lint
    - npm run test -- --coverage
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  allow_failure: false

Parallel Execution

test:
  parallel:
    matrix:
      - NODE_VERSION: ['18', '20', '22']
        OS: ['ubuntu-latest', 'windows-latest']
  runs-on: ${{ matrix.OS }}
  steps:
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ matrix.NODE_VERSION }}
    - run: npm test

Caching Dependencies

- name: Cache node modules
  uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

Fail Fast

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - run: npm run lint
    # Fail immediately, don't wait for other jobs

  test:
    needs: lint  # Only run if lint passes
    runs-on: ubuntu-latest
    steps:
      - run: npm test

CI Notifications

Slack Notification

- name: Notify Slack
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    payload: |
      {
        "text": "CI Failed: ${{ github.repository }}",
        "blocks": [
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "*Build Failed*\n${{ github.event.head_commit.message }}"
            }
          }
        ]
      }
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

Status Checks

# Require status checks before merge
# In repository settings:
# - Require status checks to pass
# - Require branches to be up to date
# - Select required checks: lint, test, security

Metrics & Monitoring

Build Metrics to Track

MetricTargetAction if Exceeded
Build Duration< 10 minOptimize or parallelize
Build Success Rate> 95%Investigate failures
Test Coverage> 80%Add tests
Time to Fix Broken Build< 10 minPrioritize fixes

Dashboard Example

┌─────────────────────────────────────────────────────────────────┐
│                    CI DASHBOARD                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Build Status: ✅ Passing         Last Build: 5 min ago         │
│                                                                  │
│  Build Duration Trend (last 7 days)                             │
│  ┌────────────────────────────────────────┐                     │
│  │    ▄                                   │ 12 min              │
│  │   ▄█▄    ▄                             │ 10 min              │
│  │  ▄███▄  ▄█▄   ▄▄   ▄    ▄▄            │  8 min              │
│  │ ▄█████▄▄███▄ ▄██▄ ▄█▄  ▄██▄           │  6 min              │
│  └────────────────────────────────────────┘                     │
│    Mon Tue Wed Thu Fri Sat Sun                                  │
│                                                                  │
│  Success Rate: 96.5%    Coverage: 84.2%    Avg Time: 7.3 min   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Troubleshooting

Common Issues

IssueCauseSolution
Flaky testsNon-deterministic behaviorIsolate tests, fix race conditions
Slow buildsLarge dependenciesCache dependencies, parallelize
Merge conflictsLong-lived branchesMerge more frequently
Environment issuesInconsistent setupUse containers, lock versions

Debugging CI Failures

# Add debug output
- name: Debug
  if: failure()
  run: |
    echo "Node version: $(node -v)"
    echo "NPM version: $(npm -v)"
    cat package.json
    ls -la node_modules/ | head -20

# Enable step debug logging
# Set secret: ACTIONS_STEP_DEBUG = true


Compliance

This section fulfills ISO 13485 requirements for software validation (4.1.5), control of production (7.5.1), and monitoring (8.2.4), and ISO 27001 requirements for secure development lifecycle (A.8.25), change management (A.8.32), and security testing (A.8.29).

View full compliance matrix

How is this guide?

Last updated on

On this page