Skip to main content

Overview

This document describes the Continuous Integration and Continuous Deployment (CI/CD) pipeline for the HandaUncle Backend application. The pipeline automates building, testing, security scanning, and deploying the application across multiple environments.
The pipeline uses GitHub Actions for automation and Google Cloud Run for deployments with Workload Identity Federation for secure, keyless authentication.

Architecture

Environments

Development

Trigger: Manual (Claim β†’ Deploy β†’ Release)Project: Dev GCP ProjectPurpose: Feature development and testing

Staging

Branch: developProject: Staging GCP ProjectPurpose: Pre-production testing and QA

Production

Branch: mainProject: Production GCP ProjectPurpose: Live production environment

Branch Strategy

Git Flow

Branch Rules

  • Created from develop
  • Manual deployment to Dev environment (Claim β†’ Deploy β†’ Release)
  • Must pass CI checks before merging
  • Used for individual feature development
  • Receives merges from feature branches via PR
  • Auto-deploys to Staging environment on push
  • Protected: Requires PR with passing checks
  • Used for integration testing
  • Only accepts PRs from develop
  • Auto-deploys to Production on push
  • Protected: Requires PR from develop only
  • Never push directly to main
Never push directly to main. All production deployments must go through develop first.

Dev Environment Lock System

The Dev environment uses a claim/release system to prevent multiple developers from overwriting each other’s deployments during testing.

How It Works

Workflow Steps

Claim the Environment

Run πŸ”’ Claim Dev Environment workflow
  • Blocks other developers from deploying
  • Shows who has the environment claimed

Deploy Your Branch

Run πŸš€ Deploy to Dev workflow
  • Enter your branch name (e.g., feature/my-feature)
  • Only works if you own the claim

Test Your Changes

Test as long as needed
  • Environment stays locked to you
  • Other developers see β€œclaimed by @you”

Release When Done

Run πŸ”“ Release Dev Environment workflow
  • Frees the environment for others
  • Don’t forget this step!

Emergency Release

If a developer forgets to release and is unavailable:
  1. Run πŸ”“ Release Dev Environment
  2. Check the Force release checkbox
  3. This will release even if claimed by someone else
Only use force release in emergencies. Always try to contact the developer first.

Workflow Files

CI Pipeline (ci.yml)

Triggers:
  • Push to: main, develop, feature/**
  • Pull requests to: main, develop
Artifacts:
  • Vulnerability report (JSON) - 30-day retention

Dev Environment Workflows

WorkflowFilePurpose
πŸ”’ Claim Dev Environmentclaim-dev.ymlClaim exclusive access to dev
πŸš€ Deploy to Devdeploy-dev.ymlDeploy a branch to dev (requires claim)
πŸ”“ Release Dev Environmentrelease-dev.ymlRelease dev for others to use

Deploy to Staging (deploy-staging.yml)

Authenticate to GCP

Uses Workload Identity Federation for keyless authentication

Build Docker Image

Build with commit SHA tag for traceability

Push to Artifact Registry

Push to regional Docker registry

Deploy to Cloud Run

Deploy with all secrets injected from Secret Manager

Output URL

Display the deployment URL in workflow summary
Concurrency: Only one staging deployment runs at a time (others queue)

PR Checks (pr-checks.yml)

JobDescription
Branch ProtectionBlocks direct PRs to main (must come from develop)
PR SummaryDisplays PR information and merge path

GCP Infrastructure

Projects

EnvironmentPurpose
DevFeature development and testing
StagingPre-production QA
ProductionLive environment

Enabled APIs

Cloud Run Admin API

Container deployment and management

Artifact Registry API

Docker image storage

Secret Manager API

Secure secrets storage

IAM API

Identity and access management

Workload Identity Federation

Enables keyless authentication from GitHub Actions to GCP - no service account keys needed!
How it works:
  1. GitHub Actions generates an OIDC token
  2. GCP exchanges it for a short-lived access token
  3. No long-lived credentials stored anywhere

Service Accounts

PurposeDescription
GitHub Actions SAUsed by CI/CD to deploy
Cloud Run SARuntime identity for the application
IAM Roles (GitHub Actions SA):
  • Cloud Run Admin
  • Artifact Registry Writer
  • Service Account User
  • Secret Manager Accessor

Secrets Management

GitHub Repository Secrets

CategoryDescription
Workload IdentityProvider URLs for each environment
Service AccountsEmail addresses for GCP authentication

GitHub Repository Variables

VariableDescription
DEV_CLAIMED_BYTracks who has claimed the dev environment

GCP Secret Manager

Core Configuration

Server port, backend secrets, environment settings
Database connection strings, Redis configuration
OAuth provider credentials, JWT secrets
API keys for various AI providers (LLMs, embeddings)
Vector database and memory service credentials
Monitoring and analytics service credentials
Document processing and storage credentials
Payment gateway credentials
Feature configuration values

Development Workflow

Creating a New Feature

1

Start from develop

git checkout develop
git pull origin develop
2

Create feature branch

git checkout -b feature/my-new-feature
3

Make changes and commit

git add .
git commit -m "feat: Add new feature"
4

Push your branch

git push origin feature/my-new-feature

Deploying to Dev

1

Claim the environment

Go to Actions β†’ πŸ”’ Claim Dev Environment β†’ Run workflow
You now have exclusive access to dev!
2

Deploy your branch

Go to Actions β†’ πŸš€ Deploy to Dev β†’ Run workflow
  • Enter your branch name (e.g., feature/my-new-feature)
    Your code is deploying to Dev!
3

Test your changes

Use the deployment URL shown in the workflow summary
4

Release when done

Go to Actions β†’ πŸ”“ Release Dev Environment β†’ Run workflow
Environment is now available for others!

Promoting to Staging

1

Create Pull Request

Go to GitHub and create a PR: feature/my-new-feature β†’ develop
2

Wait for CI checks

All lint, tests, and security scans must pass
3

Get code review

Have a teammate review your changes
4

Merge PR

Merging automatically triggers staging deployment!

Promoting to Production

1

Create PR from develop to main

Go to GitHub and create a PR: develop β†’ main
2

Wait for CI checks

All checks must pass
3

Get approval

Production deployments require approval
4

Merge PR

Merging automatically triggers production deployment!

Monitoring & Debugging

Viewing Workflow Runs

  1. Go to: GitHub Actions
  2. Select the workflow (CI Pipeline, Deploy Dev, etc.)
  3. Click on a specific run to see logs

Viewing Deployment Logs

# View logs for a Cloud Run service
gcloud run services logs read SERVICE_NAME \
  --project=PROJECT_ID \
  --region=REGION

Getting Deployment URLs

# Get the URL for a Cloud Run service
gcloud run services describe SERVICE_NAME \
  --project=PROJECT_ID \
  --region=REGION \
  --format='value(status.url)'

Downloading Security Reports

  1. Go to the CI Pipeline workflow run
  2. Scroll to β€œArtifacts” section
  3. Download the vulnerability report

Troubleshooting

Error: Dev environment is claimed by @usernameSolution:
  1. Contact the developer and ask them to release
  2. If unavailable, use Force release option in the Release workflow
Error: Dev environment is not claimedSolution: Run πŸ”’ Claim Dev Environment workflow first, then deploy
Error: Unable to get federated tokenSolution: Verify the Workload Identity pool and provider exist in GCP
Error: Permission denied on secretSolution: Ensure the service account has Secret Manager Accessor role
Error: Could not find service accountSolution: Verify the Cloud Run service account exists in the project
Symptom: Slow builds despite cachingSolution: GitHub Actions cache has a 10GB limit. Old caches are automatically evicted. This is normal behavior.

Security Considerations

Secrets Protection

  • All secrets stored in GCP Secret Manager (encrypted at rest)
  • Workload Identity Federation (no long-lived keys)
  • Minimal IAM permissions (principle of least privilege)
  • Security scanning on every build

Branch Protection

  • main only accepts PRs from develop
  • CI checks must pass before merge
  • Code review recommended

Container Security

  • Multi-stage Docker builds (minimal attack surface)
  • Non-root user in container
  • Vulnerability scanning
  • Secret scanning to prevent credential leaks

Network Security

  • HTTPS only endpoints
  • Cloud Run automatic TLS
  • No exposed ports except 443

Maintenance

Updating Secrets

# Update a secret value in GCP Secret Manager
echo -n "new-value" | gcloud secrets versions add SECRET_NAME \
  --project=PROJECT_ID \
  --data-file=-

# The next deployment will use the new value

Adding New Secrets

1

Create the secret in GCP

echo -n "value" | gcloud secrets create NEW_SECRET \
  --project=PROJECT_ID \
  --data-file=-
2

Update the deployment workflow

Add to the secrets section in the workflow file

Cleaning Up Old Images

# List images in Artifact Registry
gcloud artifacts docker images list \
  REGISTRY_PATH/REPOSITORY

# Delete old images
gcloud artifacts docker images delete \
  REGISTRY_PATH/REPOSITORY/IMAGE@DIGEST

Cost Optimization

Cloud Run is pay-per-use and scales to zero when idle, making it very cost-effective for development environments.
ServicePricing Model
Cloud RunPay-per-use, scales to zero
Artifact RegistryStandard storage pricing
Secret ManagerPer-access operation pricing
GitHub ActionsFree for public repos, usage-based for private

References