Agent skill
preview-environments-builder
Creates ephemeral preview deployments for each pull request with automatic deployment, unique URLs, and cleanup on PR close. Use for "preview deployments", "PR environments", "ephemeral environments", or "review apps".
Install this agent skill to your Project
npx add-skill https://github.com/patricio0312rev/skills/tree/main/ci-cd/preview-environments-builder
SKILL.md
Preview Environments Builder
Deploy isolated preview environments for every pull request.
Vercel Preview Deployment
# .github/workflows/preview.yml
name: Preview Deployment
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
deploy-preview:
runs-on: ubuntu-latest
environment:
name: preview-${{ github.event.pull_request.number }}
url: ${{ steps.deploy.outputs.url }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- run: npm run build
- name: Deploy to Vercel
id: deploy
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
scope: ${{ secrets.VERCEL_ORG_ID }}
alias-domains: pr-${{ github.event.pull_request.number }}.myapp.dev
- name: Comment PR
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 deployed!\n\nš **URL:** ${{ steps.deploy.outputs.url }}\n\nCommit: ${context.sha.substring(0, 7)}`
})
Docker-based Preview
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker image
run: |
docker build -t myapp:pr-${{ github.event.pull_request.number }} .
- name: Deploy to Kubernetes
run: |
kubectl create namespace pr-${{ github.event.pull_request.number }} || true
kubectl apply -f k8s/preview.yml \
--namespace pr-${{ github.event.pull_request.number }}
kubectl set image deployment/myapp \
myapp=myapp:pr-${{ github.event.pull_request.number }} \
--namespace pr-${{ github.event.pull_request.number }}
- name: Get preview URL
id: url
run: |
URL=$(kubectl get ingress myapp \
--namespace pr-${{ github.event.pull_request.number }} \
-o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
echo "url=https://pr-${{ github.event.pull_request.number }}.preview.myapp.com" >> $GITHUB_OUTPUT
- name: Comment PR
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 deployed to: ${{ steps.url.outputs.url }}`
})
Cleanup on PR Close
# .github/workflows/cleanup-preview.yml
name: Cleanup Preview
on:
pull_request:
types: [closed]
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Delete Vercel deployment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const deployments = await github.rest.repos.listDeployments({
owner: context.repo.owner,
repo: context.repo.repo,
environment: `preview-${context.issue.number}`
});
for (const deployment of deployments.data) {
await github.rest.repos.createDeploymentStatus({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: deployment.id,
state: 'inactive'
});
await github.rest.repos.deleteDeployment({
owner: context.repo.owner,
repo: context.repo.repo,
deployment_id: deployment.id
});
}
- name: Cleanup Kubernetes namespace
run: |
kubectl delete namespace pr-${{ github.event.pull_request.number }} --ignore-not-found=true
Environment Naming
# Consistent naming pattern
environment:
name: preview-pr-${{ github.event.pull_request.number }}
url: https://pr-${{ github.event.pull_request.number }}.preview.myapp.com
Database Seeding
- name: Setup preview database
run: |
# Create database
psql -c "CREATE DATABASE preview_pr_${{ github.event.pull_request.number }};"
# Seed with test data
npm run db:seed -- --database=preview_pr_${{ github.event.pull_request.number }}
env:
DATABASE_URL: ${{ secrets.PREVIEW_DB_URL }}
Best Practices
- Unique URLs: pr-{number}.preview.domain.com
- Auto cleanup: Delete on PR close
- Comment on PR: Link to preview
- Environment protection: Require approval
- Resource limits: Prevent abuse
- TTL: Auto-delete after 7 days
- Secrets management: Use preview-specific secrets
Output Checklist
- Preview deployment workflow
- Unique URL generation
- PR comment with link
- Cleanup workflow on close
- Environment naming strategy
- Database seeding (if needed)
- Resource limits configured
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
rate-limiting-abuse-protection
Implements rate limiting and abuse prevention with per-route policies, IP/user-based limits, sliding windows, safe error responses, and observability. Use when adding "rate limiting", "API protection", "abuse prevention", or "DDoS protection".
rbac-permissions-builder
Implements role-based access control with permission matrix, route guards, policy functions, and UI permission hints. Provides middleware/guards, helper utilities, test suggestions, and permission checking patterns. Use when building "RBAC", "permissions", "access control", or "authorization".
websocket-realtime-builder
Implements real-time features using WebSockets with Socket.io, rooms, authentication, and reconnection handling. Use when users request "real-time updates", "WebSocket", "Socket.io", "live chat", or "push notifications".
webhook-receiver-hardener
Secures webhook receivers with signature verification, retry handling, deduplication, idempotency keys, and error responses. Provides verification code, dedupe storage strategy, runbook for incidents. Use when implementing "webhooks", "webhook security", "event receivers", or "third-party integrations".
auth-module-builder
Implements secure authentication patterns including login/registration, session management, JWT tokens, password hashing, cookie settings, and CSRF protection. Provides auth routes, middleware, security configurations, and threat model documentation. Use when building "authentication", "login system", "JWT auth", or "session management".
rest-to-graphql-migrator
Migrates REST APIs to GraphQL incrementally with schema stitching, REST datasources, and gradual endpoint migration. Use when users request "migrate to GraphQL", "REST to GraphQL", "GraphQL wrapper", or "API modernization".
Didn't find tool you were looking for?