technicalFor: cto-series-a

CI/CD Pipeline Setup Checklist for AI Products (Free Download)

A CI/CD pipeline is the engineering team's quality gate. Every code change passes through it before reaching production, and the quality of the gate determines the quality of what reaches users. For AI products, the standard pipeline steps (build, lint, test, deploy) are necessary but not sufficient. AI products also need evaluation steps that assess whether the AI component is behaving correctly after each change. This checklist is designed for CTOs and senior engineers who are setting up or improving a CI/CD pipeline for an AI SaaS product. It covers GitHub Actions workflow structure, type checking, unit and integration test configuration, LLM evaluation runs, and zero-downtime deployment steps. The result is a pipeline that gives the team confidence to deploy frequently without manually testing the AI behaviour after every change. For UK products in regulated sectors, the CI/CD pipeline is also part of the compliance story. FCA-regulated fintech firms and NHS-connected healthtech products are expected to demonstrate controlled, auditable deployment processes. A pipeline with deployment approvals, automated security scans, and a deployment history log provides exactly the evidence an ICO audit or an FCA systems review would look for. SpeedMVPs builds CI/CD pipelines as a standard component of every AI MVP delivery, including type checking, automated tests, and staging deployment, all configured and tested within the fixed-price two to three week sprint starting from GBP 8,000, with full code ownership handed over at the end.

How to use this template: Copy the sections below and adapt the placeholder content to your specific use case. Contact us if you need help implementing it.

What This Template Covers

The CI/CD pipeline checklist covers six pipeline stages that together define a production-grade delivery process for an AI product. The workflow structure section defines the trigger conditions (push to main, pull request to main, scheduled evaluation runs), the job dependencies (which jobs must complete before others start), and the environment matrix (different configurations for staging and production deployments). The static analysis stage covers type checking, linting, and formatting checks. These are fast checks that catch a large class of errors before the more expensive test stages run. The test stage covers unit tests, integration tests, and end-to-end tests. For AI products, this stage also includes the non-AI test coverage: the logic that processes AI inputs and outputs, the API endpoints, and the data layer. The LLM evaluation stage is specific to AI products. It runs the AI components against a curated evaluation dataset and reports quality metrics. This stage can block deployment if quality falls below a defined threshold. The build stage covers production build, asset optimisation, and any compilation steps required before deployment. The deployment stage covers staging deployment, smoke tests against the staging environment, production deployment using a zero-downtime strategy (blue-green, rolling, or canary), and post-deployment verification. The notification and rollback section covers how the team is notified of pipeline results and how a failed deployment is reversed.

How to Use This Template Step by Step

Step one: define your trigger strategy. At minimum, the pipeline should run on every push to the main branch and on every pull request that targets main. Add a scheduled trigger for comprehensive LLM evaluation runs that are too slow to run on every commit: daily or weekly depending on your evaluation dataset size and the cost of model inference during evaluation. Step two: set up the static analysis jobs. These should run first because they are fast and catch errors cheaply. Required checks: TypeScript type checking (tsc --noEmit), ESLint with your project's configured rules, and Prettier format checking. These checks should run in parallel and complete in under two minutes combined. Step three: configure the test suite. Separate unit tests from integration tests. Unit tests (testing individual functions and components in isolation) should run in under five minutes. Integration tests (testing database interactions, API endpoints, and external service mocks) take longer. For AI products, add a test category for the non-AI business logic that processes and validates AI inputs and outputs. Use mocked AI responses for these tests to avoid test flakiness from variable AI outputs. Step four: set up the LLM evaluation stage. Create an evaluation script that: loads your evaluation dataset, runs each input through the AI component, scores each output against the expected output, and reports aggregate metrics (accuracy, F1, task completion rate, or whichever metrics are defined in your PRD). Set a minimum passing threshold for each metric. The evaluation stage should run against the current code and compare to the last passing evaluation to detect regressions. Step five: configure the build step. For a Next.js application, this is npm run build or pnpm build. The build step should fail if there are TypeScript errors, missing environment variables, or any compile-time issue. Store build artifacts for the deployment step. Step six: set up staging deployment. Deploy to staging automatically on every successful pipeline run from the main branch. Run a smoke test suite against staging that verifies: the application is accessible, authentication works, the database connection is healthy, and the AI component returns a valid response for a test input. Fail the pipeline if smoke tests fail. Step seven: configure production deployment. Use a zero-downtime deployment strategy. For Vercel or Railway, this is handled automatically. For self-hosted infrastructure, implement either blue-green deployment (deploy to inactive environment, switch traffic) or rolling deployment (replace instances one at a time). Add a manual approval gate before production deployment if the team prefers that control.

Section-by-Section Walkthrough

The GitHub Actions workflow structure section uses a jobs object with explicit needs relationships. The recommended job order is: static-analysis (no dependencies, runs immediately), test (needs: static-analysis), evaluate-llm (needs: test, can run in parallel with other test jobs), build (needs: test), deploy-staging (needs: build), and deploy-production (needs: deploy-staging). The static analysis job should use a cached node_modules installation to keep it fast. Use the actions/cache action with a cache key based on the hash of the package lock file. Restoring from cache typically reduces installation time from 60 to 90 seconds to 5 to 10 seconds. The test job should set up a test database (PostgreSQL in a service container is standard for GitHub Actions) and run integration tests against it. Use a separate test database for each pipeline run to prevent test interference. Seed the test database with deterministic fixtures using a dedicated seeding script. The LLM evaluation job needs careful design to be useful rather than just slow. Key decisions: how large is the evaluation dataset (start with 50 to 100 examples, grow as needed), what is the maximum cost budget per evaluation run (set this as a guardrail), and what is the threshold for blocking deployment versus warning? For evaluation runs that are too expensive to run on every commit, use a separate scheduled workflow that runs nightly and posts results to a dashboard. The deployment jobs should use GitHub Environments for production deployments, which enables: environment-specific secrets, deployment protection rules (requiring reviewer approval), and deployment history tracking. This is particularly valuable for regulated products in fintech or healthtech where deployment approvals may need to be documented. The notification section should post pipeline results to Slack or Teams. Failed pipelines should generate an alert that includes: which job failed, the error message, a link to the full logs, and which commit triggered the failure. Successful production deployments should also be announced with the deployment URL and a brief summary of what was deployed.

Common Mistakes This Template Prevents

The most common CI/CD mistake for AI products is not having an automated LLM evaluation step at all. Teams that rely on manual testing of AI outputs after each change are unable to deploy quickly because manual testing does not scale. Automated evaluation with defined quality thresholds allows rapid iteration with confidence. This checklist makes LLM evaluation a first-class pipeline stage, not an afterthought. The second mistake is running all pipeline stages sequentially when many can run in parallel. A pipeline that takes 30 minutes because steps that could run simultaneously are running one after another slows development and discourages frequent commits. The job dependency structure in this template is designed to maximise parallelism. The third mistake is not having a rollback plan. Every deployment should have a defined rollback procedure that can be executed in under five minutes. For Vercel and Railway, rollback to the previous deployment is one click. For custom infrastructure, document the exact rollback steps and test them before they are needed in a crisis. The fourth mistake is using production secrets in the CI/CD pipeline in a way that could expose them in logs. All secrets should be stored in the CI/CD platform's secret management (GitHub Actions Secrets, not environment variables) and referenced by name. Log outputs from deployment steps should be reviewed to ensure secrets are not being printed.

Customisation Tips for Different Project Types

For products with a Python backend alongside a TypeScript frontend, add a separate Python CI job that runs mypy type checking, ruff linting, and pytest test suite. Run Python and TypeScript jobs in parallel to minimise total pipeline time. The LLM evaluation job can be written in Python if the evaluation logic is Python-native. For products that fine-tune or retrain models as part of the development cycle, add a model training pipeline separate from the deployment pipeline. Model training jobs are typically too slow and expensive to run on every commit. Trigger training jobs manually or on a weekly schedule, and gate model updates on evaluation results before promoting to production. For enterprise products with compliance requirements (fintech under FCA oversight, healthtech under NHS Digital requirements), add a compliance check stage. This can include: dependency vulnerability scanning (npm audit, Snyk), SAST (static application security testing) with tools like Semgrep, secrets scanning to ensure credentials are not committed to the repository, and licence compliance checking for open-source dependencies. For products deployed to AWS or GCP rather than managed platforms like Vercel, the deployment stage needs to include infrastructure-as-code steps (Terraform plan and apply, or AWS CDK deploy). Add a Terraform plan step to the CI pipeline that runs on pull requests so reviewers can see infrastructure changes before they are merged.

Frequently Asked Questions

How long should a CI/CD pipeline take for an AI product?+

A well-optimised pipeline for an AI product should complete the full cycle from commit to staging deployment in under 15 minutes for most change types. Static analysis should complete in under 2 minutes, unit tests in under 5 minutes, integration tests in under 8 minutes, and build and staging deployment in under 5 minutes. The LLM evaluation step is the variable: a small evaluation dataset (50 examples) might add 2 to 5 minutes, while a comprehensive evaluation against 500 examples might add 20 to 30 minutes. For lengthy evaluations, run them as a separate nightly job rather than blocking every deployment.

How do I avoid flaky tests caused by variable AI outputs?+

The key is to never assert on the exact content of AI-generated text in unit or integration tests. Instead: mock the AI provider entirely in unit tests (return a fixed, known response), use snapshot testing sparingly and only for very stable outputs, and test the logic around the AI call (input validation, output parsing, error handling) rather than the AI output itself. Reserve evaluation of actual AI output quality for the dedicated LLM evaluation stage, which uses metrics rather than exact string matching. This separation keeps your test suite deterministic and your evaluation stage meaningful.

Should I run database migrations in the CI/CD pipeline?+

Yes, migrations should be part of the deployment process. The standard approach is to run migrations as a pre-deployment step: run pending migrations against the target database before switching traffic to the new application version. This requires that migrations are backward-compatible with the previous application version (so that the old version can run against the new schema during the transition period). Write migrations that add columns before the application code that reads them, and remove columns only after the application code that reads them has been removed. Test migrations on a copy of the production database regularly.

How do I handle environment-specific configuration in the pipeline?+

Use the CI/CD platform's environment system to separate secrets and configuration for staging and production. In GitHub Actions, create separate Environments (Settings - Environments) for staging and production, each with their own secrets. Reference secrets using the secrets context syntax and they are automatically scoped to the current environment. Never hardcode environment-specific values in workflow files. Use environment variables for values that differ between environments (API URLs, feature flags, log levels) and secrets for credentials and keys.

What is a zero-downtime deployment and how do I implement one?+

Zero-downtime deployment means deploying a new version of the application without any period where the service is unavailable to users. For Vercel and Railway, zero-downtime is built in: new deployments become active only after they pass health checks, and the previous version handles traffic until the new version is ready. For self-hosted infrastructure, implement a rolling deployment: replace one server instance at a time, verifying health checks between each replacement, so at least one instance is always handling traffic. The key requirement is that the new version is backward-compatible with the current database schema during the transition period.

Want us to build this for you?

Download free or build your project with SpeedMVPs. Get a free consultation at speedmvps.co.uk

Get a Free Quote