Skip to content

Deployment

See ENVIRONMENTS.md for a complete overview of all environments and their configurations.

CI/CD with GitHub Actions

This project uses GitHub Actions for automated deployment with separate workflows for frontend and backend:

Development Deploys (main branch)

  • Frontend Deploy

    • File: .github/workflows/deploy-frontend-dev.yml
    • Trigger: Pushes to main branch (paths: web/, shared/, firestore.rules, firebase.json)
    • Deploys to Firebase Hosting dev target + Firestore rules
    • Uses secrets prefixed with DEV_
    • Generates version.json for deploy verification
  • Functions Deploy

    • File: .github/workflows/deploy-functions-dev.yml
    • Trigger: Pushes to main branch (paths: functions/, shared/, firebase.json)
    • Deploys Cloud Functions to Firebase (Cloud Run)
    • Sets environment variables on Cloud Run services
    • Uses secrets prefixed with DEV_
    • Includes health checks for API endpoints

Production Deploy (Tag-based)

  • File: .github/workflows/deploy-prod.yml
  • Trigger: Pushes of version tags matching v*.*.* (e.g., v1.2.3)
  • Deploys: Frontend to Firebase Hosting prod target + Firestore rules
  • Uses: Secrets prefixed with PROD_
  • Note: Functions source is in functions/ in this monorepo. Dev deploys automatically. Prod functions deploy via deploy-functions-prod.yml on version tags.

Why Tag-based Production Releases?

  • Every production release has an immutable identifier (the tag) that points to the exact commit deployed
  • Rollbacks are simple: redeploy an older tag
  • No separate prod branch is required
  • Clear version history and release tracking

Required GitHub Secrets

Development (main branch)

Frontend secrets:

  • DEV_VITE_PUBLIC_APIKEY
  • DEV_VITE_PUBLIC_AUTHDOMAIN
  • DEV_VITE_PUBLIC_PROJECTID
  • DEV_VITE_PUBLIC_STORAGEBUCKET
  • DEV_VITE_PUBLIC_MESSAGINGSENDERID
  • DEV_VITE_PUBLIC_APPID
  • DEV_VITE_PUBLIC_MEASUREMENT_ID
  • DEV_VITE_PUBLIC_VAPID_KEY
  • DEV_FIREBASE_SERVICE_ACCOUNT (service account JSON content)

Functions integration secrets:

  • GOOGLE_CALENDAR_CLIENT_ID
  • GOOGLE_CALENDAR_CLIENT_SECRET
  • GOOGLE_CALENDAR_REDIRECT_URI
  • DISCORD_CLIENT_ID
  • DISCORD_CLIENT_SECRET
  • DISCORD_REDIRECT_URI
  • ENCRYPTION_KEY

Build notification secrets:

  • DISCORD_WEBHOOK_BUILDS (Discord webhook URL for build notifications)
  • DISCORD_WEBHOOK_AI_DEV (Discord webhook URL for dev channel)

Production (tag-based releases)

  • PROD_VITE_PUBLIC_APIKEY
  • PROD_VITE_PUBLIC_AUTHDOMAIN
  • PROD_VITE_PUBLIC_PROJECTID
  • PROD_VITE_PUBLIC_STORAGEBUCKET
  • PROD_VITE_PUBLIC_MESSAGINGSENDERID
  • PROD_VITE_PUBLIC_APPID
  • PROD_VITE_PUBLIC_MEASUREMENT_ID
  • PROD_VITE_PUBLIC_VAPID_KEY
  • PROD_VITE_PUBLIC_SERVICE_ACCOUNT (service account JSON content)
  • PROD_VITE_API_URL (prod Cloud Run API URL — required, no fallback)

How it Works

Frontend Workflow

  1. Build job:
    • Installs dependencies with pnpm install
    • Builds the web app with pnpm build:web
    • Generates version.json with commit SHA for deploy verification
    • Archives the build output (web/dist/)
  2. Deploy job:
    • Downloads the build artifact
    • Deploys to Firebase Hosting: firebase deploy --only hosting:dev (or hosting:prod)
    • Deploys Firestore rules: firebase deploy --only firestore:rules
    • Deploys Firestore indexes: firebase deploy --only firestore:indexes
  3. Health Check:
    • Verifies frontend is accessible (HTTP 200)
    • Verifies version.json exists and SHA matches deployed commit
  4. Notify:
    • Sends build status to Discord channels

Functions Workflow

  1. Build job:
    • Installs dependencies with pnpm install
    • Builds shared types: pnpm build:shared
    • Builds functions: pnpm build:functions
  2. Deploy job:
    • Deploys Cloud Functions: firebase deploy --only functions --project seed-start-7255a
    • Removes old environment variables from Cloud Run services
    • Sets new environment variables (Calendar, Discord integrations)
  3. Health Check:
    • Verifies API health endpoint returns 200 OK
    • Validates JSON response
    • Checks frontend homepage
  4. Notify:
    • Sends build status to Discord channels

Adding/Updating Secrets

  • Go to your GitHub repo > Settings > Secrets and variables > Actions.
  • Add or update the required secrets for each environment.

How to Release to Production

From your local machine:

bash
git checkout main
git pull

git tag -a v1.2.3 -m "Production release v1.2.3"
git push origin v1.2.3

This triggers the production workflow and deploys exactly that tag.

B) Create Release via GitHub Website

  1. Go to your repo in GitHub
  2. Click Releases (right side) → Draft a new release
  3. In Choose a tag, type a new tag like v1.2.3
  4. In Target, choose the branch/commit to tag:
    • Usually main (GitHub will tag the latest commit on main)
    • Or select a specific commit if needed
  5. Click Publish release

Result:

  • GitHub creates the tag v1.2.3
  • Your deploy-prod.yml (tag trigger) runs
  • Prod deploy happens

C) Rollback

To rollback production, redeploy a previous version tag (e.g., v1.2.2) by re-running the workflow for that tag in GitHub Actions (or pushing the tag if it didn't exist yet).

Small-team Guardrails

  • Only cut tags from commits that already passed CI on main
  • Protect tags if you want: disallow deleting tags (optional)
  • Keep tag format consistent: vX.Y.Z

This document describes how to build, test, and deploy the project, including CI/CD and environment setup.


Local Build Process

Build the entire project:

bash
pnpm install
pnpm build

Or build specific packages:

bash
# Build web only
pnpm build:web

# Build functions only
pnpm build:functions

# Build shared types
pnpm build:shared

Output locations:

  • Frontend: web/dist/
  • Functions: functions/lib/
  • Shared: shared/dist/

Testing Before Deploy

Run tests and lint checks:

bash
pnpm lint
pnpm test

Manual Deployment Steps

Note: Automated deployment via GitHub Actions is preferred. Manual deployment is for debugging only.

  1. Ensure you have Firebase CLI:

    bash
    npm install -g firebase-tools
    firebase login
  2. Build the project:

    bash
    pnpm build
  3. Deploy to Firebase:

    bash
    # Deploy everything
    firebase deploy --project seed-start-7255a
    
    # Or deploy specific targets
    firebase deploy --only hosting:dev --project seed-start-7255a
    firebase deploy --only functions --project seed-start-7255a
  4. Verify deployment by visiting the deployed URL.


CI/CD

  • The project uses GitHub Actions for automated builds and deploys.
  • All PRs should pass tests and lint before merging.
  • Main branch deploys automatically to development.
  • Production deploys are triggered by version tags (v*.*.*).

Best Practices

  • Never commit secrets or API keys to the repo.
  • Use environment variables for sensitive config.
  • Test thoroughly before deploying.
  • Monitor error logs after deployment.

For more, see ARCHITECTURE.md or ask a maintainer.

Internal docs — access restricted via Cloudflare Zero Trust.