← Labs

Lab 4: Deployment Pipelines (CI/CD)

Advanced
Level
GitHub Actions
Technology

Set up automated testing with GitHub Actions and deploy your Next.js application to Vercel staging environment.

Lab Overview

What You'll Do: Set up GitHub Actions for automated testing, deploy Next.js to Vercel, and configure staging environment

Lab Collaborators:

  • Edward Lampoh - Software Developer & Collaborator
  • Oluwafemi Adebayo, PhD - Academic Professor & Collaborator

🚨 Prerequisites Required

You must complete Labs 1, 2, & 3 with working tests before starting Lab 4.

Prerequisites Check

Before starting Lab 4, ensure you have:

  • ✅ GitHub repository with your code (forked from the lab)
  • ✅ Working Next.js application
  • ✅ Working Flask MLOps service
  • ✅ Passing tests from Lab 3: pytest test_app.py
  • ✅ GitHub account with push access to your repository

🔍 Quick Test

  1. 1. git status - should show your repo
  2. 2. npm run build - should build successfully
  3. 3. cd mlops-service && pytest test_app.py - all tests pass
  4. 4. If all work, you're ready for Lab 4!

Part A: GitHub Actions Setup

Configure automated testing for your Next.js and Flask applications

1. Repository Configuration

Enable GitHub Actions (if not already enabled):

  1. Go to your GitHub repository
  2. Click the "Actions" tab
  3. If prompted, click "I understand my workflows, go ahead and enable them"
  4. You should see a message about workflows being enabled

2. Test Configuration

Install testing dependencies:

bash
npm install --save-dev jest jest-environment-node

Your repository already includes comprehensive test suites and Jest configuration.

Part B: Automated Testing

GitHub Actions will automatically test your code on every commit

1. Create Next.js Workflow

Create the workflow directory structure:

bash
# Create .github/workflows directory
mkdir -p .github/workflows

Create the Next.js workflow file:

Create a file at .github/workflows/nextjs-ci.yml with the following content:

yaml
name: Next.js Testing
# Lab 4: Deployment Pipelines (CI/CD)
# This workflow handles automated testing of the Next.js application

on:
  push:
    branches: [ main, develop, test-cicd ]
    paths:
      - 'app/**'
      - 'components/**'
      - 'lib/**'
      - 'package.json'
      - 'package-lock.json'
      - 'next.config.js'
      - 'tailwind.config.js'
  pull_request:
    branches: [ main ]
    paths:
      - 'app/**'
      - 'components/**'
      - 'lib/**'
      - 'package.json'
      - 'package-lock.json'

jobs:
  # Test Job - Runs comprehensive testing
  test:
    name: Test Next.js Application
    runs-on: ubuntu-latest

    steps:
      # Checkout the repository
      - name: Checkout code
        uses: actions/checkout@v4

      # Set up Node.js
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'

      # Install dependencies
      - name: Install dependencies
        run: npm ci

      # Run comprehensive test suite
      - name: Run test suite
        run: npm test
        env:
          # Test environment variables
          NODE_ENV: test

      # Run linting (if ESLint is configured)
      - name: Run linting
        run: npm run lint || echo "Linting not configured, skipping..."
        continue-on-error: true

      # Run type checking (if TypeScript is configured)
      - name: Type check
        run: npx tsc --noEmit || echo "TypeScript not configured, skipping..."
        continue-on-error: true

      # Build the application
      - name: Build application
        run: npm run build

      # Verify build output
      - name: Verify build output
        run: |
          if [ -d ".next" ]; then
            echo "Build successful - .next directory exists"
            ls -la .next/
          else
            echo "Build failed - .next directory not found"
            exit 1
          fi

What This Workflow Does:

  • Triggers: Runs on push to main/develop, or pull requests
  • Setup: Installs Node.js 18 and dependencies with npm ci
  • Testing: Runs comprehensive test suite with Jest
  • Linting: Runs ESLint to check code quality (optional)
  • Type Checking: Validates TypeScript types (optional)
  • Building: Creates production build to verify deployment readiness

2. Test Your Workflows

Run tests locally first:

bash
# Run Next.js tests
npm test

# Run MLOps tests
cd mlops-service
pytest test_app.py -v

Trigger GitHub Actions:

bash
# Make a small change to trigger CI
echo "<!-- Testing Pipeline -->" >> README.md

# Commit and push
git add README.md
git commit -m "test: trigger testing pipeline"
git push origin main

Watch your workflow run:

  1. Go to your GitHub repository
  2. Click the "Actions" tab
  3. You should see your workflow running
  4. Click on the workflow to see detailed logs

✅ Success Indicators

  • • Green checkmark next to your commit
  • • "Test Next.js Application" job completes successfully
  • • Build creates .next directory

3. Create MLOps Service Workflow

Create the MLOps workflow file:

Create a file at .github/workflows/mlops-ci.yml with the following content:

yaml
name: MLOps Service Testing
# Lab 4: Deployment Pipelines (CI/CD)
# This workflow handles automated testing of the Flask MLOps service

on:
  push:
    branches: [ main, develop, test-cicd ]
    paths:
      - 'mlops-service/**'
  pull_request:
    branches: [ main ]
    paths:
      - 'mlops-service/**'

jobs:
  # Test Job - Runs pytest suite from Lab 3
  test:
    name: Test MLOps Service
    runs-on: ubuntu-latest

    defaults:
      run:
        working-directory: ./mlops-service

    steps:
      # Checkout the repository
      - name: Checkout code
        uses: actions/checkout@v4

      # Set up Python
      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.9'

      # Install dependencies
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      # Run pytest suite (from Lab 3)
      - name: Run tests
        run: |
          echo "Running MLOps service tests..."
          pytest test_app.py -v --tb=short
        env:
          # Test environment variables
          FLASK_ENV: testing
          TESTING: true

      # Test Flask app can start
      - name: Test Flask startup
        run: |
          echo "Testing Flask service startup..."
          timeout 10s python app.py &
          sleep 5

          # Test health endpoint
          curl -f http://localhost:5001/health || {
            echo "Health check failed"
            exit 1
          }

          echo "Flask service starts successfully"

      # Security scan
      - name: Security scan
        run: |
          echo "Running basic security checks..."
          pip install safety
          safety check || echo "Security warnings found, review before production"
        continue-on-error: true

What This Workflow Does:

  • Triggers: Runs when mlops-service/ files change
  • Setup: Installs Python 3.9 and Flask dependencies
  • Testing: Runs your Lab 3 pytest suite automatically
  • Flask Startup: Verifies the service can start and respond
  • Security Scan: Checks for vulnerable dependencies

💡 What Gets Tested

The MLOps workflow automatically runs all the tests you created in Lab 3:

  • • Health endpoint availability
  • • Prometheus metrics endpoint
  • • Metrics tracking functionality
  • • Error handling and validation

Part C: Vercel Deployment

Deploy your Next.js application to Vercel staging environment

1. Vercel Account Setup

Create your Vercel account:

  1. Go to vercel.com
  2. Click "Sign up with GitHub"
  3. Authorize Vercel to access your repositories
  4. Import your project repository

2. Deploy to Vercel

Configure deployment settings:

  1. In Vercel dashboard, click "Import Project"
  2. Select your GitHub repository
  3. Vercel will auto-detect Next.js settings
  4. Add environment variables in Vercel dashboard:

Environment Variables to Add:

  • DATABASE_URL - Your Neon database URL
  • GOOGLE_GENERATIVE_AI_API_KEY - Your Gemini API key
  • MLOPS_SERVICE_URL - http://localhost:5001 for now

Deploy your application:

bash
# Click "Deploy" in Vercel dashboard
# Wait for build to complete
# Get your staging URL: https://your-app-name.vercel.app

Part D: Testing Integration

1. Monitor Workflow Status

Check that both workflows are running:

  1. Go to your GitHub repository
  2. Click the "Actions" tab
  3. You should see both workflows running on commits
  4. Green checkmarks mean tests passed

2. Quality Gates

Your tests now act as quality gates:

  • Next.js tests: Validate API structure and business logic
  • MLOps tests: Ensure Flask service works correctly
  • Build verification: Confirms deployment readiness

💡 Key Learning

Your Lab 3 tests are now part of CI/CD:

  • • Every commit runs both test suites automatically
  • • Failed tests show up as red X marks on commits
  • • This prevents broken code from reaching staging

Part E: Workflow Monitoring

1. Check Deployment Status

Verify your Vercel deployment:

  1. Go to your Vercel dashboard
  2. Click on your project
  3. See deployment history and status
  4. Click "Visit" to see your live staging site

2. Test Your Staging Environment

Verify your staging deployment works:

  1. Visit your Vercel URL
  2. Try creating a test business
  3. Test the chat functionality
  4. Note: MLOps service will still be local for now

3. Debug Failed Workflows

When tests fail in GitHub Actions:

  1. Go to Actions tab → Click failed workflow
  2. Click the failed job to see detailed logs
  3. Look for error messages in red
  4. Fix the issue locally and push again

✅ Success Indicators

  • • Green checkmarks next to commits in GitHub
  • • Vercel shows successful deployment
  • • Your staging site loads and functions correctly

Troubleshooting

Tests failing in GitHub Actions:

Run tests locally first: npm test and pytest test_app.py

Vercel build failing:

Check that environment variables are set in Vercel dashboard

Workflow not triggering:

Ensure you're pushing to main or develop branch

Jest tests failing:

Check that jest and jest-environment-node are installed

Lab 4 Summary - What You Built

Congratulations! You've implemented a complete CI/CD pipeline for your AI application. Here's what you accomplished:

✅ What You Built

  • Automated Testing: GitHub Actions run tests on every commit
  • Next.js Test Suite: Comprehensive application validation
  • Flask Test Integration: Lab 3 pytest suite runs automatically
  • Vercel Deployment: Live staging environment
  • Quality Gates: Failed tests prevent broken deployments

🚀 Skills Gained

  • GitHub Actions: Automated testing workflows
  • Vercel Deployment: Staging environment setup
  • Test Integration: Quality gates for code changes
  • Environment Management: Development vs staging configuration

🎯 Next Steps

Lab 5 will cover containerization with Docker, and Lab 7 will handle cloud deployment of your Flask service.