Skip to content

Instantly share code, notes, and snippets.

@ariefbayu
Created May 7, 2026 05:22
Show Gist options
  • Select an option

  • Save ariefbayu/8bb080d4f2bb8ea69a89bebc83f7f459 to your computer and use it in GitHub Desktop.

Select an option

Save ariefbayu/8bb080d4f2bb8ea69a89bebc83f7f459 to your computer and use it in GitHub Desktop.

StreetEdge Deployment & Online Testing Guide

This guide outlines the steps required to deploy the StreetEdge monorepo to Google Cloud Platform (GCP) and test it in a live environment.

1. Local Build Validation

Before attempting an online deployment, ensure the monorepo is healthy and all packages are correctly linked.

cd streetedge-backend-app
pnpm install
pnpm build

2. GCP Project Infrastructure

Ensure you have a GCP Project created with the following services enabled via the GCP Console:

  • Cloud Run: To host the API (apps/api) and Dashboard (apps/nextjs).
  • Artifact Registry: To store your Docker container images.
  • Secret Manager: To securely store environment variables (API keys, DB URLs).
  • IAM (Identity and Access Management): To manage deployment permissions.

3. CI/CD Configuration (GitHub Actions)

StreetEdge uses GitHub Actions for automated deployment. The skeleton is located at .github/workflows/ci.yml.

A. Set up Workload Identity Federation (OIDC)

This is the secure, keyless method for GitHub to authenticate with GCP. Follow these steps using the gcloud CLI or GCP Console:

1. Create a Workload Identity Pool

This pool will manage the identity relationship between GitHub and GCP.

gcloud iam workload-identity-pools create "github-pool" \
    --project="${PROJECT_ID}" \
    --location="global" \
    --display-name="GitHub Actions Pool"

Example: github-pool

2. Create an OIDC Provider

This defines the connection to GitHub's identity server. Note: The attribute-condition is required to ensure only your repository can access the pool.

gcloud iam workload-identity-pools providers create-oidc "github-provider" \
    --project="${PROJECT_ID}" \
    --location="global" \
    --workload-identity-pool="github-pool" \
    --display-name="GitHub Provider" \
    --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
    --attribute-condition="assertion.repository == '${GITHUB_REPO}'" \
    --issuer-uri="https://token.actions.githubusercontent.com"

Example Provider Path: projects/123456789012/locations/global/workloadIdentityPools/github-pool/providers/github-provider

3. Create a Deployment Service Account

This account will perform the actual deployment actions.

gcloud iam service-accounts create "github-deployer" \
    --project="${PROJECT_ID}" \
    --display-name="GitHub Actions Deployer"

Example: github-deployer@streetedge-prod-123.iam.gserviceaccount.com

4. Grant Required Permissions

Assign roles to the Service Account so it can manage Cloud Run and Artifact Registry.

# Allow deploying to Cloud Run
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:github-deployer@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/run.developer"

# Allow uploading to Artifact Registry
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:github-deployer@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/artifactregistry.writer"

# Allow impersonating the service account (Required for Cloud Run)
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:github-deployer@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/iam.serviceAccountUser"

5. Allow GitHub to Impersonate the Service Account

This connects your specific GitHub repository to the Service Account.

gcloud iam service-accounts add-iam-policy-binding "github-deployer@${PROJECT_ID}.iam.gserviceaccount.com" \
    --project="${PROJECT_ID}" \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/github-pool/attribute.repository/${GITHUB_REPO}"
  • ${PROJECT_NUMBER}: Found in the GCP Project Dashboard.
  • ${GITHUB_REPO}: Format: owner/repository-name (e.g., ariefbayu/streetedge-backend-app). Note: Do not include the full URL or .git suffix.

B. Required GitHub Secrets

Add the following secrets to your GitHub repository settings:

  • GCP_PROJECT_ID: Your unique GCP project ID.
  • GCP_WORKLOAD_IDENTITY_PROVIDER: The full resource name of your OIDC provider.
  • GCP_SERVICE_ACCOUNT: The email of the deployment service account.

4. Dockerization

Each service in the apps/ directory requires a Dockerfile. Because we are using a Turborepo monorepo, we use the turbo prune command to create a subset of the monorepo containing only the files needed for a specific service.

A. General Docker Strategy

  1. Prune: Run npx turbo prune @streetedge/[app-name] --docker to generate an isolated out/ directory.
  2. Build: Use a multi-stage Dockerfile to install dependencies, build the app, and run the production output.
  3. Optimize: Use slim base images (node:22-slim) to reduce costs and deployment speed on Cloud Run.

B. Ingestion API Dockerfile (apps/api/Dockerfile)

This file should live in streetedge-backend-app/apps/api/Dockerfile.

FROM node:22-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

FROM base AS builder
WORKDIR /app
RUN npm install -g turbo
COPY . .
# Generate a pruned version of the monorepo for the API
RUN turbo prune @streetedge/api-hub --docker

FROM base AS installer
WORKDIR /app
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN pnpm install --frozen-lockfile

COPY --from=builder /app/out/full/ .
RUN pnpm turbo run build --filter=@streetedge/api-hub

FROM base AS runner
WORKDIR /app
COPY --from=installer /app/apps/api/dist ./dist
COPY --from=installer /app/node_modules ./node_modules
COPY --from=installer /app/apps/api/package.json ./package.json

EXPOSE 3001
CMD ["node", "dist/index.js"]

C. Dashboard Dockerfile (apps/nextjs/Dockerfile)

This file should live in streetedge-backend-app/apps/nextjs/Dockerfile. Next.js requires the standalone output mode enabled in next.config.js.

# ... (Base, Builder, and Installer stages similar to API above) ...

# Final Runner stage for Next.js
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=installer /app/apps/nextjs/public ./apps/nextjs/public
COPY --from=installer /app/apps/nextjs/.next/standalone ./
COPY --from=installer /app/apps/nextjs/.next/static ./apps/nextjs/.next/static

EXPOSE 3000
CMD ["node", "apps/nextjs/server.js"]

D. Build and Push to Artifact Registry

Run these commands from the root of the monorepo:

# 1. Authenticate Docker with GCP
gcloud auth configure-docker [REGION]-docker.pkg.dev

# 2. Build the image (example for API)
docker build -t [REGION]-docker.pkg.dev/[PROJECT_ID]/[REPO_NAME]/api-hub:latest -f apps/api/Dockerfile .

# 3. Push the image
docker push [REGION]-docker.pkg.dev/[PROJECT_ID]/[REPO_NAME]/api-hub:latest

5. Environment Configuration

Manage your secrets and configuration variables:

  • Local Development: Use .env files within the specific app directories (do not commit these).
  • Production (GCP): Use GCP Secret Manager to inject sensitive values (e.g., DATABASE_URL, FIREBASE_SECRET) into Cloud Run at runtime.

6. Manual Deployment (Alternative)

To test a deployment immediately from your local machine using the gcloud CLI:

# Deploy the Ingestion API
cd streetedge-backend-app/apps/api
gcloud run deploy streetedge-api \
  --source . \
  --platform managed \
  --region YOUR_REGION \
  --allow-unauthenticated

# Deploy the Next.js Dashboard
cd streetedge-backend-app/apps/nextjs
gcloud run deploy streetedge-dashboard \
  --source . \
  --platform managed \
  --region YOUR_REGION \
  --allow-unauthenticated

Assessor: StreetEdge Technical Architect Status: Initial Guide Created (2026-05-06)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment