Notes · DevOps · February 2026

Registration Live: From Zero to Cloud Run in One Session

Published February 28, 2026 · Detroit Automation Academy · Historical engineering note — migrated from the retired blog.

We shipped the academy registration system from a broken build to a fully deployed, publicly accessible system in a single engineering session. Here's what that actually looked like.

Starting point: five consecutive build failures

The deploy.sh script existed. The Docker images existed. What didn't exist: a working build.

The first failure was a Go syntax error in backend/main.go — a raw newline embedded inside a string literal:

// Broken
fmt.Printf("Detroit Automation Academy Registration Backend starting on port %s...
", port)

// Fixed
fmt.Printf("...starting on port %s...\n", port)

Go doesn't allow unescaped newlines inside string literals. The fix was one character.

IAM permission cascade

With the backend building, the push to Google Container Registry failed — the Compute service account had the right role but the Cloud Build service account didn't. We granted the missing role to both service accounts and the build cleared.

The missing frontend scaffold

The React frontend had App.tsx and EnrollmentForm.tsx — but no public/index.html, no src/index.tsx, and an invalid tsconfig.json. react-scripts build requires all three.

We also caught a TypeScript error: inside an early-return block, TypeScript narrowed a view-state variable to a literal type, making a later comparison a dead branch (TS2367). Fixed by refactoring to a single return with conditional rendering.

Replacing Terraform with direct deployment

The deploy script ended with terraform init && terraform apply — but Terraform wasn't installed and the infra directory didn't exist. Rather than block, we replaced it with direct gcloud run deploy calls. Both backend and frontend were live in 60 seconds.

Firestore persistence

The original backend stored records in memory — wiped on every cold start. We rewrote the storage handler to use Firestore with a graceful in-memory fallback:

  • Collections are tenant-namespaced
  • If Firestore is unreachable, the handler falls back to thread-safe in-memory storage
  • The /health endpoint reports which storage is active so you can tell at a glance

Historical note: the endpoints from this session are no longer live. This post is preserved as an engineering record of the build.