Version Control and CI/CD
Introduction
Modern software development relies heavily on version control and continuous integration/continuous deployment (CI/CD). This article covers Git workflows, GitHub Actions, Docker containerization, and Kubernetes basics.
1. Git Version Control
1.1 Core Git Concepts
Working Directory
│ git add
▼
Staging Area (Index)
│ git commit
▼
Local Repository
│ git push
▼
Remote Repository
1.2 Branching Models
Git Flow
gitGraph
commit id: "init"
branch develop
checkout develop
commit id: "feat-start"
branch feature/login
checkout feature/login
commit id: "login-impl"
commit id: "login-test"
checkout develop
merge feature/login id: "merge-login"
branch release/1.0
checkout release/1.0
commit id: "bugfix"
checkout main
merge release/1.0 id: "v1.0" tag: "v1.0"
checkout develop
merge release/1.0 id: "sync"
| Branch | Purpose | Lifecycle |
|---|---|---|
main |
Production code | Permanent |
develop |
Development integration | Permanent |
feature/* |
New feature development | Temporary |
release/* |
Release preparation | Temporary |
hotfix/* |
Emergency fixes | Temporary |
Trunk-Based Development
main ──●──●──●──●──●──●──●──●──
│ │ │
└─●─┘ └──●──┘ └─●─┘
Short-lived branches (< 1-2 days)
- The trunk is always in a deployable state
- Branches have very short lifespans (hours to a couple of days)
- Relies on feature flags to hide incomplete features
- Suited for teams with mature CI/CD practices
1.3 Merge vs Rebase
Merge: creates a merge commit, preserving complete history
git checkout main
git merge feature/login
# creates a merge commit
Rebase: "transplants" branch commits onto the target branch
git checkout feature/login
git rebase main
# replays feature commits on top of main
git checkout main
git merge feature/login # fast-forward
| Approach | History | Advantages | Disadvantages |
|---|---|---|---|
| Merge | Non-linear | Preserves true history | History can be messy |
| Rebase | Linear | Clean history | Rewrites history; caution needed in collaboration |
1.4 Cherry-pick
Applies specific commits to other branches:
git checkout main
git cherry-pick abc1234 # apply a specific commit to main
git cherry-pick abc..def # apply a range
Use cases: syncing hotfixes from main to develop, or selectively porting features.
2. GitHub Actions
2.1 Workflow Basic Structure
# .github/workflows/ci.yml
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
PYTHON_VERSION: '3.11'
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Cache dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest --cov=src tests/
- name: Upload coverage
uses: codecov/codecov-action@v4
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install ruff
- run: ruff check src/
deploy:
needs: [test, lint]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Deploy to production
run: ./deploy.sh
2.2 Commonly Used Actions
| Action | Purpose |
|---|---|
actions/checkout |
Check out code |
actions/setup-python |
Configure Python |
actions/setup-node |
Configure Node.js |
actions/cache |
Cache dependencies |
docker/build-push-action |
Build and push Docker images |
peaceiris/actions-gh-pages |
Deploy to GitHub Pages |
3. Docker
3.1 Core Concepts
Dockerfile → docker build → Image → docker run → Container
(recipe) (image) (running instance)
| Concept | Analogy | Description |
|---|---|---|
| Image | Class | Read-only template containing app and dependencies |
| Container | Instance | Running instance of an Image, read-write |
| Dockerfile | Blueprint | Defines how to build an Image |
| Registry | Repository | Stores and distributes Images (e.g., Docker Hub) |
3.2 Dockerfile Best Practices
# Multi-stage build
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
FROM python:3.11-slim AS runtime
# Non-root user
RUN useradd --create-home appuser
USER appuser
WORKDIR /app
COPY --from=builder /root/.local /home/appuser/.local
COPY . .
ENV PATH=/home/appuser/.local/bin:$PATH
EXPOSE 8000
HEALTHCHECK CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Optimization tips:
- Leverage build cache: COPY dependency files first, then source code
- Multi-stage builds to reduce image size
- Use
.dockerignoreto exclude unnecessary files - Choose
slimoralpinebase images
3.3 Docker Compose
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
pgdata:
4. Kubernetes Basics
4.1 Core Concepts
| Concept | Description |
|---|---|
| Pod | Smallest deployable unit, contains one or more containers |
| Service | Provides stable network access to Pods |
| Deployment | Manages Pod replicas, updates, and rollbacks |
| ConfigMap/Secret | Configuration and sensitive data management |
| Namespace | Virtual cluster for resource isolation |
| Ingress | HTTP/HTTPS external access entry point |
4.2 Basic Resource Definitions
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: myapp:v1.0
ports:
- containerPort: 8000
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8000
type: ClusterIP
4.3 Rolling Updates
# Update image version
kubectl set image deployment/web-app web=myapp:v2.0
# Check update status
kubectl rollout status deployment/web-app
# Rollback
kubectl rollout undo deployment/web-app
5. Complete CI/CD Pipeline
graph LR
A[Code Commit] --> B[CI: Build]
B --> C[CI: Test]
C --> D[CI: Code Quality]
D --> E[CD: Build Image]
E --> F[CD: Push to Registry]
F --> G{Environment}
G -->|staging| H[Deploy to Staging]
H --> I[Integration Tests]
I --> J[Manual Approval]
J --> K[Deploy to Production]
G -->|direct| K
style A fill:#f9f
style K fill:#bfb
5.1 Full Example: GitHub Actions + Docker + K8s
name: Deploy Pipeline
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: |
pip install -r requirements.txt
pytest tests/
- name: Build Docker image
run: |
docker build -t myregistry/myapp:${{ github.sha }} .
- name: Push to registry
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker push myregistry/myapp:${{ github.sha }}
- name: Deploy to Kubernetes
uses: azure/k8s-deploy@v5
with:
manifests: k8s/
images: myregistry/myapp:${{ github.sha }}
6. Best Practices
Git Standards
- Commit messages: use Conventional Commits (
feat:,fix:,docs:,refactor:) - Branch protection: main branch requires PR + code review + CI passing
- Signed commits: GPG-sign important commits
CI/CD Principles
- Fast feedback: tests should complete within 10 minutes
- Immutable artifacts: the same build artifact is deployed to all environments
- Infrastructure as Code: all configuration under version control
- Progressive delivery: canary releases, blue-green deployments
Relations to Other Topics
- See Testing and Quality Assurance for why automated validation is the core input to continuous integration
- See Full-Stack Development for how cross-stack teams manage branching, builds, and deployment
- See Cloud Services for image registries, container deployment, and cloud delivery infrastructure
- See Software Engineering Overview for the role of version control and delivery in the software lifecycle
References
- "Pro Git" - Scott Chacon & Ben Straub
- GitHub Actions Official Documentation
- Docker Official Documentation
- Kubernetes Official Documentation