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 Authentication → Get 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 Settings → Service 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 → Authentication → Settings
  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: _________________