---
title: "Production Playbook: CI/CD for ML with GitHub Actions"
newsletter: "MLOps Community"
date: 2025-05-27
source: https://aaif.live/newsletters/mlopscommunity/2025-05-27-production-playbook-ci-cd-for-ml-with-github-actions
---

# Production Playbook: CI/CD for ML with GitHub Actions

*MLOps Community — Agentic AI Foundation, 2025-05-27*

[https://go.mlops.community/GwazeEmail](https://go.mlops.community/GwazeEmail)

PRODUCTION PLAYBOOK: CI/CD FOR ML WITH GITHUB ACTIONS



Setting up CI/CD for ML isn’t the same as for a web app or backend service. You’re dealing with constantly evolving data, experiment tracking, flaky models, environment drift - the works. But done right, CI/CD can help catch silent failures early, avoid model regression, and make your life easier when it comes to releases.

This one’s a practical walkthrough for wiring up a modern ML CI/CD pipeline using GitHub Actions. We’ll touch on DVC, MLflow, Docker, and testing along the way.


Workflow triggers that actually make sense

Your CI/CD flow shouldn’t fire on every README update. For ML projects, it’s better to be picky - trigger only when relevant files change:

Yaml on: push: branches: - "main" paths: - "data/**" - "models/**" - "scripts/**" - "configs/**"

That keeps things fast and focused.





PULLING DATASETS WITH DVC



You don’t want huge CSVs in your Git repo. DVC lets you version them separately and sync them as needed:

Yaml - name: Fetch Data with DVC env: AWS_ACCESS_KEY_ID: ${{ '{{ secrets.AWS_ACCESS_KEY_ID }}' }} AWS_SECRET_ACCESS_KEY: ${{ '{{ secrets.AWS_SECRET_ACCESS_KEY }}' }} run: dvc pull -r dataset_remote

Logging experiments with MLflow

If you’re not tracking experiments, good luck debugging model changes. MLflow is one of the easiest ways to log what’s happening:

Python import mlflow mlflow.set_experiment("CI/CD Experiment") mlflow.log_param("algorithm", "XGBoost") mlflow.log_metric("RMSE", 0.032)

Tests that actually catch things

You want tests for the boring stuff (preprocessing functions), the risky stuff (model accuracy), and the sensitive stuff (fairness). Examples:

Unit test for preprocessing

Python def test_scale_features(): original_data = [10, 20, 30] scaled_data = scale_features(original_data) assert scaled_data == [0.0, 0.5, 1.0], "Scaling failed"

Model sanity check

Python def test_model_performance(): performance = evaluate_model() assert performance['accuracy'] >= 0.95, "Performance below acceptable level"

Bias test using Fairlearn

Python from fairlearn.metrics import MetricFrame metrics = MetricFrame(accuracy_score, y_true, y_pred, sensitive_features=gender) assert metrics.overall >= 0.90, "Bias exceeds acceptable limits"

Docker, so things don’t break on prod

Don’t trust "works on my machine." Docker keeps everything reproducible:

Dockerfile FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . ENV MODEL_DIR=/app/model EXPOSE 8080 CMD ["python", "serve.py"]

Lint your Dockerfiles too:

Bash hadolint Dockerfile

Scheduled retraining with cron

You can retrain weekly if you want - and yes, cron syntax still sucks:

Yaml on: schedule: - cron: "0 0 * * 0" # Every Sunday at midnight

Secrets stay secret

Don't hardcode anything sensitive. GitHub Secrets exists for a reason:

Yaml - name: Execute Model Training env: MLFLOW_TRACKING_URI: ${{ '{{ secrets.MLFLOW_TRACKING_URI }}' }} AWS_ACCESS_KEY_ID: ${{ '{{ secrets.AWS_ACCESS_KEY_ID }}' }} AWS_SECRET_ACCESS_KEY: ${{ '{{ secrets.AWS_SECRET_ACCESS_KEY }}' }} run: python train.py

Bonus: Conditional logic and rollbacks

A few more things worth adding if you’re serious:

 * Conditional retraining (e.g. triggered by drift)
 * MLflow model registry for structured promotions:

Python mlflow.register_model("model_path", "Production_Model")
 * Real-time monitoring with Prometheus/Grafana
 * Auto rollbacks when things go sideways

That’s it. CI/CD for ML won’t make your models better, but it’ll make sure bad ones don’t slip through unnoticed.

It’s one of the highest leverage things you can set up - and with GitHub Actions, it’s pretty doable even for small teams.

Working on something tricky or planning ahead? Here’s how we can help - just hit reply:

 * Custom workshops tailored to your company’s needs
 * Hiring? I know some quality folks looking for a new adventure
 * Want to connect with someone tackling similar problems? I can introduce you

Thanks for reading, catch you next time!

Interested in partnering with us? Get in touch: partners@mlops.community

Thanks for reading. See you in Slack [https://go.mlops.community/slack], YouTube [https://www.youtube.com/channel/UCG6qpjVnBTTT8wLGBygANOQ?view_as=subscriber], and podcast [https://home.mlops.community/public/content/] land. Oh yeah, and we are also on X [https://twitter.com/mlopscommunity] and LinkedIn [https://go.mlops.community/linkedin].

The MLOps Community newsletter is edited by Jessica Rudd [https://www.linkedin.com/in/jmrudd/].

Shoutout to Ranuga Disansa [https://go.mlops.community/i83caq] for his contributions.

---
Source: https://aaif.live/newsletters/mlopscommunity/2025-05-27-production-playbook-ci-cd-for-ml-with-github-actions
