Agent Development Lifecycle (ADLC) Guide
1. Overview: The Shift from SDLC to ADLC
Section titled β1. Overview: The Shift from SDLC to ADLCβIn traditional software development, human engineers write code over hours or days, submit a few PRs per week, and wait patiently for serialized CI/CD runs.
In an Agent Development Lifecycle (ADLC), autonomous AI coding agents (Claude Code, Devin, Symphony executors, Antigravity) collaborate alongside humans at machine velocity:
- Dozens of PRs are authored, reviewed, and merged per day.
- Iteration cycles drop from days to minutes.
- Traditional deployment bottlenecks and serial queues quickly back up and halt velocity.
This guide outlines the architecture, guardrails, and tools powering the ADLC at ERP-Unlocked.
2. The Bottleneck: The PR #3315 Dilemma
Section titled β2. The Bottleneck: The PR #3315 DilemmaβIn PR #3315 (βfix(deploy): make GCP releases convergent and diagnosableβ), cancel-in-progress in .github/workflows/gcp-deploy.yml was set to false:
concurrency: group: gcp-deploy-${{ github.ref_name }} cancel-in-progress: falseWhy it was disabled
Section titled βWhy it was disabledβDuring a previous staging outage, cancelling deploy workflows in GitHub Actions caused cancellation thrash:
- When GitHub Actions killed a runner mid-flight, underlying Cloud Build jobs or Ansible systemd worker unit migrations were aborted midway through container pulls and unit installs on GCE VMs (
erp-staging-temporal,erp-staging-dagster). - This left staging VMs in half-converged states with mismatched container tags.
- Serializing deployments (
cancel-in-progress: false) guaranteed that every active run converges to clean completion.
The Tradeoff
Section titled βThe TradeoffβWhile serialization ensured stability, it introduced a new failure mode under agent volume:
If 4 agent PRs merge into staging within 20 minutes, each 15-minute deploy queues sequentially. The 4th PR takes 1 hour to reach staging! Furthermore, auto-deploy-main.yml blocks on the exact staging run, stalling production promotions.
3. The Solution: The 4 Pillars of the ADLC
Section titled β3. The Solution: The 4 Pillars of the ADLCββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ Agent Development Lifecycle (ADLC) βββββββββββββββββββββ¬βββββββββββββββββββ¬βββββββββββββββββββ¬ββββββββββββββββ€β 1. Blacksmith β 2. Coalescing β 3. Decoupled β 4. Ephemeral ββ NVMe BuildKit β Deployment Gate β Build vs Deploy β PR Previews ββ 42s Builds β 0s Queue Drain β Pure / Atomic β Safe Sandbox βββββββββββββββββββββ΄βββββββββββββββββββ΄βββββββββββββββββββ΄ββββββββββββββββPillar 1: High-Speed Container Builds with Blacksmith NVMe BuildKit
Section titled βPillar 1: High-Speed Container Builds with Blacksmith NVMe BuildKitβStandard Google Cloud Build runs on E2_HIGHCPU_8 instances with network-bound layer caching (--cache-from) and GCS rsync pnpm store hydration. Warm builds take 12β18 minutes, and cold builds take up to 57 minutes ($0.19β$0.25 per deploy).
Rather than adding a second vendor bill (such as Depot.dev), ERP-Unlocked leverages Blacksmithβs native BuildKit integration (useblacksmith/setup-docker-builder):
- Persistent NVMe Sticky Disks: Caches Docker layers directly on local high-speed SSDs.
- Empirical Benchmark Results (Workflow run
35648129031):- Node.js & TypeScript (
tsc --noEmit): 12s on Blacksmith vs 48s on standard runner (4.0x faster). - Docker Build (
temporal-worker): 42s on Blacksmith vs 159s on standard runner (3.8x faster and 10x faster than Cloud Build). - Compute Cost: $0.0097 / run (~1Β’).
- Node.js & TypeScript (
Using the Composite Action
Section titled βUsing the Composite ActionβA reusable composite action is available at .github/actions/blacksmith-build-push:
- name: Build and push container image uses: ./.github/actions/blacksmith-build-push with: file: apps/temporal-worker/Dockerfile tags: us-east1-docker.pkg.dev/ordermatic-prod/erp-unlocked/temporal-worker:${{ github.sha }} push: truePillar 2: Deployment Coalescing (Safe Queue Draining)
Section titled βPillar 2: Deployment Coalescing (Safe Queue Draining)βRather than abruptly cancelling active builds or blindly running redundant 15-minute builds for superseded commits, .github/workflows/gcp-deploy.yml implements an ADLC Coalescing Gate:
if [ "${{ github.event_name }}" = "push" ]; then git fetch origin "${{ github.ref_name }}" --depth=1 2>/dev/null || true CURRENT_HEAD=$(git rev-parse "origin/${{ github.ref_name }}" 2>/dev/null || echo "") if [ -n "$CURRENT_HEAD" ] && [ "${{ github.sha }}" != "$CURRENT_HEAD" ]; then echo "superseded=true" >> "$GITHUB_OUTPUT" echo "::notice title=Deployment Coalesced::Commit ${{ github.sha }} has been superseded by $CURRENT_HEAD on ${{ github.ref_name }}." exit 0 fifiHow it works in practice:
Section titled βHow it works in practice:β- Commit A merges to
stagingand begins deploying. - While Commit A is running, PR B, PR C, and PR D merge to
staging. - Commit A completes its deployment cleanly (no cancellation thrash).
- Run B starts -> detects
origin/stagingis at Commit D -> skips Cloud Build and completes with statussuccessin 3 seconds. - Run C starts -> detects
origin/stagingis at Commit D -> skips Cloud Build and completes in 3 seconds. - Run D starts -> confirms it matches
origin/staging-> executes deployment! - Total queue drain time drops from 45 minutes down to seconds, with zero risk to VM convergence.
Additionally, if all services are unchanged (e.g. documentation, README, or markdown-only commits), Cloud Build submission is skipped (all_unchanged=true), completing the run in seconds.
Pillar 3: Decoupling Build from Deploy
Section titled βPillar 3: Decoupling Build from DeployβIn the mature ADLC architecture:
- Build Phase (Stateless & Cancellable):
- Builds container images using Depot.dev.
- Pushes
:sha-<commit>images to Google Artifact Registry. - 100% safe to cancel on branch updates (
cancel-in-progress: true).
- Deploy Phase (Atomic Convergence):
- Zero compilation and zero image building.
- Points Cloud Run to the already-built digest (
gcloud run deploy --image=...in ~30s). - Runs Drizzle database migrations with idempotency guards.
- Updates VM systemd unit files atomically (
mv .tmp .service && systemctl restart).
Pillar 4: Ephemeral PR Preview Environments (Agent Sandboxes)
Section titled βPillar 4: Ephemeral PR Preview Environments (Agent Sandboxes)βTo prevent agents from competing for shared staging:
- Agents can spin up isolated Cloud Run preview revisions tagged per PR (
--tag pr-${PR_NUMBER} --no-traffic). - The preview URL (
https://pr-123---erp-webapp-staging-xxx.a.run.app) serves the PRβs exact build without receiving public staging traffic. - Agents run automated UI tests (e.g.
/recorded-ui-test) and API evaluations directly on the preview URL before marking the PR ready for merge.