google-agents-cli-scaffold
Project scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.
deployment-automation
Expert DevOps automation consultant for building production-grade CI/CD deployment pipelines using Vercel, GitHub Actions, and Railway. Implements build/test/preview/production workflows, automated rollbacks, canary deployments, blue-green strategies, environment promotion, secrets management, he...
Full skill instructions
This skill provides comprehensive deployment automation patterns for modern web applications using industry-leading platforms: Vercel (frontend), Railway (backend), and GitHub Actions (CI/CD orchestration).
Core Capabilities:
Updated for 2025: This guide reflects the latest platform features, security best practices, and deployment patterns validated by production teams.
/health endpoints that verify all dependencies┌─────────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐
│ Commit │ -> │ Test │ -> │ Deploy │ -> │ Monitor │
│ & Push │ │ & Lint │ │ Preview │ │ Health │
└─────────────┘ └──────────┘ └─────────────┘ └──────────┘
│
v
┌─────────────┐
│ Deploy │
│ Production │
│ (Canary) │
└─────────────┘
│
v
┌─────────────┐
│ Promote │
│ or Rollback│
└─────────────┘
| Metric | Target | Action if Exceeded |
|---|---|---|
| Build Time | < 5 minutes | Investigate caching, optimize dependencies |
| Deployment Time | < 2 minutes | Check network, reduce asset size |
| Health Check Response | < 500ms | Optimize endpoint, check database |
| P95 Latency | < 200ms | Add caching, optimize queries |
| Error Rate | < 0.1% | Automatic rollback + investigation |
Choose Your Platform:
| Use Case | Platform | Why |
|---|---|---|
| Next.js, React, Vue, Static Sites | Vercel | Zero-config, edge network, instant previews |
| Node.js, Python, Go backends | Railway | Simple setup, good DX, affordable |
| Custom workflows, monorepos | GitHub Actions | Full control, free for public repos |
When to Use: Frontend applications, Next.js, static sites, serverless functions
Key Features:
Standard Workflow with Testing (2025 Pattern):
# .github/workflows/vercel-preview.yml
name: Vercel Preview Deployment
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
# Step 1: Run tests first
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
- name: Run type checking
run: npm run type-check
- name: Run tests
run: npm test
# Step 2: Deploy only if tests pass
deploy-preview:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Pull Vercel Environment
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy to Vercel
id: deploy
run: |
URL=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
echo "preview-url=$URL" >> $GITHUB_OUTPUT
- name: Comment PR with Preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '🚀 Preview deployment ready!\n\n**URL:** ${{ steps.deploy.outputs.preview-url }}'
})
# .github/workflows/vercel-production.yml
name: Vercel Production Deployment
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
on:
push:
branches:
- main
jobs:
# Step 1: Full test suite
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run full test suite
run: |
npm run lint
npm run type-check
npm test
npm run test:e2e # End-to-end tests
# Step 2: Deploy to production
deploy-production:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vercel CLI
run: npm install --global vercel@latest
- name: Pull Vercel Environment
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
- name: Build Project
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy to Vercel
id: deploy
run: |
URL=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }})
echo "production-url=$URL" >> $GITHUB_OUTPUT
- name: Post-deployment smoke tests
run: |
chmod +x ./scripts/smoke-test.sh
./scripts/smoke-test.sh ${{ steps.deploy.outputs.production-url }}
- name: Notify on success
if: success()
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-H 'Content-Type: application/json' \
-d '{"text":"✅ Production deployment successful!\n**URL:** ${{ steps.deploy.outputs.production-url }}"}'
- name: Notify on failure
if: failure()
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-H 'Content-Type: application/json' \
-d '{"text":"❌ Production deployment failed! Check GitHub Actions logs."}'
Required Secrets:
VERCEL_TOKEN: Create at vercel.com/account/tokensVERCEL_ORG_ID: Found in .vercel/project.json after running vercel linkVERCEL_PROJECT_ID: Found in .vercel/project.jsonBest Practices:
See references/VERCEL_ADVANCED.md for advanced patterns, caching strategies, and troubleshooting.
When to Use: Backend services, databases, Node.js/Python/Go apps, APIs
Key Features:
Standard Workflow:
# .github/workflows/railway-deploy.yml
name: Deploy to Railway
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
container: ghcr.io/railwayapp/cli:latest
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
SERVICE_ID: ${{ secrets.RAILWAY_SERVICE_ID }}
steps:
- uses: actions/checkout@v3
- name: Deploy to Railway
run: railway up --service=${{ env.SERVICE_ID }}
Alternative: Custom Docker Workflow
# .github/workflows/railway-docker.yml
name: Railway Docker Deploy
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install Railway CLI
run: npm install -g @railway/cli
- name: Link Railway Project
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: |
railway link --project=${{ secrets.RAILWAY_PROJECT_ID }} \
--environment=${{ secrets.RAILWAY_ENVIRONMENT_ID }}
- name: Deploy
run: railway redeploy --yes
Required Secrets:
RAILWAY_TOKEN: Create at railway.app/account/tokensRAILWAY_SERVICE_ID: Found in service settingsRAILWAY_PROJECT_ID: Found in project settingsRAILWAY_ENVIRONMENT_ID: Found in environment settings (production/staging)Best Practices:
See references/RAILWAY_ADVANCED.md for monorepo deployments, database migrations, and optimization strategies.
What is Canary Deployment?
Gradually roll out changes to a small subset of users before full production release. This minimizes blast radius if issues occur.
When to Use:
Implementation Pattern:
Stage 1: Deploy Canary (10% traffic)
# .github/workflows/canary-deploy.yml
name: Canary Deployment
on:
push:
branches:
- main
jobs:
deploy-canary:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# Deploy to canary environment (separate service or slot)
- name: Deploy Canary Version
run: |
# Deploy to Railway with canary tag
railway up --service=${{ secrets.CANARY_SERVICE_ID }} \
--environment=production
# Route 10% traffic to canary
- name: Configure Traffic Split
run: |
# Use your platform's traffic management API
# Vercel: Update deployment alias with traffic routing
# Railway: Use load balancer configuration
echo "Routing 10% traffic to canary"
# Wait and monitor for 15 minutes
- name: Monitor Canary Health
run: |
sleep 900 # 15 minutes
# Run health checks (see scripts/health-check.sh)
./scripts/health-check.sh ${{ secrets.CANARY_URL }}
Stage 2: Promote or Rollback
promote-or-rollback:
needs: deploy-canary
runs-on: ubuntu-latest
steps:
- name: Check Canary Metrics
id: metrics
run: |
# Fetch error rate, latency, success rate from monitoring
# Example: Query Prometheus/Datadog/custom metrics endpoint
ERROR_RATE=$(curl -s ${{ secrets.METRICS_API }}/error-rate)
if [ "$ERROR_RATE" -lt "1" ]; then
echo "status=success" >> $GITHUB_OUTPUT
else
echo "status=failure" >> $GITHUB_OUTPUT
fi
- name: Promote Canary
if: steps.metrics.outputs.status == 'success'
run: |
# Route 100% traffic to new version
railway up --service=${{ secrets.PRODUCTION_SERVICE_ID }}
echo "✅ Canary promoted to production"
- name: Rollback Canary
if: steps.metrics.outputs.status == 'failure'
run: |
# Route all traffic back to stable version
railway rollback --service=${{ secrets.CANARY_SERVICE_ID }}
echo "⚠️ Canary rolled back due to high error rate"
Progressive Rollout Schedule:
Rollback Triggers:
See references/CANARY_DEPLOYMENTS.md for detailed canary strategies, A/B testing, and feature flags.
Railway Rollback:
# Rollback to previous deployment
railway rollback --service=my-service
# Rollback to specific deployment ID
railway rollback --service=my-service --deployment=dep_abc123
Vercel Rollback:
# List recent deployments
vercel ls
# Promote previous deployment to production
vercel promote [deployment-url] --prod
GitHub Actions Rollback Workflow:
# .github/workflows/rollback.yml
name: Emergency Rollback
on:
workflow_dispatch:
inputs:
target_version:
description: 'Version to rollback to'
required: true
type: string
jobs:
rollback:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ inputs.target_version }}
- name: Rollback Vercel
run: |
vercel promote [previous-deployment-url] --prod \
--token=${{ secrets.VERCEL_TOKEN }}
- name: Rollback Railway
run: railway rollback --service=${{ secrets.SERVICE_ID }}
- name: Notify Team
run: |
# Send Slack/Discord notification
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-d '{"text":"🚨 Rollback to version ${{ inputs.target_version }} completed"}'
git revert or git reset to stable commitSee references/ROLLBACK_STRATEGIES.md for advanced rollback patterns and disaster recovery.
GitHub Secrets (for CI/CD):
Vercel Environment Variables:
# Via CLI
vercel env add VARIABLE_NAME production
vercel env add VARIABLE_NAME preview
# Via Dashboard
Project Settings → Environment Variables → Add
Railway Environment Variables:
# Via CLI
railway variables set VARIABLE_NAME=value
# Via Dashboard
Service Settings → Variables → Add Variable
Development:
NODE_ENV=development
API_URL=http://localhost:3000
DATABASE_URL=postgresql://localhost:5432/dev_db
DEBUG=true
Preview/Staging:
NODE_ENV=staging
API_URL=https://api-staging.example.com
DATABASE_URL=postgresql://staging-db.railway.app/db
DEBUG=true
SENTRY_ENVIRONMENT=staging
Production:
NODE_ENV=production
API_URL=https://api.example.com
DATABASE_URL=postgresql://prod-db.railway.app/db
DEBUG=false
SENTRY_ENVIRONMENT=production
Security Best Practices:
Implementation Example (Express.js):
// /health endpoint
app.get('/health', (req, res) => {
const health = {
uptime: process.uptime(),
status: 'UP',
timestamp: Date.now(),
checks: {
database: checkDatabaseConnection(),
redis: checkRedisConnection(),
api: checkExternalAPI()
}
};
const isHealthy = Object.values(health.checks).every(check => check === true);
res.status(isHealthy ? 200 : 503).json(health);
});
Use scripts/smoke-test.sh:
#!/bin/bash
# Health check script for post-deployment verification
DEPLOYMENT_URL=$1
MAX_RETRIES=10
RETRY_DELAY=5
for i in $(seq 1 $MAX_RETRIES); do
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" $DEPLOYMENT_URL/health)
if [ "$HTTP_CODE" -eq 200 ]; then
echo "✅ Health check passed (attempt $i/$MAX_RETRIES)"
exit 0
else
echo "⚠️ Health check failed with status $HTTP_CODE (attempt $i/$MAX_RETRIES)"
sleep $RETRY_DELAY
fi
done
echo "❌ Health check failed after $MAX_RETRIES attempts"
exit 1
Integration in Workflow:
- name: Smoke Test Deployment
run: |
chmod +x ./scripts/smoke-test.sh
./scripts/smoke-test.sh https://my-app.vercel.app
Frontend (Vercel):
Backend (Railway):
Railway Health Check:
# Railway service configuration
healthCheckPath: /health
healthCheckTimeout: 30
restartPolicyMaxRetries: 3
Uptime Monitoring:
Full Example: Frontend + Backend
# .github/workflows/deploy-full-stack.yml
name: Deploy Full Stack Application
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened]
jobs:
# Step 1: Lint and Test
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Run Linter
run: npm run lint
- name: Run Tests
run: npm test
# Step 2: Deploy Frontend to Vercel
deploy-frontend:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- name: Deploy to Vercel
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
run: |
npm i -g vercel
vercel pull --yes --environment=production --token=$VERCEL_TOKEN
vercel build --prod --token=$VERCEL_TOKEN
vercel deploy --prebuilt --prod --token=$VERCEL_TOKEN
# Step 3: Deploy Backend to Railway
deploy-backend:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
container: ghcr.io/railwayapp/cli:latest
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
SERVICE_ID: ${{ secrets.RAILWAY_SERVICE_ID }}
steps:
- uses: actions/checkout@v3
- run: railway up --service=$SERVICE_ID
# Step 4: Post-Deployment Verification
verify-deployment:
needs: [deploy-frontend, deploy-backend]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Health Check Frontend
run: |
curl -f ${{ secrets.FRONTEND_URL }}/api/health || exit 1
- name: Health Check Backend
run: |
curl -f ${{ secrets.BACKEND_URL }}/health || exit 1
- name: Notify Success
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-d '{"text":"✅ Deployment successful: Frontend + Backend deployed"}'
vercel login # Authenticate
vercel link # Link to project
vercel # Deploy preview
vercel --prod # Deploy production
vercel ls # List deployments
vercel inspect [url] # Inspect deployment
vercel logs [url] # View logs
vercel env ls # List environment variables
vercel domains add example.com # Add custom domain
railway login # Authenticate
railway init # Initialize project
railway up # Deploy service
railway status # Check status
railway logs # View logs
railway run [command] # Run command
railway variables # List variables
railway open # Open in browser
railway rollback # Rollback deployment
gh workflow list # List workflows
gh workflow run [name] # Trigger workflow
gh run list # List workflow runs
gh run view [id] # View run details
gh secret set [name] # Set secret
Vercel: Build Failed
node -v)vercel build --forceRailway: Service Not Starting
railway logsGitHub Actions: Workflow Failed
Deployment Stuck
References (detailed documentation):
references/VERCEL_ADVANCED.md - Advanced Vercel patterns, caching, optimizationreferences/RAILWAY_ADVANCED.md - Railway monorepos, databases, Docker optimizationreferences/CANARY_DEPLOYMENTS.md - Progressive delivery, A/B testing, feature flagsreferences/ROLLBACK_STRATEGIES.md - Disaster recovery, incident response proceduresreferences/SECURITY_BEST_PRACTICES.md - Comprehensive security guide for CI/CD pipelines (NEW 2025)Scripts (automation tools):
scripts/smoke-test.sh - Post-deployment health verificationscripts/setup-secrets.sh - Automate GitHub secrets configurationscripts/health-check.sh - Comprehensive health check script for production monitoring✅ DO:
❌ DON'T:
.github/workflows/ directoryThis skill provides production-ready deployment automation patterns. Adapt workflows to your specific needs and always test thoroughly in non-production environments first.
Project scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.
Set up tracing, logging, and monitoring for deployed ADK agents across Cloud Trace, BigQuery, and third-party platforms.
Enterprise Azure infrastructure architect generating Bicep or Terraform from workload descriptions.
Plan and configure production-ready Azure Kubernetes Service clusters with Day-0 and Day-1 best practices.
Raw mechanical interfaces fusing Swiss typographic print with military terminal aesthetics. Rigid grids, extreme type scale contrast, utilitarian color, analog degradation effects. For data-heavy dashboards, portfolios, or editorial sites that need to feel like declassified blueprints.
Web search, scraping, extraction, crawling, and monitoring via ScrapeGraph AI CLI.
Skill for working with Firebase Hosting (Classic). Use this when you want to deploy static web apps, Single Page Apps (SPAs), or simple microservices. Do NOT use for Firebase App Hosting.
Deploy and manage web apps with Firebase App Hosting. Use this skill when deploying Next.js/Angular apps with backends.
Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".
Build SEO-optimized pages at scale using templates, data, and proven playbook patterns.
Design and build isolated, reusable Convex backend components with clear boundaries and app-facing wrappers.
Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".
Opus.ai: Revolutionize Your Web Experience
Build a no-code AI app in minutes.
An IDE for code migration from legacy to modern frameworks through coding agents.
Automate CGI animation in live-action scenes
Branded artistic QR-code concepts
Launch a website in seconds with AI.
Streamline Your Coding Experience with AI Code Helper
Convert any screenshot or design to clean code.