CI/CD for ML — GitHub Actions
এই পাঠে যা শিখবেন
- ML-specific CI test types
- GitHub Actions workflow syntax
- Model promotion automation
- Secrets, caching, cost optimization
১ · ML CI different কেন
Standard software CI: lint → unit test → integration test → build → deploy. ML CI extra dimensions.
- Data validation: schema, distribution, range.
- Model performance: baseline-এর সাথে compare.
- Fairness gate: subgroup metrics.
- Resource: GPU runner expensive; CPU-only-এর alternative.
২ · Complete GitHub Actions workflow
name: ML pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * *' # nightly retrain
workflow_dispatch:
env:
PYTHON_VERSION: "3.11"
AWS_REGION: ap-south-1
jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: ${{ env.PYTHON_VERSION }} }
- uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ hashFiles('requirements.lock') }}
- run: pip install -r requirements.lock
- run: pytest tests/unit/ -v
data-validation:
runs-on: ubuntu-latest
needs: unit-tests
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: ${{ env.PYTHON_VERSION }} }
- run: pip install -r requirements.lock
- name: DVC pull
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: dvc pull data/
- run: python scripts/validate_data.py data/
train-and-evaluate:
runs-on: [self-hosted, gpu] # ⭐ GPU runner
needs: data-validation
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v4
- run: pip install -r requirements.lock
- name: DVC pull
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: dvc pull data/
- name: Train
env:
MLFLOW_TRACKING_URI: ${{ secrets.MLFLOW_URI }}
run: python src/train.py
- name: Performance regression test
run: python scripts/check_performance.py --baseline-auc 0.92
- name: Fairness gate
run: python scripts/fairness_check.py --max-disparity 0.05
build-image:
runs-on: ubuntu-latest
needs: train-and-evaluate
if: success()
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ${{ secrets.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASS }}
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ secrets.REGISTRY_URL }}/sentiment:${{ github.sha }}
${{ secrets.REGISTRY_URL }}/sentiment:latest
cache-from: type=registry,ref=${{ secrets.REGISTRY_URL }}/sentiment:buildcache
cache-to: type=registry,ref=${{ secrets.REGISTRY_URL }}/sentiment:buildcache,mode=max
deploy-staging:
runs-on: ubuntu-latest
needs: build-image
environment: staging # ⭐ environment-protection
steps:
- uses: actions/checkout@v4
- uses: azure/setup-kubectl@v3
- run: |
kubectl set image deployment/sentiment-api \
sentiment=${{ secrets.REGISTRY_URL }}/sentiment:${{ github.sha }} \
-n staging
kubectl rollout status deployment/sentiment-api -n staging
৩ · ML-specific tests
- Unit: preprocess function, custom transform — fast.
- Data validation: Great Expectations / Pandera — schema, range, missing.
- Performance regression: "AUC ≥ baseline + tolerance".
- Fairness: "subgroup accuracy gap < threshold".
- Schema match: training input == serving input.
- Smoke test: sample inference end-to-end.
- Latency benchmark: p99 < SLA.
৪ · Secrets management
- GitHub Actions Secrets — encrypted at rest, exposed as env var.
- For sensitive: external secret manager (AWS Secrets Manager, Vault) + GH Action fetch.
- Never echo secret in logs.
- Rotation periodic.
৫ · Self-hosted runners
GitHub-hosted runners CPU-only. GPU training-এর জন্য self-hosted.
- EC2/on-prem GPU machine — runner agent install.
- Labels:
self-hosted, gpu, a100. - Workflow-এ
runs-on: [self-hosted, gpu]. - Security: ephemeral runner per job (containers).
৬ · Cost optimization
- Caching: pip, Docker layer, DVC cache.
- Conditional jobs: path filter — code change only triggers build, doc change skips.
- Concurrent limit: avoid burst on PR open.
- Self-hosted: 70-90% cheaper for high-utilization.
- Spot instances: on-demand spot interrupt-tolerant.
ভাবনার প্রশ্ন
প্র ০১"PR-এ কী test, nightly-তে কী test?"
CI cost ও speed-এর জন্য test stratification.
Per-PR (fast, cheap):
- Lint, unit test (Python function).
- Schema validation.
- Mock-based integration test.
- Build container (cache-aware).
- Total: 5-15 মিনিট।
Nightly (expensive):
- Full training run.
- Performance regression.
- Fairness audit.
- Latency benchmark.
- Total: 1-3 ঘণ্টা।
Pre-merge (manual trigger):
- Major change PR-এ explicit "/test full" comment.
- Run nightly-suite.
- Trade-off: PR slow, but catch issues early.
Path-based filter:
- Doc only — skip CI.
- Code only — skip data validation.
- Workflow change — full test.
মূল উপলব্ধি: Cost-conscious CI = stratification + caching + filter. Per-PR fast feedback; nightly comprehensive. Big change manual trigger.
প্র ০২"Flaky model tests — কীভাবে handle?"
Statistical model — same code, same data, slightly different result possible. Flaky test painful.
Sources of flakiness:
- Random seed not pinned.
- Hardware non-determinism (GPU).
- Test data sampling.
- External dependency (Feature Store, S3).
Mitigations:
- Seed everything (Lesson 5).
- Tolerance-based assertion:
assert abs(auc - 0.92) < 0.005(not exact). - Statistical test: 10 runs avg ± std.
- Snapshot test fixed dataset.
"Quarantine flaky" pattern:
- Mark flaky test, don't fail PR.
- Track separately, fix sprint-level.
- Don't ignore; address as tech debt.
Retry policy:
- 3-retry max, fail if all fail.
- Random seed-different retries — better statistical confidence.
মূল উপলব্ধি: Statistical CI tests — tolerance + reproducibility + quarantine. Pretending no flakes — eventually false alarms erode trust.
প্র ০৩"GH Actions GPU runner self-host vs cloud — Bangladesh team?"
GPU CI cost — Bangladesh teams strategic decision.
Cloud GPU runner (e.g., GitHub Larger runners):
- $0.07/min for A100 ≈ $4.20/hour.
- 2-hour nightly = $8/run × 30 = $240/month.
- Pros: zero ops, on-demand.
- Cons: cost compounds, queue at busy times.
Self-hosted EC2/on-prem GPU:
- EC2 g5.xlarge spot: $0.5/hour.
- 2-hour run × 30 days = $30/month + ops.
- Pros: cheap, controlled.
- Cons: maintenance, security.
On-prem GPU (existing):
- Cost: amortized hardware + power + cooling.
- Bangladesh power outage — UPS, backup.
- Idle time wasted (CI mostly nighttime).
Hybrid pattern:
- GH-hosted CPU for normal CI.
- Self-hosted GPU for nightly training.
- Spot instance for cost optimization.
Security:
- Ephemeral runners — delete after job.
- Don't run untrusted PR on self-hosted (CI escape risk).
মূল উপলব্ধি: High-utilization → self-hosted. Low-utilization → cloud. Bangladesh hybrid common — on-prem dev runner, cloud burst for peaks.
প্র ০৪"Promotion gates — কত strict, কত flexible?"
Gates too strict — innovation slow. Too lax — bad model production-এ। Balance critical.
Strict gates (must pass):
- Schema match — training input == serving input.
- Smoke test — sample inference works.
- Latency < SLA.
- Critical fairness (legal compliance).
Flexible gates (warning, not block):
- Slight accuracy drop (within tolerance).
- Subgroup performance variance (within target).
- Computational efficiency.
Override mechanism:
- Lead-DS approval comment — bypass for specific PR.
- Documented in PR description "why bypass".
- Audit log of overrides.
Calibration over time:
- Initial gates conservative.
- Loosen as confidence builds.
- Tighten if incidents.
BD context — fintech:
- Bangladesh Bank compliance — strict gates non-negotiable.
- Internal-only model — looser.
মূল উপলব্ধি: Gate strictness business risk-driven. Start strict, calibrate over time. Override mechanism essential — pure-strict eventually shipped around.
অনুশীলন
- Setup: উপরের workflow নিজের project-এ adapt. Secrets manage.
Repo settings → Secrets and variables → Actions. AWS_ACCESS_KEY_ID etc. add.
- Performance gate: python script লিখুন যা MLflow latest run-এর AUC compare.
mlflow.search_runsদিয়ে latest + baseline AUC. Tolerance check. sys.exit(1) on fail. - চিন্তা: ৩-environment (dev/stg/prod) workflow design করুন।
- dev: every PR auto deploy + smoke test.
- staging: main merge → auto deploy + integration test.
- prod: tag push → environment approval (lead-DS) → canary 5% → full.