CI/CD Best Practices

1. Commit Frequently

# Small, focused commits
git add src/user.service.ts
git commit -m "feat: add user creation endpoint"
git push origin feature/user-service

# Avoid large commits
# ❌ git commit -m "update everything"

2. Automate Everything

# Automated pipeline
name: Complete Automation

on: [push]

jobs:
  build:
    steps:
      - run: npm ci
      - run: npm run build
  
  test:
    steps:
      - run: npm test
      - run: npm run lint
  
  security:
    steps:
      - run: npm audit
      - run: trivy scan
  
  deploy:
    steps:
      - run: ./deploy.sh

3. Keep Builds Fast

# Use caching
jobs:
  build:
    steps:
      - uses: actions/cache@v3
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
      
      - run: npm ci  # Faster than npm install
      - run: npm run build

# Parallel execution
jobs:
  unit-tests:
    runs-on: ubuntu-latest
    steps:
      - run: npm run test:unit
  
  integration-tests:
    runs-on: ubuntu-latest
    steps:
      - run: npm run test:integration

4. Fail Fast

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - run: npm run lint
  
  test:
    needs: lint  # Don't test if lint fails
    runs-on: ubuntu-latest
    steps:
      - run: npm test
  
  deploy:
    needs: test  # Don't deploy if tests fail
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh

5. Test in Production-Like Environment

services:
  postgres:
    image: postgres:15  # Same version as production
    env:
      POSTGRES_PASSWORD: postgres
  
  redis:
    image: redis:7  # Same version as production

6. Implement Proper Branching

# Git Flow
main (production)
develop (integration)
feature/* (features)
hotfix/* (urgent fixes)
release/* (releases)

# Trunk-Based Development
main (always deployable)
feature/* (short-lived, < 2 days)

7. Use Semantic Versioning

# Version format: MAJOR.MINOR.PATCH
v1.0.0  # Initial release
v1.0.1  # Bug fix
v1.1.0  # New feature
v2.0.0  # Breaking change

# Tag releases
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0

8. Secure Secrets

# Never hardcode secrets
# ❌ Bad
env:
  API_KEY: "abc123"

# ✅ Good
env:
  API_KEY: ${{ secrets.API_KEY }}

9. Monitor Deployments

// Health checks
app.get('/health', async (req, res) => {
  try {
    await db.ping();
    res.status(200).json({ status: 'healthy' });
  } catch (error) {
    res.status(503).json({ status: 'unhealthy' });
  }
});

// Metrics
const prometheus = require('prom-client');
const httpRequestDuration = new prometheus.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Duration of HTTP requests in seconds'
});

10. Implement Rollback Strategy

jobs:
  deploy:
    steps:
      - name: Deploy
        run: kubectl apply -f k8s/
      
      - name: Wait for rollout
        run: kubectl rollout status deployment/myapp
      
      - name: Run smoke tests
        run: ./smoke-tests.sh
      
      - name: Rollback on failure
        if: failure()
        run: kubectl rollout undo deployment/myapp

11. Use Infrastructure as Code

# Terraform
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

# Version controlled
git add terraform/
git commit -m "Add web server infrastructure"

12. Implement Code Review

# Require PR reviews
on:
  pull_request:
    branches: [main]

jobs:
  review:
    steps:
      - name: Check approvals
        run: |
          APPROVALS=$(gh pr view ${{ github.event.pull_request.number }} --json reviews -q '.reviews | length')
          if [ $APPROVALS -lt 2 ]; then
            echo "Need at least 2 approvals"
            exit 1
          fi

13. Maintain Clean Code

// Use linters
// .eslintrc.js
module.exports = {
  extends: ['eslint:recommended'],
  rules: {
    'no-console': 'error',
    'no-unused-vars': 'error'
  }
};

// Format code
// .prettierrc
{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2
}

14. Document Everything

# README.md
## Setup
npm install

## Development
npm run dev

## Testing
npm test

## Deployment
npm run deploy

## Environment Variables
- DATABASE_URL: PostgreSQL connection string
- API_KEY: External API key

15. Use Feature Flags

class FeatureFlags {
  constructor() {
    this.flags = {
      'new-checkout': false,
      'beta-dashboard': true
    };
  }
  
  isEnabled(feature) {
    return this.flags[feature] || false;
  }
}

// Deploy code with flag disabled
// Enable after deployment

16. Implement Observability

# Three pillars: Logs, Metrics, Traces
logging:
  - ELK Stack
  - CloudWatch

metrics:
  - Prometheus
  - Grafana

tracing:
  - Jaeger
  - OpenTelemetry

17. Practice Continuous Improvement

# Retrospectives
- What went well?
- What didn't go well?
- What can we improve?

# Metrics to track
- Deployment frequency
- Lead time for changes
- Mean time to recovery
- Change failure rate

Interview Tips

  • Explain automation: Automate build, test, deploy
  • Show speed: Caching, parallel execution
  • Demonstrate security: Secrets management
  • Discuss monitoring: Health checks, metrics
  • Mention rollback: Quick recovery
  • Show documentation: Clear README

Summary

CI/CD best practices include frequent commits, automation, fast builds, fail-fast approach, production-like testing, proper branching, semantic versioning, secure secrets, deployment monitoring, rollback strategies, infrastructure as code, code reviews, clean code, documentation, feature flags, observability, and continuous improvement. Essential for successful DevOps implementation.

Test Your Knowledge

Take a quick quiz to test your understanding of this topic.

Test Your Cicd Knowledge

Ready to put your skills to the test? Take our interactive Cicd quiz and get instant feedback on your answers.