Skip to main content

Deployment Guide: New GCP Project & Firebase Project

This guide walks you through deploying the Gamuda Technology Jira Tracker to a brand new GCP project with a new Firebase project.

📋 Prerequisites

Before starting, ensure you have:

  • Google Cloud Platform account with billing enabled
  • gcloud CLI installed (brew install google-cloud-sdk on macOS)
  • Terraform installed (brew install terraform on macOS)
  • Node.js >= 18.0.0 and npm >= 9.0.0
  • Firebase CLI installed (npm install -g firebase-tools)
  • Jira account with API access
  • Bitbucket account with API access

🚀 Step-by-Step Deployment

Step 1: Configure Environment Variables

First, create your .env file from the example:

# Copy the example configuration
cp env.example .env

# Edit with your values
nano .env

Update the following values in .env:

# ============================================================================
# GCP Infrastructure Configuration (for deployment scripts)
# ============================================================================
PROJECT_ID=your-company-jira-tracker # Must be globally unique
PROJECT_NAME=Jira Tracker Production
REGION=asia-southeast1
BILLING_ACCOUNT_ID=YOUR-BILLING-ACCOUNT-ID

# Cloud Run Configuration
SERVICE_NAME=gamuda-jira-tracker
CLOUD_RUN_MEMORY=512Mi
CLOUD_RUN_CPU=1
CLOUD_RUN_TIMEOUT=300
CLOUD_RUN_MAX_INSTANCES=10

# Cloud Scheduler Configuration
SYNC_SCHEDULE=0 1 * * * # 1:00 AM daily
TIME_ZONE=Asia/Kuala_Lumpur

Also configure your Firebase, Jira, and Bitbucket credentials in the same .env file (see env.example for all options).

Share dev Firestore in prod (optional): To have dev and prod use the same Firestore (the dev one), set in .env:

  • All NEXT_PUBLIC_FIREBASE_* and Firebase secrets to your dev Firebase project values.
  • FIRESTORE_PROJECT_ID=your-dev-firebase-project-id (e.g. gtc-chikeen-tan8f5-prj). Then deploy; the build will use dev Firebase for the client, and the server will use dev Firestore via FIRESTORE_PROJECT_ID. Store the dev service account JSON in GCP Secret Manager as firebase-service-account for the prod Cloud Run service.

Important: The .env file is in .gitignore and will not be committed to version control.

Step 2: Create New GCP Project

# Load your configuration
set -a
source .env
set +a

# Login to GCP (if not already logged in)
gcloud auth login
gcloud auth application-default login

# Create the project
gcloud projects create $PROJECT_ID --name="$PROJECT_NAME"

# Set as default project
gcloud config set project $PROJECT_ID

# Link billing account (REQUIRED for all subsequent steps)
gcloud billing projects link $PROJECT_ID --billing-account=$BILLING_ACCOUNT_ID

# Verify billing is linked
gcloud billing projects describe $PROJECT_ID

Step 2: Enable Required GCP APIs

# Enable all necessary APIs
gcloud services enable \
cloudbuild.googleapis.com \
run.googleapis.com \
secretmanager.googleapis.com \
firestore.googleapis.com \
cloudscheduler.googleapis.com \
firebase.googleapis.com \
--project=$PROJECT_ID

# Verify APIs are enabled
gcloud services list --enabled --project=$PROJECT_ID

Step 3: Create and Configure Firebase Project

3.1 Create Firebase Project (Web Console)

  1. Go to https://console.firebase.google.com
  2. Click "Add project"
  3. Select your existing GCP project: $PROJECT_ID
  4. Confirm Firebase billing plan
  5. Enable Google Analytics (optional)
  6. Click "Continue" to finish setup

3.2 Enable Firebase Authentication

  1. In Firebase Console, go to AuthenticationGet Started
  2. Enable Email/Password sign-in method
  3. For Google SSO: enable the Google sign-in method (Authentication → Sign-in method → Google → Enable). The Velocity app shows "Sign in with Google" when NEXT_PUBLIC_GOOGLE_SSO_ENABLED is not set to false.
  4. (Optional) Enable other providers (e.g. SAML/OIDC for company SSO — see SSO setup)

3.3 Create Firestore Database

  1. In Firebase Console, go to Firestore Database
  2. Click "Create database"
  3. Select Production mode
  4. Choose location: asia-southeast1 (or your preferred region)
  5. Click "Enable"

3.4 Register Web App

  1. In Firebase Console, go to Project Settings (gear icon)
  2. Scroll down to "Your apps" section
  3. Click the Web icon (</>)
  4. Register app with nickname: "Jira Tracker Web"
  5. Copy the Firebase config - you'll need this later
  6. Click "Continue to console"

3.5 Generate Service Account Key

  1. In Firebase Console, go to Project SettingsService accounts
  2. Click "Generate new private key"
  3. Click "Generate key" in the dialog
  4. Save the JSON file as firebase-service-account.json in your project root
  5. IMPORTANT: Never commit this file to Git

Step 4: Configure Firestore Rules and Indexes

# Deploy Firestore rules
firebase deploy --only firestore:rules --project=$PROJECT_ID

# Deploy Firestore indexes
firebase deploy --only firestore:indexes --project=$PROJECT_ID

Step 5: Set Up Secrets in Secret Manager

The setup script will automatically use your .env configuration. Run the setup script:

./setup-secrets.sh

The script will guide you through creating the following secrets:

Firebase Configuration:

  • firebase-api-key - From Firebase config (step 3.4)
  • firebase-auth-domain - e.g., your-project.firebaseapp.com
  • firebase-project-id - Your Firebase project ID
  • firebase-storage-bucket - e.g., your-project.appspot.com
  • firebase-messaging-sender-id - From Firebase config
  • firebase-app-id - From Firebase config
  • firebase-service-account - Contents of service account JSON (step 3.5)

Jira Configuration:

Bitbucket Configuration:

Step 6: Build and Deploy Application to Cloud Run

The deployment scripts will automatically use your .env configuration:

# Make deployment scripts executable
chmod +x deploy-to-gcp.sh
chmod +x deploy-all.sh

# Deploy the application
./deploy-to-gcp.sh

This will:

  1. Build the Docker container
  2. Push to Google Container Registry
  3. Deploy to Cloud Run
  4. Configure secrets
  5. Output the service URL

Save the service URL - you'll need it for the next steps.

Step 7: Configure Firebase Authorized Domains

Firebase only allows sign-in from domains listed here. If you use a custom URL (e.g. velocity.internal.gamuda.app), add it or you'll get auth/unauthorized-domain.

  1. Go to Firebase Console → AuthenticationSettings
  2. Scroll to Authorized domains
  3. Click "Add domain"
  4. Add each domain (without https://), for example:
    • Cloud Run: your-service-xxxxx-as.a.run.app
    • Custom/internal: velocity.internal.gamuda.app
  5. Click "Add" for each

Step 8: Deploy Cloud Scheduler (Auto-Sync)

9.1 Configure Terraform Variables

cd terraform

# Copy the example file
cp terraform.tfvars.example terraform.tfvars

# Edit with your values
nano terraform.tfvars

Update terraform.tfvars:

project_id             = "your-new-project-id"
region = "asia-southeast1"
cloud_run_service_name = "gamuda-jira-tracker"
app_url = "https://your-service-xxxxx-as.a.run.app" # From Step 7
sync_schedule = "0 1 * * *" # 1 AM daily
time_zone = "Asia/Kuala_Lumpur"

9.2 Deploy with Terraform

# Initialize Terraform
terraform init

# Preview changes
terraform plan

# Apply configuration
terraform apply

Type yes when prompted.

This will create:

  • Cloud Scheduler job (daily sync)
  • Service account for scheduler
  • IAM permissions

Step 9: Initial Setup and Testing

10.1 Access Your Application

Open your Cloud Run URL in a browser:

https://your-service-xxxxx-as.a.run.app

10.2 Create Admin User

  1. Click "Register"
  2. Create your admin account
  3. Login with your credentials

10.3 Configure Team Settings

  1. Upload team configuration:

    • Go to /settings
    • Upload configs/team-config.json
  2. Upload project mappings:

    • Go to /settings
    • Upload configs/project-mappings.json

10.4 Run Initial Sync

  1. Go to Sync Manager page
  2. Click "Sync All Data"
  3. Monitor the sync progress
  4. Initial sync may take 10-30 minutes depending on data volume

10.5 Test Cloud Scheduler

Manually trigger the scheduled job:

gcloud scheduler jobs run daily-jira-bitbucket-sync \
--location=$REGION \
--project=$PROJECT_ID

Check logs:

gcloud logging read "resource.type=cloud_scheduler_job" \
--limit=10 \
--project=$PROJECT_ID

Step 10: Configure Auto-Sync (Optional)

  1. Go to your app → Settings
  2. Toggle "Enable Auto-Sync" to ON
  3. Set sync time (e.g., 01:00)
  4. Click "Save Settings"

🔍 Verification Checklist

After deployment, verify:

  • Application accessible via Cloud Run URL
  • Firebase Authentication working
  • Can register and login
  • Firestore data persisting
  • Manual sync completes successfully
  • Dashboard displays data correctly
  • Cloud Scheduler job created
  • Scheduled sync triggers automatically
  • Secrets properly configured
  • All required APIs enabled

📊 Monitoring and Logs

View Cloud Run Logs

gcloud run services logs read $SERVICE_NAME \
--region=$REGION \
--project=$PROJECT_ID \
--limit=100

View Scheduler Logs

gcloud scheduler jobs logs $SERVICE_NAME \
--location=$REGION \
--project=$PROJECT_ID

Monitor in Console

🛠️ Troubleshooting

Issue: Build fails

# Check if Cloud Build API is enabled
gcloud services list --enabled | grep cloudbuild

# View build logs
gcloud builds list --project=$PROJECT_ID

Issue: Deployment fails with permission error

# Ensure you have necessary permissions
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="user:your-email@company.com" \
--role="roles/owner"

Issue: Secrets not accessible

# Grant Cloud Run access to secrets
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
SERVICE_ACCOUNT="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"

gcloud secrets add-iam-policy-binding SECRET_NAME \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/secretmanager.secretAccessor" \
--project=$PROJECT_ID

Issue: Firestore permission denied

  1. Check Firestore rules in Firebase Console
  2. Ensure rules allow authenticated users to read/write
  3. Verify service account has Firestore permissions

Issue: Scheduler not triggering

# Check if Cloud Scheduler API is enabled
gcloud services enable cloudscheduler.googleapis.com --project=$PROJECT_ID

# Verify job exists
gcloud scheduler jobs list --location=$REGION --project=$PROJECT_ID

# Check job configuration
gcloud scheduler jobs describe daily-jira-bitbucket-sync \
--location=$REGION \
--project=$PROJECT_ID

🔐 Security Best Practices

  1. Never commit secrets:

    • Add *.tfvars to .gitignore
    • Add firebase-service-account.json to .gitignore
    • Add .env.local to .gitignore
  2. Rotate credentials regularly:

    • Rotate Jira API tokens every 90 days
    • Rotate Bitbucket API tokens every 90 days
    • Rotate Firebase service accounts annually
  3. Use principle of least privilege:

    • Create separate service accounts for different functions
    • Grant only necessary IAM roles
    • Regularly audit IAM permissions
  4. Enable security features:

    • Enable Cloud Armor for DDoS protection
    • Set up Cloud Monitoring alerts
    • Enable audit logging
  5. Backup data:

    • Enable Firestore backups
    • Export data regularly
    • Test restore procedures

📝 Post-Deployment Tasks

  1. Set up monitoring:

    # Create uptime check
    gcloud monitoring uptime create $SERVICE_NAME-uptime \
    --display-name="Jira Tracker Uptime" \
    --http-check="$SERVICE_URL" \
    --project=$PROJECT_ID
  2. Configure alerting:

    • Set up alerts for failed syncs
    • Monitor Cloud Run errors
    • Track Firestore quota usage
  3. Document your setup:

    • Save project ID, region, and URLs
    • Document custom configuration
    • Share access with team members
  4. Schedule maintenance:

    • Plan for regular updates
    • Test disaster recovery
    • Review and optimize costs

💰 Cost Optimization

  1. Cloud Run:

    • Use minimum instances: 0
    • Set max instances: 10
    • Adjust memory based on usage
  2. Firestore:

    • Monitor read/write operations
    • Optimize queries
    • Use composite indexes
  3. Cloud Scheduler:

    • Free tier: 3 jobs/month
    • Current setup: 1 job (within free tier)
  4. Secret Manager:

    • Free tier: 6 active secrets
    • Current setup: 13 secrets ($0.36/month)

🎯 Next Steps

  • Set up custom domain (optional)
  • Configure SSL certificate (optional)
  • Enable Cloud CDN (optional)
  • Set up staging environment
  • Configure CI/CD pipeline
  • Add more team members
  • Customize reports
  • Integrate with other tools

📞 Support

For issues or questions:

  • Check logs in GCP Console
  • Review Firestore rules
  • Verify Secret Manager configuration
  • Contact your infrastructure team

Deployment Date: _________________
Deployed By: _________________
Project ID: _________________
Cloud Run URL: _________________
Firebase Project: _________________