Skip to main content
Arre uses GitHub Actions for continuous integration and deployment, featuring an AI-powered QA agent that analyzes test failures and provides automated debugging insights.

Pipeline Overview

The CI/CD architecture consists of three main workflows:

Workflows

1. AI QA Agent Pipeline

File: .github/workflows/qa-agent.yml Trigger: Pull request opened or updated Purpose: Run E2E tests and provide AI-powered failure analysis
1

Checkout code

Fetches the PR branch with full git history for diff generation:
- uses: actions/checkout@v4
  with:
    fetch-depth: 0
2

Install dependencies

Sets up Node.js, installs npm packages, and Playwright browsers:
- name: Install dependencies (root)
  run: npm ci

- name: Install dependencies (functions)
  run: cd functions && npm ci

- name: Install Playwright Browsers
  run: npx playwright install --with-deps
3

Set up Firebase Emulators

Installs Java 21 required for Firebase Emulators:
- name: Set up Java 21
  uses: actions/setup-java@v4
  with:
    distribution: "temurin"
    java-version: "21"
4

Run Playwright tests

Executes tests in emulator environment:
- name: Run Playwright tests
  run: CI=true npx firebase emulators:exec "npx playwright test --project=chromium" --project demo-test
  continue-on-error: true
continue-on-error: true ensures the AI agent runs even when tests fail.
5

Run AI QA Agent

If tests fail, Gemini 2.5 analyzes the failure:
- name: Run AI QA Agent
  run: node scripts/qa-agent.js
  env:
    GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    PR_NUMBER: ${{ github.event.pull_request.number }}

AI QA Agent Features

The Gemini 2.5-powered QA agent:
  • Analyzes test failures - Reads error logs, stack traces, and test reports
  • Reviews code changes - Examines git diff to understand what changed
  • Provides root cause analysis - Identifies why tests failed
  • Suggests fixes - Posts actionable debugging steps as PR comments
  • Learns from context - Uses full repository context for accurate insights
const testResults = JSON.parse(fs.readFileSync('test-results.json'));
const gitDiff = execSync('git diff origin/main').toString();

const analysis = await gemini.analyze({
  testResults,
  gitDiff,
  traces: './test-results/',
  prompt: 'Analyze test failures and provide debugging guidance'
});

await github.rest.issues.createComment({
  owner: process.env.REPO_OWNER,
  repo: process.env.REPO_NAME,
  issue_number: process.env.PR_NUMBER,
  body: analysis
});
The AI agent requires a GEMINI_API_KEY secret. Without it, tests still run but automated analysis is skipped.

2. Preview Deployment

File: .github/workflows/firebase-hosting-pull-request.yml Trigger: Pull request opened or updated Purpose: Deploy temporary preview environment for visual testing
name: Deploy to Firebase Hosting on PR
on: pull_request

jobs:
  build_and_preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Build
        run: npm ci && npm run build
        env:
          VITE_FIREBASE_API_KEY: ${{ secrets.VITE_FIREBASE_API_KEY }}
          VITE_FIREBASE_AUTH_DOMAIN: ${{ secrets.VITE_FIREBASE_AUTH_DOMAIN }}
          VITE_FIREBASE_PROJECT_ID: ${{ secrets.VITE_FIREBASE_PROJECT_ID }}
      
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: ${{ secrets.GITHUB_TOKEN }}
          firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_ARRE_APP_DEV }}
          projectId: arre-app-dev
          expires: 6h

3. Production Deployment

File: .github/workflows/firebase-hosting-merge.yml Trigger: Code merged to main branch Purpose: Deploy to live production site
name: Deploy to Firebase Hosting on merge
on:
  push:
    branches:
      - main

jobs:
  build_and_deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Install dependencies
        run: npm ci
      
      - name: Install dependencies (functions)
        run: cd functions && npm ci
      
      - name: Build
        run: npm run build
        env:
          VITE_FIREBASE_API_KEY: ${{ secrets.VITE_FIREBASE_API_KEY }}
          VITE_FIREBASE_AUTH_DOMAIN: ${{ secrets.VITE_FIREBASE_AUTH_DOMAIN }}
          VITE_FIREBASE_PROJECT_ID: ${{ secrets.VITE_FIREBASE_PROJECT_ID }}
          VITE_FIREBASE_STORAGE_BUCKET: ${{ secrets.VITE_FIREBASE_STORAGE_BUCKET }}
          VITE_FIREBASE_MESSAGING_SENDER_ID: ${{ secrets.VITE_FIREBASE_MESSAGING_SENDER_ID }}
          VITE_FIREBASE_APP_ID: ${{ secrets.VITE_FIREBASE_APP_ID }}
      
      - name: Deploy Firebase Backend
        uses: w9jds/firebase-action@master
        with:
          args: deploy --only firestore,functions --force
        env:
          GCP_SA_KEY: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_ARRE_APP_DEV }}
          PROJECT_ID: arre-app-dev
      
      - uses: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: ${{ secrets.GITHUB_TOKEN }}
          firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_ARRE_APP_DEV }}
          channelId: live
          projectId: arre-app-dev

Deployment Steps

1

Build application

Vite compiles the app with production optimizations:
npm run build
Output: dist/ directory with static assets
2

Deploy backend

Updates Firestore rules, indexes, and Cloud Functions:
firebase deploy --only firestore,functions --force
3

Deploy hosting

Uploads static assets to Firebase Hosting:
firebase deploy --only hosting
Live at: https://arre-app-dev.web.app

Environment Variables

All sensitive configuration is stored in GitHub Secrets:
SecretDescription
VITE_FIREBASE_API_KEYFirebase project API key
VITE_FIREBASE_AUTH_DOMAINFirebase Auth domain
VITE_FIREBASE_PROJECT_IDFirebase project ID
VITE_FIREBASE_STORAGE_BUCKETFirebase Storage bucket
VITE_FIREBASE_MESSAGING_SENDER_IDFCM sender ID
VITE_FIREBASE_APP_IDFirebase app ID
FIREBASE_SERVICE_ACCOUNT_ARRE_APP_DEVService account for deployment
GEMINI_API_KEYAPI key for AI QA agent
Never commit .env files or hardcode secrets in source code. All environment variables must be injected at build time via GitHub Secrets.

Setting Secrets

1

Navigate to repository settings

Go to Settings > Secrets and variables > Actions
2

Add new secret

Click New repository secret
3

Enter name and value

  • Name: VITE_FIREBASE_API_KEY
  • Value: AIzaSy...
4

Save

Click Add secret

Security & Best Practices

12-Factor App Methodology

The build process enforces strict separation of config from code:
  • ✅ Environment variables injected at build time
  • ✅ No plaintext secrets in repository
  • ✅ Different configs for dev/preview/production
  • ✅ Zero-trust deployment via service accounts

Service Account Authentication

Deployments use Firebase service accounts instead of personal credentials:
env:
  GCP_SA_KEY: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_ARRE_APP_DEV }}
This ensures:
  • No human credentials in CI/CD
  • Fine-grained permission control
  • Audit trail for all deployments

CI/CD Configuration

Optimal settings for stability:
SettingValueReason
workers1 on CIPrevents race conditions
retries2 on CIHandles flaky tests
forbidOnlytrue on CIPrevents accidental .only() merges
reporterJSON + HTMLEnables AI analysis

Rollback Strategy

Firebase Hosting retains deployment history. To rollback:
1

Open Firebase Console

Navigate to Firebase Console
2

View hosting releases

Go to Build > Hosting > Release history
3

Select previous version

Click on the stable release
4

Rollback

Click Rollback to restore the previous version
Rollbacks take effect immediately. No rebuild required.

Monitoring & Debugging

View Workflow Runs

Check CI/CD status in GitHub:
  1. Go to Actions tab
  2. Select workflow (QA Agent, Preview, Production)
  3. View logs for each step

Test Reports

Playwright generates HTML reports:
# View locally after test run
px playwright show-report
On CI, reports are available as artifacts.

AI QA Comments

When tests fail, the AI agent posts comments like:
Test Failure Analysis Failed Test: should create a manual task Root Cause: The btn-create-task button is disabled because the form validation is now requiring a date field, which was added in commit abc123. Suggested Fix:
  1. Update test to fill the date field before clicking create
  2. Or make the date field optional in the validation schema
Code Reference: src/components/NewTaskModal.tsx:145

Next Steps

Testing Guide

Learn how to write and run Playwright tests

Deployment

Manual deployment and production operations

Build docs developers (and LLMs) love