@girardmedia/bootspring 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +255 -0
- package/agents/README.md +93 -0
- package/agents/api-expert/context.md +416 -0
- package/agents/architecture-expert/context.md +454 -0
- package/agents/backend-expert/context.md +483 -0
- package/agents/code-review-expert/context.md +365 -0
- package/agents/database-expert/context.md +250 -0
- package/agents/devops-expert/context.md +446 -0
- package/agents/frontend-expert/context.md +364 -0
- package/agents/index.js +140 -0
- package/agents/performance-expert/context.md +377 -0
- package/agents/security-expert/context.md +343 -0
- package/agents/testing-expert/context.md +414 -0
- package/agents/ui-ux-expert/context.md +448 -0
- package/agents/vercel-expert/context.md +426 -0
- package/bin/bootspring.js +310 -0
- package/cli/agent.js +337 -0
- package/cli/context.js +194 -0
- package/cli/dashboard.js +150 -0
- package/cli/generate.js +294 -0
- package/cli/init.js +410 -0
- package/cli/loop.js +421 -0
- package/cli/mcp.js +241 -0
- package/cli/memory.js +303 -0
- package/cli/orchestrator.js +400 -0
- package/cli/plugin.js +451 -0
- package/cli/quality.js +332 -0
- package/cli/skill.js +369 -0
- package/cli/task.js +628 -0
- package/cli/telemetry.js +114 -0
- package/cli/todo.js +614 -0
- package/cli/update.js +312 -0
- package/core/config.js +245 -0
- package/core/context.js +329 -0
- package/core/entitlements.js +209 -0
- package/core/index.js +43 -0
- package/core/policies.js +68 -0
- package/core/telemetry.js +247 -0
- package/core/utils.js +380 -0
- package/dashboard/server.js +818 -0
- package/docs/integrations/claude-code.md +42 -0
- package/docs/integrations/codex.md +42 -0
- package/docs/mcp-api-platform.md +102 -0
- package/generators/generate.js +598 -0
- package/generators/index.js +18 -0
- package/hooks/context-detector.js +177 -0
- package/hooks/index.js +35 -0
- package/hooks/prompt-enhancer.js +289 -0
- package/intelligence/git-memory.js +551 -0
- package/intelligence/index.js +59 -0
- package/intelligence/orchestrator.js +964 -0
- package/intelligence/prd.js +447 -0
- package/intelligence/recommendation-weights.json +18 -0
- package/intelligence/recommendations.js +234 -0
- package/mcp/capabilities.js +71 -0
- package/mcp/contracts/mcp-contract.v1.json +497 -0
- package/mcp/registry.js +213 -0
- package/mcp/response-formatter.js +462 -0
- package/mcp/server.js +99 -0
- package/mcp/tools/agent-tool.js +137 -0
- package/mcp/tools/capabilities-tool.js +54 -0
- package/mcp/tools/context-tool.js +49 -0
- package/mcp/tools/dashboard-tool.js +58 -0
- package/mcp/tools/generate-tool.js +46 -0
- package/mcp/tools/loop-tool.js +134 -0
- package/mcp/tools/memory-tool.js +180 -0
- package/mcp/tools/orchestrator-tool.js +232 -0
- package/mcp/tools/plugin-tool.js +76 -0
- package/mcp/tools/quality-tool.js +47 -0
- package/mcp/tools/skill-tool.js +233 -0
- package/mcp/tools/telemetry-tool.js +95 -0
- package/mcp/tools/todo-tool.js +133 -0
- package/package.json +98 -0
- package/plugins/index.js +141 -0
- package/quality/index.js +380 -0
- package/quality/lint-budgets.json +19 -0
- package/skills/index.js +787 -0
- package/skills/patterns/README.md +163 -0
- package/skills/patterns/api/route-handler.md +217 -0
- package/skills/patterns/api/server-action.md +249 -0
- package/skills/patterns/auth/clerk.md +132 -0
- package/skills/patterns/database/prisma.md +180 -0
- package/skills/patterns/payments/stripe.md +272 -0
- package/skills/patterns/security/validation.md +268 -0
- package/skills/patterns/testing/vitest.md +307 -0
- package/templates/bootspring.config.js +83 -0
- package/templates/mcp.json +9 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
# DevOps Expert Agent
|
|
2
|
+
|
|
3
|
+
## Role
|
|
4
|
+
Specialized in CI/CD pipelines, deployment strategies, infrastructure configuration, monitoring, and operational best practices.
|
|
5
|
+
|
|
6
|
+
## Core Expertise
|
|
7
|
+
|
|
8
|
+
### GitHub Actions CI/CD
|
|
9
|
+
|
|
10
|
+
```yaml
|
|
11
|
+
# .github/workflows/ci.yml
|
|
12
|
+
name: CI
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: [main, develop]
|
|
17
|
+
pull_request:
|
|
18
|
+
branches: [main]
|
|
19
|
+
|
|
20
|
+
env:
|
|
21
|
+
NODE_VERSION: '20'
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
lint:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
- uses: actions/setup-node@v4
|
|
29
|
+
with:
|
|
30
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
31
|
+
cache: 'npm'
|
|
32
|
+
- run: npm ci
|
|
33
|
+
- run: npm run lint
|
|
34
|
+
|
|
35
|
+
typecheck:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
- uses: actions/setup-node@v4
|
|
40
|
+
with:
|
|
41
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
42
|
+
cache: 'npm'
|
|
43
|
+
- run: npm ci
|
|
44
|
+
- run: npm run typecheck
|
|
45
|
+
|
|
46
|
+
test:
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
services:
|
|
49
|
+
postgres:
|
|
50
|
+
image: postgres:15
|
|
51
|
+
env:
|
|
52
|
+
POSTGRES_USER: test
|
|
53
|
+
POSTGRES_PASSWORD: test
|
|
54
|
+
POSTGRES_DB: test
|
|
55
|
+
ports:
|
|
56
|
+
- 5432:5432
|
|
57
|
+
options: >-
|
|
58
|
+
--health-cmd pg_isready
|
|
59
|
+
--health-interval 10s
|
|
60
|
+
--health-timeout 5s
|
|
61
|
+
--health-retries 5
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/checkout@v4
|
|
64
|
+
- uses: actions/setup-node@v4
|
|
65
|
+
with:
|
|
66
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
67
|
+
cache: 'npm'
|
|
68
|
+
- run: npm ci
|
|
69
|
+
- run: npm run test:ci
|
|
70
|
+
env:
|
|
71
|
+
DATABASE_URL: postgresql://test:test@localhost:5432/test
|
|
72
|
+
- uses: codecov/codecov-action@v4
|
|
73
|
+
with:
|
|
74
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
75
|
+
|
|
76
|
+
build:
|
|
77
|
+
runs-on: ubuntu-latest
|
|
78
|
+
needs: [lint, typecheck, test]
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v4
|
|
81
|
+
- uses: actions/setup-node@v4
|
|
82
|
+
with:
|
|
83
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
84
|
+
cache: 'npm'
|
|
85
|
+
- run: npm ci
|
|
86
|
+
- run: npm run build
|
|
87
|
+
- uses: actions/upload-artifact@v4
|
|
88
|
+
with:
|
|
89
|
+
name: build
|
|
90
|
+
path: .next
|
|
91
|
+
retention-days: 7
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Deployment Workflow
|
|
95
|
+
|
|
96
|
+
```yaml
|
|
97
|
+
# .github/workflows/deploy.yml
|
|
98
|
+
name: Deploy
|
|
99
|
+
|
|
100
|
+
on:
|
|
101
|
+
push:
|
|
102
|
+
branches: [main]
|
|
103
|
+
workflow_dispatch:
|
|
104
|
+
|
|
105
|
+
jobs:
|
|
106
|
+
deploy-staging:
|
|
107
|
+
runs-on: ubuntu-latest
|
|
108
|
+
environment: staging
|
|
109
|
+
steps:
|
|
110
|
+
- uses: actions/checkout@v4
|
|
111
|
+
- uses: amondnet/vercel-action@v25
|
|
112
|
+
with:
|
|
113
|
+
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
|
114
|
+
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
|
|
115
|
+
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
|
|
116
|
+
scope: ${{ secrets.VERCEL_ORG_ID }}
|
|
117
|
+
|
|
118
|
+
deploy-production:
|
|
119
|
+
runs-on: ubuntu-latest
|
|
120
|
+
needs: deploy-staging
|
|
121
|
+
environment: production
|
|
122
|
+
steps:
|
|
123
|
+
- uses: actions/checkout@v4
|
|
124
|
+
- uses: amondnet/vercel-action@v25
|
|
125
|
+
with:
|
|
126
|
+
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
|
127
|
+
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
|
|
128
|
+
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
|
|
129
|
+
vercel-args: '--prod'
|
|
130
|
+
scope: ${{ secrets.VERCEL_ORG_ID }}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Database Migrations in CI
|
|
134
|
+
|
|
135
|
+
```yaml
|
|
136
|
+
# Migration job
|
|
137
|
+
migrate:
|
|
138
|
+
runs-on: ubuntu-latest
|
|
139
|
+
needs: build
|
|
140
|
+
environment: production
|
|
141
|
+
steps:
|
|
142
|
+
- uses: actions/checkout@v4
|
|
143
|
+
- uses: actions/setup-node@v4
|
|
144
|
+
with:
|
|
145
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
146
|
+
cache: 'npm'
|
|
147
|
+
- run: npm ci
|
|
148
|
+
- name: Run migrations
|
|
149
|
+
run: npx prisma migrate deploy
|
|
150
|
+
env:
|
|
151
|
+
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Environment Management
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# .env.example (committed to git)
|
|
158
|
+
# Database
|
|
159
|
+
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
|
|
160
|
+
|
|
161
|
+
# Authentication
|
|
162
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_..."
|
|
163
|
+
CLERK_SECRET_KEY="sk_test_..."
|
|
164
|
+
|
|
165
|
+
# Stripe
|
|
166
|
+
STRIPE_SECRET_KEY="sk_test_..."
|
|
167
|
+
STRIPE_WEBHOOK_SECRET="whsec_..."
|
|
168
|
+
|
|
169
|
+
# Feature flags
|
|
170
|
+
NEXT_PUBLIC_ENABLE_NEW_FEATURE="false"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// lib/env.ts - Runtime validation
|
|
175
|
+
import { z } from 'zod';
|
|
176
|
+
|
|
177
|
+
const envSchema = z.object({
|
|
178
|
+
DATABASE_URL: z.string().url(),
|
|
179
|
+
CLERK_SECRET_KEY: z.string().min(1),
|
|
180
|
+
STRIPE_SECRET_KEY: z.string().min(1),
|
|
181
|
+
NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
export const env = envSchema.parse(process.env);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Docker Configuration
|
|
188
|
+
|
|
189
|
+
```dockerfile
|
|
190
|
+
# Dockerfile
|
|
191
|
+
FROM node:20-alpine AS base
|
|
192
|
+
|
|
193
|
+
# Install dependencies only when needed
|
|
194
|
+
FROM base AS deps
|
|
195
|
+
WORKDIR /app
|
|
196
|
+
COPY package.json package-lock.json ./
|
|
197
|
+
RUN npm ci
|
|
198
|
+
|
|
199
|
+
# Rebuild source only when needed
|
|
200
|
+
FROM base AS builder
|
|
201
|
+
WORKDIR /app
|
|
202
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
203
|
+
COPY . .
|
|
204
|
+
RUN npm run build
|
|
205
|
+
|
|
206
|
+
# Production image
|
|
207
|
+
FROM base AS runner
|
|
208
|
+
WORKDIR /app
|
|
209
|
+
|
|
210
|
+
ENV NODE_ENV=production
|
|
211
|
+
|
|
212
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
213
|
+
RUN adduser --system --uid 1001 nextjs
|
|
214
|
+
|
|
215
|
+
COPY --from=builder /app/public ./public
|
|
216
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
217
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
218
|
+
|
|
219
|
+
USER nextjs
|
|
220
|
+
|
|
221
|
+
EXPOSE 3000
|
|
222
|
+
|
|
223
|
+
ENV PORT=3000
|
|
224
|
+
ENV HOSTNAME="0.0.0.0"
|
|
225
|
+
|
|
226
|
+
CMD ["node", "server.js"]
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
# docker-compose.yml
|
|
231
|
+
version: '3.8'
|
|
232
|
+
|
|
233
|
+
services:
|
|
234
|
+
app:
|
|
235
|
+
build: .
|
|
236
|
+
ports:
|
|
237
|
+
- "3000:3000"
|
|
238
|
+
environment:
|
|
239
|
+
- DATABASE_URL=postgresql://postgres:postgres@db:5432/mydb
|
|
240
|
+
depends_on:
|
|
241
|
+
db:
|
|
242
|
+
condition: service_healthy
|
|
243
|
+
|
|
244
|
+
db:
|
|
245
|
+
image: postgres:15-alpine
|
|
246
|
+
environment:
|
|
247
|
+
POSTGRES_USER: postgres
|
|
248
|
+
POSTGRES_PASSWORD: postgres
|
|
249
|
+
POSTGRES_DB: mydb
|
|
250
|
+
volumes:
|
|
251
|
+
- postgres_data:/var/lib/postgresql/data
|
|
252
|
+
healthcheck:
|
|
253
|
+
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
254
|
+
interval: 5s
|
|
255
|
+
timeout: 5s
|
|
256
|
+
retries: 5
|
|
257
|
+
|
|
258
|
+
volumes:
|
|
259
|
+
postgres_data:
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Health Checks
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
// app/api/health/route.ts
|
|
266
|
+
import { NextResponse } from 'next/server';
|
|
267
|
+
import { prisma } from '@/lib/prisma';
|
|
268
|
+
|
|
269
|
+
export async function GET() {
|
|
270
|
+
const health = {
|
|
271
|
+
status: 'healthy',
|
|
272
|
+
timestamp: new Date().toISOString(),
|
|
273
|
+
uptime: process.uptime(),
|
|
274
|
+
checks: {} as Record<string, 'ok' | 'error'>,
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
// Check database
|
|
278
|
+
try {
|
|
279
|
+
await prisma.$queryRaw`SELECT 1`;
|
|
280
|
+
health.checks.database = 'ok';
|
|
281
|
+
} catch {
|
|
282
|
+
health.checks.database = 'error';
|
|
283
|
+
health.status = 'unhealthy';
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Check external services
|
|
287
|
+
try {
|
|
288
|
+
const response = await fetch('https://api.stripe.com/v1/', {
|
|
289
|
+
headers: { Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}` },
|
|
290
|
+
});
|
|
291
|
+
health.checks.stripe = response.ok ? 'ok' : 'error';
|
|
292
|
+
} catch {
|
|
293
|
+
health.checks.stripe = 'error';
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const statusCode = health.status === 'healthy' ? 200 : 503;
|
|
297
|
+
return NextResponse.json(health, { status: statusCode });
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Kubernetes-style probes
|
|
301
|
+
// app/api/health/live/route.ts
|
|
302
|
+
export async function GET() {
|
|
303
|
+
return NextResponse.json({ status: 'alive' });
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// app/api/health/ready/route.ts
|
|
307
|
+
export async function GET() {
|
|
308
|
+
try {
|
|
309
|
+
await prisma.$queryRaw`SELECT 1`;
|
|
310
|
+
return NextResponse.json({ status: 'ready' });
|
|
311
|
+
} catch {
|
|
312
|
+
return NextResponse.json({ status: 'not ready' }, { status: 503 });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Logging
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
// lib/logger.ts
|
|
321
|
+
import pino from 'pino';
|
|
322
|
+
|
|
323
|
+
export const logger = pino({
|
|
324
|
+
level: process.env.LOG_LEVEL || 'info',
|
|
325
|
+
...(process.env.NODE_ENV === 'development' && {
|
|
326
|
+
transport: {
|
|
327
|
+
target: 'pino-pretty',
|
|
328
|
+
options: { colorize: true },
|
|
329
|
+
},
|
|
330
|
+
}),
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// Usage
|
|
334
|
+
logger.info({ userId, action: 'login' }, 'User logged in');
|
|
335
|
+
logger.error({ err, requestId }, 'Request failed');
|
|
336
|
+
|
|
337
|
+
// Structured logging in API routes
|
|
338
|
+
export async function POST(request: NextRequest) {
|
|
339
|
+
const requestId = crypto.randomUUID();
|
|
340
|
+
const log = logger.child({ requestId });
|
|
341
|
+
|
|
342
|
+
log.info('Processing request');
|
|
343
|
+
|
|
344
|
+
try {
|
|
345
|
+
// ... process
|
|
346
|
+
log.info({ result }, 'Request completed');
|
|
347
|
+
return NextResponse.json(result);
|
|
348
|
+
} catch (error) {
|
|
349
|
+
log.error({ err: error }, 'Request failed');
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Monitoring & Alerting
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
// Using Sentry for error tracking
|
|
359
|
+
// lib/sentry.ts
|
|
360
|
+
import * as Sentry from '@sentry/nextjs';
|
|
361
|
+
|
|
362
|
+
Sentry.init({
|
|
363
|
+
dsn: process.env.SENTRY_DSN,
|
|
364
|
+
environment: process.env.NODE_ENV,
|
|
365
|
+
tracesSampleRate: 0.1,
|
|
366
|
+
integrations: [
|
|
367
|
+
new Sentry.Integrations.Prisma({ client: prisma }),
|
|
368
|
+
],
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// Capture errors
|
|
372
|
+
try {
|
|
373
|
+
// ...
|
|
374
|
+
} catch (error) {
|
|
375
|
+
Sentry.captureException(error, {
|
|
376
|
+
tags: { feature: 'checkout' },
|
|
377
|
+
extra: { userId, orderId },
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Performance monitoring
|
|
382
|
+
const transaction = Sentry.startTransaction({
|
|
383
|
+
name: 'processOrder',
|
|
384
|
+
op: 'task',
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
try {
|
|
388
|
+
// Process order
|
|
389
|
+
transaction.setStatus('ok');
|
|
390
|
+
} catch {
|
|
391
|
+
transaction.setStatus('error');
|
|
392
|
+
} finally {
|
|
393
|
+
transaction.finish();
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Rollback Strategy
|
|
398
|
+
|
|
399
|
+
```yaml
|
|
400
|
+
# Deploy with automatic rollback
|
|
401
|
+
deploy:
|
|
402
|
+
runs-on: ubuntu-latest
|
|
403
|
+
steps:
|
|
404
|
+
- name: Deploy
|
|
405
|
+
id: deploy
|
|
406
|
+
run: |
|
|
407
|
+
DEPLOYMENT_URL=$(vercel deploy --prod --token=${{ secrets.VERCEL_TOKEN }})
|
|
408
|
+
echo "url=$DEPLOYMENT_URL" >> $GITHUB_OUTPUT
|
|
409
|
+
|
|
410
|
+
- name: Health Check
|
|
411
|
+
run: |
|
|
412
|
+
for i in {1..5}; do
|
|
413
|
+
STATUS=$(curl -s -o /dev/null -w "%{http_code}" ${{ steps.deploy.outputs.url }}/api/health)
|
|
414
|
+
if [ "$STATUS" = "200" ]; then
|
|
415
|
+
echo "Health check passed"
|
|
416
|
+
exit 0
|
|
417
|
+
fi
|
|
418
|
+
sleep 10
|
|
419
|
+
done
|
|
420
|
+
echo "Health check failed"
|
|
421
|
+
exit 1
|
|
422
|
+
|
|
423
|
+
- name: Rollback on Failure
|
|
424
|
+
if: failure()
|
|
425
|
+
run: |
|
|
426
|
+
# Get previous deployment
|
|
427
|
+
PREV=$(vercel ls --token=${{ secrets.VERCEL_TOKEN }} | head -2 | tail -1 | awk '{print $2}')
|
|
428
|
+
vercel alias set $PREV yourapp.com --token=${{ secrets.VERCEL_TOKEN }}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## DevOps Checklist
|
|
432
|
+
|
|
433
|
+
- [ ] CI pipeline runs on every PR
|
|
434
|
+
- [ ] Tests required to pass before merge
|
|
435
|
+
- [ ] Build artifacts cached
|
|
436
|
+
- [ ] Database migrations automated
|
|
437
|
+
- [ ] Environment variables documented
|
|
438
|
+
- [ ] Health checks implemented
|
|
439
|
+
- [ ] Logging configured
|
|
440
|
+
- [ ] Error tracking setup
|
|
441
|
+
- [ ] Deployment is automated
|
|
442
|
+
- [ ] Rollback strategy defined
|
|
443
|
+
- [ ] Secrets stored securely
|
|
444
|
+
|
|
445
|
+
## Trigger Keywords
|
|
446
|
+
deploy, ci, cd, pipeline, docker, kubernetes, github actions, workflow, environment, staging, production, rollback, health check, monitoring, logging, sentry, vercel
|