Introduction to CI/CD Pipelines
What is CI/CD?
CI/CD stands for Continuous Integration and Continuous Deployment. CI automates building and testing code changes, while CD automates the deployment process. Together, they form a pipeline that ensures code changes are reliable and can be released quickly.
- Continuous Integration: Merge code frequently, run automated tests
- Continuous Delivery: Keep code deployable at any time
- Continuous Deployment: Automatically deploy every change that passes tests
GitHub Actions Basics
GitHub Actions is a powerful CI/CD platform built into GitHub. Workflows are defined in YAML files in the .github/workflows directory.
# .github/workflows/ci.ymlname:CI Pipeline on: push: branches: [main, develop] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - name:Checkout code 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 linter run: npm run lint - name:Run tests run: npm test - name:Build application run: npm run buildDocker in CI/CD
Docker ensures consistent environments from development to production. Here's how to build and push Docker images in your pipeline:
# Build and push Docker image build: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name:Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name:Build and push uses: docker/build-push-action@v5 with: context: . push: true tags: | myapp:latest myapp:${{ github.sha }}Sample Dockerfile
# Multi-stage build for smaller imageFROM node:20-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ciCOPY . .RUN npm run build FROM node:20-alpine AS runnerWORKDIR /appENV NODE_ENV=production COPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesCOPY --from=builder /app/package.json ./ EXPOSE 3000CMD ["node", "dist/index.js"]Environment Management
# Deploy to different environments deploy-staging: needs: build runs-on: ubuntu-latest environment: staging steps: - name:Deploy to staging run: | echo "Deploying to staging..." # Add your deployment commands here deploy-production: needs: deploy-staging runs-on: ubuntu-latest environment: production if: github.ref == 'refs/heads/main' steps: - name:Deploy to production run: | echo "Deploying to production..."Deployment Strategies
- Rolling Update: Gradually replace old instances with new ones
- Blue-Green: Run two identical environments, switch traffic instantly
- Canary: Route small percentage of traffic to new version first
- Feature Flags: Deploy code but enable features selectively
Best Practices
- Keep pipelines fast - cache dependencies, parallelize jobs
- Use branch protection rules to require passing checks
- Store secrets securely using GitHub Secrets or vault
- Version your Docker images with commit SHA
- Implement rollback mechanisms for failed deployments
- Monitor deployments and set up alerts
- Document your pipeline in the repository
“If it hurts, do it more frequently, and bring the pain forward. - Continuous Delivery principle”
Conclusion
CI/CD pipelines are essential for modern software development. Start with a simple workflow that runs tests on every push, then gradually add build, security scanning, and deployment stages. The goal is to make releasing software boring - and that's a good thing.