@valentia-ai-skills/framework 1.0.4 → 1.0.6
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/bin/cli.js +90 -18
- package/package.json +2 -2
- package/skills/global/api-design/tests/test-prompts.md +0 -25
- package/skills/global/code-standards/tests/test-prompts.md +0 -26
- package/skills/global/deployment/SKILL.md +0 -240
- package/skills/global/deployment/tests/test-prompts.md +0 -27
- package/skills/global/documentation/SKILL.md +0 -298
- package/skills/global/documentation/tests/test-prompts.md +0 -26
- package/skills/global/git-workflow/SKILL.md +0 -177
- package/skills/global/git-workflow/tests/test-prompts.md +0 -11
- package/skills/global/security-baseline/SKILL.md +0 -239
- package/skills/global/security-baseline/tests/test-prompts.md +0 -23
- package/skills/global/testing-standards/SKILL.md +0 -257
- package/skills/global/testing-standards/tests/test-prompts.md +0 -25
- package/skills/onboarding/SKILL.md +0 -110
- package/skills/stack/devops/SKILL.md +0 -220
- package/skills/stack/devops/tests/test-prompts.md +0 -29
- package/skills/stack/node-backend/SKILL.md +0 -304
- package/skills/stack/node-backend/tests/test-prompts.md +0 -27
- package/skills/stack/python-backend/SKILL.md +0 -304
- package/skills/stack/python-backend/tests/test-prompts.md +0 -27
- package/skills/stack/react/SKILL.md +0 -251
- package/skills/stack/react/tests/test-prompts.md +0 -26
- package/skills/stack/react-native/SKILL.md +0 -255
- package/skills/stack/react-native/tests/test-prompts.md +0 -26
package/bin/cli.js
CHANGED
|
@@ -214,6 +214,71 @@ function getLocalSkills() {
|
|
|
214
214
|
return skills;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
// ── Email + OTP Verification ──
|
|
218
|
+
|
|
219
|
+
async function requestOtpForEmail(emailInput) {
|
|
220
|
+
let email = emailInput;
|
|
221
|
+
let attempts = 0;
|
|
222
|
+
|
|
223
|
+
while (attempts < 2) {
|
|
224
|
+
if (!email || !email.includes("@")) {
|
|
225
|
+
console.log(c("red", "Invalid email."));
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
console.log(c("dim", "\nVerifying your email..."));
|
|
230
|
+
|
|
231
|
+
const response = await fetchJSON(SUPABASE_FUNCTION_URL, { email, action: "request_otp" });
|
|
232
|
+
|
|
233
|
+
if (response.error === "not_found") {
|
|
234
|
+
attempts++;
|
|
235
|
+
if (attempts >= 2) {
|
|
236
|
+
console.log(c("red", "\n✗ Email not recognized. Access denied."));
|
|
237
|
+
console.log(c("dim", " Contact your Framework Admin to be added to the system.\n"));
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
console.log(c("yellow", "\n⚠ Email not found. Please check and try again.\n"));
|
|
241
|
+
email = await ask(`${c("bold", "Enter your work email:")} `);
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (response.error) {
|
|
246
|
+
throw new Error(response.error);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// OTP sent successfully
|
|
250
|
+
console.log(c("green", `\n✓ Found: ${response.user_name}`));
|
|
251
|
+
console.log(c("dim", ` A verification code has been sent to ${email}\n`));
|
|
252
|
+
|
|
253
|
+
return email;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async function verifyOtp(email) {
|
|
258
|
+
const otp = await ask(`${c("bold", "Enter the 6-digit code:")} `);
|
|
259
|
+
|
|
260
|
+
if (!otp || otp.length < 4) {
|
|
261
|
+
console.log(c("red", "Invalid code."));
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
console.log(c("dim", "\nVerifying code..."));
|
|
266
|
+
|
|
267
|
+
const response = await fetchJSON(SUPABASE_FUNCTION_URL, { email, otp, action: "verify_otp" });
|
|
268
|
+
|
|
269
|
+
if (response.error === "invalid_otp") {
|
|
270
|
+
console.log(c("red", "\n✗ Invalid verification code. Please run setup again."));
|
|
271
|
+
process.exit(1);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (response.error) {
|
|
275
|
+
throw new Error(response.error);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
console.log(c("green", "✓ Verified!\n"));
|
|
279
|
+
return response;
|
|
280
|
+
}
|
|
281
|
+
|
|
217
282
|
// ── Commands ──
|
|
218
283
|
|
|
219
284
|
async function cmdSetup() {
|
|
@@ -229,37 +294,39 @@ async function cmdSetup() {
|
|
|
229
294
|
}
|
|
230
295
|
|
|
231
296
|
// 2. Ask for email
|
|
232
|
-
|
|
233
|
-
if (!email || !email.includes("@")) {
|
|
234
|
-
console.log(c("red", "Invalid email. Please try again."));
|
|
235
|
-
process.exit(1);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// 3. Lookup team from Supabase
|
|
239
|
-
console.log(c("dim", "\nLooking up your team..."));
|
|
297
|
+
let email = await ask(`${c("bold", "Enter your work email:")} `);
|
|
240
298
|
|
|
241
|
-
let response;
|
|
242
299
|
let skills;
|
|
243
300
|
let teamName = null;
|
|
244
301
|
let useRemote = true;
|
|
245
302
|
|
|
246
303
|
try {
|
|
247
|
-
|
|
304
|
+
// 3. Request OTP (with 1 retry for wrong email)
|
|
305
|
+
email = await requestOtpForEmail(email);
|
|
306
|
+
|
|
307
|
+
// 4. Verify OTP and get skills
|
|
308
|
+
const response = await verifyOtp(email);
|
|
248
309
|
|
|
249
310
|
if (response.team) {
|
|
250
311
|
teamName = response.team.name;
|
|
251
|
-
console.log(c("green",
|
|
312
|
+
console.log(c("green", `✓ Team: ${teamName}`));
|
|
252
313
|
if (response.user) {
|
|
253
314
|
console.log(c("dim", ` Welcome, ${response.user.name} (${response.user.role})`));
|
|
254
315
|
}
|
|
255
316
|
if (response.team.stack_tags?.length) {
|
|
256
317
|
console.log(c("dim", ` Stack: ${response.team.stack_tags.join(", ")}`));
|
|
257
318
|
}
|
|
258
|
-
} else {
|
|
259
|
-
console.log(c("yellow",
|
|
319
|
+
} else if (response.message) {
|
|
320
|
+
console.log(c("yellow", `⚠ ${response.message}`));
|
|
260
321
|
}
|
|
261
322
|
|
|
262
323
|
skills = response.skills || [];
|
|
324
|
+
|
|
325
|
+
if (skills.length === 0) {
|
|
326
|
+
console.log(c("yellow", "\n⚠ No skills are enabled for your team. Contact your Team Lead."));
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
|
|
263
330
|
console.log(` ${c("bold", skills.length)} skill(s) to install\n`);
|
|
264
331
|
|
|
265
332
|
} catch (err) {
|
|
@@ -275,7 +342,7 @@ async function cmdSetup() {
|
|
|
275
342
|
process.exit(1);
|
|
276
343
|
}
|
|
277
344
|
|
|
278
|
-
//
|
|
345
|
+
// 5. Install for each tool
|
|
279
346
|
for (const toolKey of tools) {
|
|
280
347
|
const tool = TOOL_CONFIGS[toolKey];
|
|
281
348
|
if (!tool) continue;
|
|
@@ -290,7 +357,7 @@ async function cmdSetup() {
|
|
|
290
357
|
console.log("");
|
|
291
358
|
}
|
|
292
359
|
|
|
293
|
-
//
|
|
360
|
+
// 6. Save config
|
|
294
361
|
const config = {
|
|
295
362
|
version: require(path.join(__dirname, "..", "package.json")).version,
|
|
296
363
|
email,
|
|
@@ -302,7 +369,7 @@ async function cmdSetup() {
|
|
|
302
369
|
};
|
|
303
370
|
saveConfig(config);
|
|
304
371
|
|
|
305
|
-
//
|
|
372
|
+
// 7. Summary
|
|
306
373
|
console.log(c("blue", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
307
374
|
console.log(c("green", "✅ Setup complete!"));
|
|
308
375
|
console.log(` ${skills.length} skills installed for ${tools.length} tool(s)`);
|
|
@@ -320,13 +387,18 @@ async function cmdUpdate() {
|
|
|
320
387
|
process.exit(1);
|
|
321
388
|
}
|
|
322
389
|
|
|
323
|
-
|
|
390
|
+
const email = config.email;
|
|
391
|
+
console.log(c("dim", `Updating for ${email}...`));
|
|
324
392
|
|
|
325
393
|
let skills;
|
|
326
394
|
let teamName = config.team;
|
|
327
395
|
|
|
328
396
|
try {
|
|
329
|
-
|
|
397
|
+
// Request OTP for the saved email
|
|
398
|
+
await requestOtpForEmail(email);
|
|
399
|
+
|
|
400
|
+
// Verify OTP
|
|
401
|
+
const response = await verifyOtp(email);
|
|
330
402
|
skills = response.skills || [];
|
|
331
403
|
teamName = response.team?.name || config.team;
|
|
332
404
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@valentia-ai-skills/framework",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "AI development skills framework
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "AI development skills framework ÃÂÃÂÃÂÃÂÃÂÃÂÃÂâÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂÃÂàcentralized coding standards, security patterns, and SOPs for AI-assisted development. Works with Claude Code, Cursor, Copilot, Windsurf, and any AI coding tool.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-skills",
|
|
7
7
|
"claude-code",
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
## Test 1: CRUD Endpoint Design
|
|
2
|
-
**Prompt**: "Design the REST API endpoints for a blog post system with posts, comments, and tags"
|
|
3
|
-
**Expected**:
|
|
4
|
-
- Plural nouns: /posts, /comments, /tags
|
|
5
|
-
- Proper nesting: /posts/:id/comments (max 2 levels)
|
|
6
|
-
- All CRUD methods with correct status codes
|
|
7
|
-
- Response envelope with data/error pattern
|
|
8
|
-
- Pagination on list endpoints
|
|
9
|
-
|
|
10
|
-
## Test 2: Error Handling
|
|
11
|
-
**Prompt**: "Write the error handling middleware for an Express API that returns consistent error responses"
|
|
12
|
-
**Expected**:
|
|
13
|
-
- Error envelope: { error: { code, message, details } }
|
|
14
|
-
- Correct status codes (400 for validation, 401 for auth, 404 for not found)
|
|
15
|
-
- No stack traces or internal details exposed
|
|
16
|
-
- Proper differentiation between 401 and 403
|
|
17
|
-
|
|
18
|
-
## Test 3: Complex Query Endpoint
|
|
19
|
-
**Prompt**: "Build a product search endpoint with filtering by price range, category, and rating, with sorting and pagination"
|
|
20
|
-
**Expected**:
|
|
21
|
-
- Query params: minPrice, maxPrice, category, minRating
|
|
22
|
-
- Sort format: sort=price:asc
|
|
23
|
-
- Offset pagination with page, pageSize, totalItems
|
|
24
|
-
- Default and max page sizes enforced
|
|
25
|
-
- Input validation on all query params
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
## Test 1: New Function Creation
|
|
2
|
-
**Prompt**: "Write a function that fetches a user from the database by email, checks if they're active, and returns their profile with recent orders"
|
|
3
|
-
**Expected**:
|
|
4
|
-
- Function named descriptively (e.g., `getUserProfileWithOrders`)
|
|
5
|
-
- Parameters use camelCase
|
|
6
|
-
- Boolean check uses `isActive` pattern
|
|
7
|
-
- Error handling with context
|
|
8
|
-
- Under 40 lines, early returns
|
|
9
|
-
|
|
10
|
-
## Test 2: Refactoring Messy Code
|
|
11
|
-
**Prompt**: "Refactor this: `function do_stuff(a, b, c, d, e, f) { try { if (a) { if (b) { if (c) { return process(d, e, f); } } } } catch(e) {} }`"
|
|
12
|
-
**Expected**:
|
|
13
|
-
- Renamed to descriptive name
|
|
14
|
-
- Parameters grouped into options object (>4 params)
|
|
15
|
-
- Nesting reduced via early returns
|
|
16
|
-
- Error handling added (not swallowed)
|
|
17
|
-
- camelCase naming
|
|
18
|
-
|
|
19
|
-
## Test 3: File Organization
|
|
20
|
-
**Prompt**: "Create a user registration module with validation, database save, email notification, and audit logging"
|
|
21
|
-
**Expected**:
|
|
22
|
-
- Split into multiple files (not one 500-line file)
|
|
23
|
-
- kebab-case file names
|
|
24
|
-
- Proper import ordering
|
|
25
|
-
- Named exports
|
|
26
|
-
- Each file has single responsibility
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: deployment
|
|
3
|
-
description: >
|
|
4
|
-
Organization-wide deployment standards for CI/CD pipelines, environment
|
|
5
|
-
management, release processes, and rollback procedures. Use this skill
|
|
6
|
-
whenever writing, reviewing, or discussing deployment configurations,
|
|
7
|
-
CI/CD pipelines, Docker files, environment promotion, feature flags,
|
|
8
|
-
release management, or rollback strategies. Triggers on: "deploy",
|
|
9
|
-
"deployment", "CI/CD", "pipeline", "GitHub Actions", "Docker", "Dockerfile",
|
|
10
|
-
"container", "Kubernetes", "k8s", "helm", "terraform", "release",
|
|
11
|
-
"rollback", "staging", "production", "environment", "feature flag",
|
|
12
|
-
"blue-green", "canary", "rolling update". Applies to all teams.
|
|
13
|
-
version: "1.0.0"
|
|
14
|
-
scope: global
|
|
15
|
-
author: Framework Admin
|
|
16
|
-
last_reviewed: 2026-03-19
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
# Deployment Standards
|
|
20
|
-
|
|
21
|
-
## Overview
|
|
22
|
-
|
|
23
|
-
Consistent deployment practices ensure reliable, safe releases across all
|
|
24
|
-
services. These standards cover CI/CD pipelines, environment management,
|
|
25
|
-
containerization, and rollback procedures.
|
|
26
|
-
|
|
27
|
-
## 1. Environment Promotion
|
|
28
|
-
|
|
29
|
-
### Environment Ladder
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
Development → Staging → Production
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
| Environment | Purpose | Who Deploys | Auto/Manual |
|
|
36
|
-
|-------------|---------|-------------|-------------|
|
|
37
|
-
| Development | Feature testing, integration | Any developer | Auto on PR merge to dev |
|
|
38
|
-
| Staging | Pre-production validation, QA | CI/CD pipeline | Auto on merge to main |
|
|
39
|
-
| Production | Live users | CI/CD + manual approval | Manual gate after staging |
|
|
40
|
-
|
|
41
|
-
### Rules
|
|
42
|
-
- Code must pass through ALL environments in order — no skipping staging
|
|
43
|
-
- Staging must mirror production configuration (same infra, same env vars pattern)
|
|
44
|
-
- Production deployments require at least 1 manual approval
|
|
45
|
-
- Exception: hotfix branches can fast-track with 2 approvals
|
|
46
|
-
|
|
47
|
-
## 2. CI/CD Pipeline Structure
|
|
48
|
-
|
|
49
|
-
### Required Pipeline Stages
|
|
50
|
-
|
|
51
|
-
```yaml
|
|
52
|
-
# Every service must implement these stages:
|
|
53
|
-
|
|
54
|
-
stages:
|
|
55
|
-
# Stage 1: Quality Gates (runs on every PR)
|
|
56
|
-
- lint # Code style, formatting
|
|
57
|
-
- typecheck # TypeScript / mypy
|
|
58
|
-
- test:unit # Unit tests with coverage
|
|
59
|
-
- security:scan # Dependency vulnerability scan
|
|
60
|
-
|
|
61
|
-
# Stage 2: Build (runs on merge to main)
|
|
62
|
-
- build # Compile, bundle, Docker build
|
|
63
|
-
- test:integration # Integration tests against test DB
|
|
64
|
-
|
|
65
|
-
# Stage 3: Deploy (runs after build succeeds)
|
|
66
|
-
- deploy:staging # Auto-deploy to staging
|
|
67
|
-
- test:e2e # E2E tests against staging
|
|
68
|
-
- deploy:production # Manual approval gate → production
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Rules
|
|
72
|
-
- PRs cannot merge if any Stage 1 check fails
|
|
73
|
-
- Build artifacts are created ONCE and promoted through environments
|
|
74
|
-
- Never rebuild between staging and production — same artifact, different config
|
|
75
|
-
- Pipeline must complete in under 15 minutes for Stage 1 (fast feedback)
|
|
76
|
-
- Full pipeline (through staging E2E) under 30 minutes
|
|
77
|
-
|
|
78
|
-
## 3. Containerization (Docker)
|
|
79
|
-
|
|
80
|
-
### Dockerfile Standards
|
|
81
|
-
|
|
82
|
-
```dockerfile
|
|
83
|
-
# ── Stage 1: Dependencies ──
|
|
84
|
-
FROM node:20-alpine AS deps
|
|
85
|
-
WORKDIR /app
|
|
86
|
-
COPY package.json package-lock.json ./
|
|
87
|
-
RUN npm ci --production=false
|
|
88
|
-
|
|
89
|
-
# ── Stage 2: Build ──
|
|
90
|
-
FROM node:20-alpine AS build
|
|
91
|
-
WORKDIR /app
|
|
92
|
-
COPY --from=deps /app/node_modules ./node_modules
|
|
93
|
-
COPY . .
|
|
94
|
-
RUN npm run build
|
|
95
|
-
RUN npm prune --production
|
|
96
|
-
|
|
97
|
-
# ── Stage 3: Production ──
|
|
98
|
-
FROM node:20-alpine AS production
|
|
99
|
-
WORKDIR /app
|
|
100
|
-
|
|
101
|
-
# Security: run as non-root
|
|
102
|
-
RUN addgroup -g 1001 appgroup && \
|
|
103
|
-
adduser -u 1001 -G appgroup -D appuser
|
|
104
|
-
USER appuser
|
|
105
|
-
|
|
106
|
-
COPY --from=build /app/dist ./dist
|
|
107
|
-
COPY --from=build /app/node_modules ./node_modules
|
|
108
|
-
COPY --from=build /app/package.json ./
|
|
109
|
-
|
|
110
|
-
EXPOSE 3000
|
|
111
|
-
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \
|
|
112
|
-
CMD wget -qO- http://localhost:3000/health || exit 1
|
|
113
|
-
|
|
114
|
-
CMD ["node", "dist/main.js"]
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### Rules
|
|
118
|
-
- Multi-stage builds always — keep production image minimal
|
|
119
|
-
- Run as non-root user — never run as root in production
|
|
120
|
-
- Include HEALTHCHECK in Dockerfile
|
|
121
|
-
- Pin base image versions: `node:20.11-alpine` not `node:latest`
|
|
122
|
-
- Use `.dockerignore` to exclude: node_modules, .git, .env, tests, docs
|
|
123
|
-
- Production image should be under 200MB
|
|
124
|
-
- No dev dependencies in production stage
|
|
125
|
-
|
|
126
|
-
## 4. Environment Configuration
|
|
127
|
-
|
|
128
|
-
### Config by Environment
|
|
129
|
-
|
|
130
|
-
```
|
|
131
|
-
# Pattern: same env var names, different values per environment
|
|
132
|
-
DATABASE_URL=postgres://... # different per environment
|
|
133
|
-
LOG_LEVEL=debug # development
|
|
134
|
-
LOG_LEVEL=info # staging
|
|
135
|
-
LOG_LEVEL=warn # production
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### Rules
|
|
139
|
-
- Same env var names across all environments
|
|
140
|
-
- Secrets stored in secrets manager (not in CI/CD variables for production)
|
|
141
|
-
- Environment-specific config via env vars, never via code branches
|
|
142
|
-
- Every env var documented in README (see documentation skill)
|
|
143
|
-
- Config validated at startup (see security-baseline skill)
|
|
144
|
-
|
|
145
|
-
## 5. Release Strategy
|
|
146
|
-
|
|
147
|
-
### Semantic Versioning
|
|
148
|
-
```
|
|
149
|
-
v{MAJOR}.{MINOR}.{PATCH}
|
|
150
|
-
|
|
151
|
-
MAJOR: Breaking changes (API incompatibility)
|
|
152
|
-
MINOR: New features (backward compatible)
|
|
153
|
-
PATCH: Bug fixes (backward compatible)
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### Release Process
|
|
157
|
-
1. Merge to main → auto-deploy to staging
|
|
158
|
-
2. QA validates on staging (manual or automated)
|
|
159
|
-
3. Create GitHub Release with tag `v1.2.3`
|
|
160
|
-
4. Release triggers production deployment (with manual approval gate)
|
|
161
|
-
5. Monitor dashboards for 15 minutes post-deploy
|
|
162
|
-
6. If issues: rollback immediately
|
|
163
|
-
|
|
164
|
-
### Feature Flags
|
|
165
|
-
For risky changes, use feature flags:
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
// Feature flag pattern
|
|
169
|
-
if (featureFlags.isEnabled("new-checkout-flow", { userId: user.id })) {
|
|
170
|
-
return newCheckoutFlow(order);
|
|
171
|
-
} else {
|
|
172
|
-
return legacyCheckoutFlow(order);
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### Rules
|
|
177
|
-
- Feature flags for any change affecting > 10% of users
|
|
178
|
-
- Flags have an expiry date — clean up within 2 weeks of full rollout
|
|
179
|
-
- Flag states stored in config service (not hardcoded)
|
|
180
|
-
- Always have a kill switch that reverts to old behavior
|
|
181
|
-
|
|
182
|
-
## 6. Rollback Procedures
|
|
183
|
-
|
|
184
|
-
### Automated Rollback Triggers
|
|
185
|
-
- Error rate > 5% for 2 minutes
|
|
186
|
-
- p99 latency > 5s for 5 minutes
|
|
187
|
-
- Health check failures on > 25% of instances
|
|
188
|
-
|
|
189
|
-
### Manual Rollback Process
|
|
190
|
-
```bash
|
|
191
|
-
# Option 1: Revert to previous container image
|
|
192
|
-
kubectl rollout undo deployment/my-service
|
|
193
|
-
|
|
194
|
-
# Option 2: Deploy a specific known-good version
|
|
195
|
-
kubectl set image deployment/my-service app=my-service:v1.2.2
|
|
196
|
-
|
|
197
|
-
# Option 3: Disable via feature flag (fastest)
|
|
198
|
-
# Toggle flag off in config service
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
### Rules
|
|
202
|
-
- Every deployment must be rollback-ready before proceeding
|
|
203
|
-
- Database migrations must be backward-compatible (new code works with old schema AND new schema)
|
|
204
|
-
- Rollback should complete in under 5 minutes
|
|
205
|
-
- Post-rollback: create incident ticket, investigate, fix forward
|
|
206
|
-
- Never rollback database migrations in production — fix forward only
|
|
207
|
-
|
|
208
|
-
## 7. Database Migration Safety
|
|
209
|
-
|
|
210
|
-
### Safe Migration Patterns
|
|
211
|
-
```
|
|
212
|
-
✅ ADD a new column (nullable or with default)
|
|
213
|
-
✅ ADD a new table
|
|
214
|
-
✅ ADD a new index (CONCURRENTLY)
|
|
215
|
-
✅ RENAME with a transition period (old name → alias → new name)
|
|
216
|
-
|
|
217
|
-
❌ DROP a column (in same deploy as code change)
|
|
218
|
-
❌ RENAME a column (without transition period)
|
|
219
|
-
❌ CHANGE column type (without transition period)
|
|
220
|
-
❌ ADD NOT NULL without default
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
### Two-Phase Migration Pattern
|
|
224
|
-
For breaking schema changes:
|
|
225
|
-
1. **Phase 1**: Deploy code that works with BOTH old and new schema. Run migration to add new structure.
|
|
226
|
-
2. **Phase 2** (next release): Deploy code that uses only new schema. Remove old structure.
|
|
227
|
-
|
|
228
|
-
## Checklist
|
|
229
|
-
|
|
230
|
-
Before deploying:
|
|
231
|
-
- [ ] All CI stages pass (lint, typecheck, unit tests, security scan)
|
|
232
|
-
- [ ] Docker image is multi-stage, runs as non-root, under 200MB
|
|
233
|
-
- [ ] Integration tests pass against staging
|
|
234
|
-
- [ ] E2E tests pass against staging
|
|
235
|
-
- [ ] Database migration is backward-compatible
|
|
236
|
-
- [ ] Rollback plan documented and tested
|
|
237
|
-
- [ ] Feature flags in place for risky changes
|
|
238
|
-
- [ ] Monitoring dashboards ready for post-deploy observation
|
|
239
|
-
- [ ] Manual approval obtained for production
|
|
240
|
-
- [ ] Changelog updated
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
## Test 1: Dockerfile Creation
|
|
2
|
-
**Prompt**: "Write a Dockerfile for a Node.js Express API service with TypeScript compilation"
|
|
3
|
-
**Expected**:
|
|
4
|
-
- Multi-stage build (deps → build → production)
|
|
5
|
-
- Non-root user
|
|
6
|
-
- HEALTHCHECK instruction
|
|
7
|
-
- Pinned base image version
|
|
8
|
-
- Production-only dependencies in final stage
|
|
9
|
-
- .dockerignore mentioned
|
|
10
|
-
|
|
11
|
-
## Test 2: CI/CD Pipeline
|
|
12
|
-
**Prompt**: "Set up a GitHub Actions workflow for a Python FastAPI service with linting, testing, Docker build, and deployment to staging"
|
|
13
|
-
**Expected**:
|
|
14
|
-
- Stages: lint → typecheck → test → build → deploy
|
|
15
|
-
- Runs on PR and merge to main
|
|
16
|
-
- Docker build with caching
|
|
17
|
-
- Integration tests before deploy
|
|
18
|
-
- Environment-specific secrets handling
|
|
19
|
-
|
|
20
|
-
## Test 3: Database Migration Strategy
|
|
21
|
-
**Prompt**: "I need to rename the 'username' column to 'display_name' in our users table. How do I do this safely?"
|
|
22
|
-
**Expected**:
|
|
23
|
-
- Two-phase migration approach
|
|
24
|
-
- Phase 1: add display_name, backfill, deploy code that reads both
|
|
25
|
-
- Phase 2: drop username column in next release
|
|
26
|
-
- Never rename in a single deploy
|
|
27
|
-
- Backward compatibility emphasized
|