alumni_lookup

CI Pipeline Design

Last Updated: December 2, 2025
Purpose: Define continuous integration workflows for automated testing and deployment gating.


Table of Contents

  1. CI Goals
  2. Tooling
  3. Workflow Definitions
  4. Quality Gates
  5. Test Categories & Priorities
  6. Workflow YAML Specifications

CI Goals

Primary Objectives

  1. Every push runs tests — No code reaches main without passing the full Minitest suite
  2. Fail fast — Break the build early on test failures
  3. Block broken deploys — Staging and production deploys gated on test success
  4. Developer feedback — Clear, fast results on PRs

Secondary Objectives (Future)


Tooling

Primary: GitHub Actions

Why GitHub Actions:

No existing CI configuration found — we’ll create from scratch.

Runners

Environment Runner
All workflows ubuntu-latest

Required Services

Service Purpose Version
PostgreSQL Test database 14+
Ruby Application runtime 3.2.3+ (from .ruby-version)
Node.js Asset compilation 18+ (from package.json)

Workflow Definitions

Overview

┌─────────────────────────────────────────────────────────────────────────┐
│                           CI/CD Pipeline                                 │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   ┌──────────────┐    ┌──────────────┐    ┌──────────────┐             │
│   │ Pull Request │───▶│    CI        │───▶│   Merge      │             │
│   │ Created      │    │ (tests)      │    │   to main    │             │
│   └──────────────┘    └──────────────┘    └──────┬───────┘             │
│                              │                    │                      │
│                              │ Must pass          │                      │
│                              ▼                    ▼                      │
│                       ┌──────────────┐    ┌──────────────┐             │
│                       │ Block merge  │    │ Deploy to    │             │
│                       │ if failing   │    │ Staging      │             │
│                       └──────────────┘    └──────┬───────┘             │
│                                                   │                      │
│                                                   │ Smoke tests          │
│                                                   ▼                      │
│                                           ┌──────────────┐             │
│                                           │ Deploy to    │◀── Manual   │
│                                           │ Production   │    or tag   │
│                                           └──────────────┘             │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

Workflow 1: CI (Test Suite)

File: .github/workflows/ci.yml

Trigger Behavior
push to any branch Run tests
pull_request to main Run tests, block merge if failing

Jobs:

  1. test
    • Checkout code
    • Setup Ruby (from .ruby-version)
    • Setup Node.js
    • Install dependencies (bundle install, npm install)
    • Setup test database
    • Run rails test

Estimated Duration: 3-5 minutes


Workflow 2: Deploy to Staging

File: .github/workflows/deploy-staging.yml

Trigger Behavior
push to main (after merge) Deploy to staging
Manual dispatch Deploy to staging on demand

Jobs:

  1. test — Re-run full test suite (don’t trust cached results)
  2. deploy — Deploy to Heroku staging app
  3. smoke — Run basic smoke tests against staging URLs

Dependencies:


Workflow 3: Deploy to Production

File: .github/workflows/deploy-production.yml

Trigger Behavior
Git tag (v*) Deploy tagged release to production
Manual dispatch with approval Deploy on demand

Jobs:

  1. test — Full test suite
  2. deploy — Deploy to Heroku production app
  3. verify — Post-deploy verification

Safety Gates:


Quality Gates

Gate 1: Merge to Main

Requirement Enforcement
All tests pass GitHub branch protection rule
PR reviewed (optional for solo) GitHub branch protection rule
No conflicts Git

Setup: Configure branch protection on main to require CI passing.


Gate 2: Deploy to Staging

Requirement Enforcement
Tests pass on main CI workflow
Build succeeds Heroku
Migrations run cleanly Heroku release phase

Automatic: Deploys trigger on merge to main.


Gate 3: Deploy to Production

Requirement Enforcement
Tests pass CI workflow
Staging smoke tests pass Deploy workflow
Tag created OR manual approval Workflow trigger

Semi-Automatic: Create tag to deploy, or manually trigger with approval.


Test Categories & Priorities

Based on TESTING_GUIDE.md and TODO_BUGS.md:

P0: Critical (Must Always Pass)

Category Test File Description
Authentication sessions_controller_test.rb Login/logout, session security
User Management users_controller_test.rb Admin-only access, profile security
Model Validations alumni_test.rb, user_test.rb Data integrity

P1: High Priority

Category Test File Description
Alumni Search alumni_controller_test.rb Core search functionality
Engagement engagement_score_calculator_test.rb Scoring accuracy
Champion Signup champion_signup_test.rb External-facing flow
Permissions *_controller_test.rb Role-based access

P2: Medium Priority

Category Test File Description
Settings settings/*_controller_test.rb Admin CRUD operations
Affinities alumni_affinities_controller_test.rb Affinity management
Mailers *_mailer_test.rb Email content/delivery

P3: Lower Priority

Category Description
Edge cases Unusual input handling
Performance Query optimization (not currently tested)

Known Fragile Areas

From TODO_BUGS.md:

Issue Area Test Impact
Modal flow edge case Alumni affinities Low — JavaScript path is primary
Activity code validation Engagement activities Medium — could add validation test

Workflow YAML Specifications

1. CI Workflow (ci.yml)

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: ['**']
  pull_request:
    branches: [main]

env:
  RAILS_ENV: test
  DATABASE_URL: postgres://postgres:postgres@localhost:5432/alumni_lookup_test

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      postgres:
        image: postgres:14
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: alumni_lookup_test
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

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

      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: .ruby-version
          bundler-cache: true

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

      - name: Install Node dependencies
        run: npm ci

      - name: Build CSS
        run: npm run build:css

      - name: Setup database
        run: |
          bin/rails db:create
          bin/rails db:schema:load

      - name: Run tests
        run: bin/rails test

      - name: Upload test results (on failure)
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: tmp/test-results/
          retention-days: 7

2. Deploy Staging Workflow (deploy-staging.yml)

# .github/workflows/deploy-staging.yml
name: Deploy to Staging

on:
  push:
    branches: [main]
  workflow_dispatch:

env:
  HEROKU_APP_STAGING: alumni-lookup-staging

jobs:
  test:
    uses: ./.github/workflows/ci.yml

  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: staging

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

      - name: Deploy to Heroku
        uses: akhileshns/heroku-deploy@v3.13.15
        with:
          heroku_api_key: $
          heroku_app_name: $
          heroku_email: $

      - name: Run migrations
        run: |
          heroku run rails db:migrate --app $
        env:
          HEROKU_API_KEY: $

  smoke-test:
    needs: deploy
    runs-on: ubuntu-latest

    steps:
      - name: Wait for deploy
        run: sleep 30

      - name: Check lookup portal
        run: |
          curl -f https://staging-lookup.bualum.co/users/sign_in || exit 1

      - name: Check champions portal
        run: |
          curl -f https://staging-champions.bualum.co/ || exit 1

3. Deploy Production Workflow (deploy-production.yml)

# .github/workflows/deploy-production.yml
name: Deploy to Production

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:

env:
  HEROKU_APP_PRODUCTION: alumni-lookup

jobs:
  test:
    uses: ./.github/workflows/ci.yml

  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: production  # Enables approval requirement

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

      - name: Deploy to Heroku
        uses: akhileshns/heroku-deploy@v3.13.15
        with:
          heroku_api_key: $
          heroku_app_name: $
          heroku_email: $

      - name: Run migrations
        run: |
          heroku run rails db:migrate --app $
        env:
          HEROKU_API_KEY: $

  verify:
    needs: deploy
    runs-on: ubuntu-latest

    steps:
      - name: Wait for deploy
        run: sleep 30

      - name: Verify lookup portal
        run: |
          curl -f https://lookup.bualum.co/users/sign_in || exit 1

      - name: Verify champions portal
        run: |
          curl -f https://champions.bualum.co/ || exit 1

Implementation Checklist

Phase 1: Basic CI

Phase 2: Staging Deploy

Phase 3: Production Deploy


Secrets Required

Secret Purpose How to Get
HEROKU_API_KEY Deploy to Heroku heroku auth:token
HEROKU_EMAIL Heroku account email Your Heroku login email

Add secrets at: https://github.com/<owner>/<repo>/settings/secrets/actions