- Docker: Multi-stage Dockerfile with security hardening, docker-compose for production and development environments - Environment: Comprehensive .env.example with all config options, lib/config/env.ts for typed environment validation - Logging: Structured JSON logging with request/response middleware - Monitoring: Prometheus metrics endpoint, Grafana dashboard, health checks (liveness/readiness probes) - Security: Security headers, rate limiting, CORS middleware - CI/CD: GitHub Actions workflows for CI, production deploy, and preview deployments - Error tracking: Sentry integration foundation Files created: - Docker: Dockerfile, docker-compose.yml, docker-compose.dev.yml, .dockerignore - Config: lib/config/env.ts, lib/config/index.ts - Logging: lib/logging/logger.ts, lib/logging/middleware.ts - Monitoring: lib/monitoring/sentry.ts, lib/monitoring/metrics.ts, lib/monitoring/health.ts - Security: lib/security/headers.ts, lib/security/rateLimit.ts, lib/security/cors.ts - API: pages/api/health/*, pages/api/metrics.ts - Infra: infra/prometheus/prometheus.yml, infra/grafana/*
139 lines
4.1 KiB
YAML
139 lines
4.1 KiB
YAML
# LocalGreenChain Preview Deployments
|
|
# Agent 4: Production Deployment
|
|
#
|
|
# Creates preview deployments for pull requests
|
|
|
|
name: Preview Deployment
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, synchronize, reopened]
|
|
|
|
concurrency:
|
|
group: preview-${{ github.event.pull_request.number }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
# ==========================================================================
|
|
# Build Preview
|
|
# ==========================================================================
|
|
build:
|
|
name: Build Preview
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@v1
|
|
with:
|
|
bun-version: latest
|
|
|
|
- name: Install dependencies
|
|
run: bun install --frozen-lockfile
|
|
|
|
- name: Build application
|
|
run: bun run build
|
|
env:
|
|
NEXT_TELEMETRY_DISABLED: 1
|
|
NEXT_PUBLIC_API_URL: https://preview-${{ github.event.pull_request.number }}.localgreenchain.dev
|
|
|
|
- name: Upload build artifacts
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: preview-build
|
|
path: |
|
|
.next/
|
|
public/
|
|
package.json
|
|
next.config.js
|
|
retention-days: 7
|
|
|
|
# ==========================================================================
|
|
# Deploy Preview
|
|
# ==========================================================================
|
|
deploy:
|
|
name: Deploy Preview
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
needs: [build]
|
|
permissions:
|
|
pull-requests: write
|
|
|
|
steps:
|
|
- name: Download build artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: preview-build
|
|
|
|
- name: Deploy preview
|
|
id: deploy
|
|
run: |
|
|
# Add your preview deployment logic here
|
|
# Examples: Vercel, Netlify, or custom solution
|
|
|
|
PREVIEW_URL="https://preview-${{ github.event.pull_request.number }}.localgreenchain.dev"
|
|
echo "preview_url=${PREVIEW_URL}" >> $GITHUB_OUTPUT
|
|
echo "Deployed to: ${PREVIEW_URL}"
|
|
|
|
- name: Comment on PR
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const previewUrl = '${{ steps.deploy.outputs.preview_url }}';
|
|
|
|
// Find existing comment
|
|
const comments = await github.rest.issues.listComments({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.issue.number,
|
|
});
|
|
|
|
const botComment = comments.data.find(comment =>
|
|
comment.user.type === 'Bot' &&
|
|
comment.body.includes('Preview Deployment')
|
|
);
|
|
|
|
const body = `## 🚀 Preview Deployment
|
|
|
|
| Status | URL |
|
|
|--------|-----|
|
|
| ✅ Ready | [${previewUrl}](${previewUrl}) |
|
|
|
|
**Commit:** \`${context.sha.substring(0, 7)}\`
|
|
**Updated:** ${new Date().toISOString()}
|
|
|
|
---
|
|
<sub>This preview will be automatically deleted when the PR is closed.</sub>`;
|
|
|
|
if (botComment) {
|
|
await github.rest.issues.updateComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: botComment.id,
|
|
body: body
|
|
});
|
|
} else {
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.issue.number,
|
|
body: body
|
|
});
|
|
}
|
|
|
|
# ==========================================================================
|
|
# Cleanup on PR Close
|
|
# ==========================================================================
|
|
cleanup:
|
|
name: Cleanup Preview
|
|
runs-on: ubuntu-latest
|
|
if: github.event.action == 'closed'
|
|
|
|
steps:
|
|
- name: Delete preview deployment
|
|
run: |
|
|
echo "Cleaning up preview deployment for PR #${{ github.event.pull_request.number }}"
|
|
# Add your cleanup logic here
|