elsabro 2.0.1 → 2.2.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/commands/elsabro/add-phase.md +17 -0
- package/commands/elsabro/add-todo.md +111 -53
- package/commands/elsabro/audit-milestone.md +19 -0
- package/commands/elsabro/check-todos.md +210 -31
- package/commands/elsabro/complete-milestone.md +20 -1
- package/commands/elsabro/debug.md +19 -0
- package/commands/elsabro/discuss-phase.md +18 -1
- package/commands/elsabro/execute.md +496 -52
- package/commands/elsabro/insert-phase.md +18 -1
- package/commands/elsabro/list-phase-assumptions.md +17 -0
- package/commands/elsabro/new-milestone.md +19 -0
- package/commands/elsabro/new.md +19 -0
- package/commands/elsabro/pause-work.md +75 -0
- package/commands/elsabro/plan-milestone-gaps.md +20 -1
- package/commands/elsabro/plan.md +264 -36
- package/commands/elsabro/progress.md +203 -79
- package/commands/elsabro/quick.md +19 -0
- package/commands/elsabro/remove-phase.md +17 -0
- package/commands/elsabro/research-phase.md +18 -1
- package/commands/elsabro/resume-work.md +130 -2
- package/commands/elsabro/start.md +365 -98
- package/commands/elsabro/verify-work.md +271 -12
- package/package.json +1 -1
- package/references/SYSTEM_INDEX.md +241 -0
- package/references/command-flow.md +352 -0
- package/references/enforcement-rules.md +331 -0
- package/references/error-handling-instructions.md +26 -12
- package/references/state-sync.md +381 -0
- package/references/task-dispatcher.md +388 -0
- package/references/tasks-integration.md +380 -0
- package/skills/api-microservice.md +765 -0
- package/skills/api-setup.md +76 -3
- package/skills/auth-setup.md +46 -6
- package/skills/chrome-extension.md +584 -0
- package/skills/cicd-setup.md +1206 -0
- package/skills/cli-tool.md +884 -0
- package/skills/database-setup.md +41 -5
- package/skills/desktop-app.md +1351 -0
- package/skills/expo-app.md +35 -2
- package/skills/full-stack-app.md +543 -0
- package/skills/mobile-app.md +813 -0
- package/skills/nextjs-app.md +33 -2
- package/skills/payments-setup.md +76 -1
- package/skills/saas-starter.md +639 -0
- package/skills/sentry-setup.md +41 -7
- package/skills/testing-setup.md +1218 -0
|
@@ -0,0 +1,1206 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cicd-setup
|
|
3
|
+
description: Configurar CI/CD completo con GitHub Actions, testing automatizado, deployment y releases
|
|
4
|
+
tags: [cicd, github-actions, deployment, automation, devops, vercel, netlify, releases]
|
|
5
|
+
difficulty: advanced
|
|
6
|
+
estimated_time: 35min
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Skill: CI/CD Setup
|
|
10
|
+
|
|
11
|
+
<when_to_use>
|
|
12
|
+
Usar cuando el usuario menciona:
|
|
13
|
+
- "CI/CD"
|
|
14
|
+
- "GitHub Actions"
|
|
15
|
+
- "deploy automatico"
|
|
16
|
+
- "pipeline"
|
|
17
|
+
- "integracion continua"
|
|
18
|
+
- "continuous deployment"
|
|
19
|
+
- "automatizar releases"
|
|
20
|
+
- "workflow de CI"
|
|
21
|
+
- "deploy a produccion"
|
|
22
|
+
</when_to_use>
|
|
23
|
+
|
|
24
|
+
<pre_requisites>
|
|
25
|
+
## Pre-requisitos
|
|
26
|
+
- Repositorio en GitHub
|
|
27
|
+
- Proyecto con tests configurados
|
|
28
|
+
- Cuenta en plataforma de deployment (Vercel/Netlify)
|
|
29
|
+
- Conocimiento basico de YAML
|
|
30
|
+
- (Opcional) NPM account para publicar paquetes
|
|
31
|
+
</pre_requisites>
|
|
32
|
+
|
|
33
|
+
<tech_stack>
|
|
34
|
+
## Stack Tecnologico
|
|
35
|
+
| Categoria | Tecnologia | Version | Proposito |
|
|
36
|
+
|-----------|------------|---------|-----------|
|
|
37
|
+
| CI | GitHub Actions | - | Workflows automatizados |
|
|
38
|
+
| Deployment | Vercel | - | Deploy de apps Next.js/React |
|
|
39
|
+
| Deployment Alt | Netlify | - | Deploy de sitios estaticos |
|
|
40
|
+
| Releases | semantic-release | 24.x | Versionado semantico automatico |
|
|
41
|
+
| Changelog | conventional-changelog | 5.x | Generacion de changelog |
|
|
42
|
+
| Linting | ESLint | 9.x | Linting de codigo |
|
|
43
|
+
| Formatting | Prettier | 3.x | Formateo de codigo |
|
|
44
|
+
| Commits | commitlint | 19.x | Validacion de commits |
|
|
45
|
+
| Hooks | husky | 9.x | Git hooks |
|
|
46
|
+
</tech_stack>
|
|
47
|
+
|
|
48
|
+
<project_structure>
|
|
49
|
+
## Estructura de Proyecto
|
|
50
|
+
```
|
|
51
|
+
project/
|
|
52
|
+
├── .github/
|
|
53
|
+
│ ├── workflows/
|
|
54
|
+
│ │ ├── ci.yml # Tests, lint, build
|
|
55
|
+
│ │ ├── deploy-preview.yml # Preview deployments
|
|
56
|
+
│ │ ├── deploy-prod.yml # Production deployment
|
|
57
|
+
│ │ ├── release.yml # Semantic release
|
|
58
|
+
│ │ └── codeql.yml # Security scanning
|
|
59
|
+
│ ├── CODEOWNERS
|
|
60
|
+
│ ├── dependabot.yml
|
|
61
|
+
│ └── PULL_REQUEST_TEMPLATE.md
|
|
62
|
+
├── .husky/
|
|
63
|
+
│ ├── pre-commit
|
|
64
|
+
│ ├── commit-msg
|
|
65
|
+
│ └── pre-push
|
|
66
|
+
├── .releaserc.json
|
|
67
|
+
├── commitlint.config.js
|
|
68
|
+
└── package.json
|
|
69
|
+
```
|
|
70
|
+
</project_structure>
|
|
71
|
+
|
|
72
|
+
<setup_steps>
|
|
73
|
+
## Paso 1: Instalar Dependencias
|
|
74
|
+
|
|
75
|
+
### Dependencias de Desarrollo
|
|
76
|
+
```bash
|
|
77
|
+
# Semantic Release
|
|
78
|
+
npm install -D semantic-release @semantic-release/changelog @semantic-release/git @semantic-release/github
|
|
79
|
+
|
|
80
|
+
# Commitlint
|
|
81
|
+
npm install -D @commitlint/cli @commitlint/config-conventional
|
|
82
|
+
|
|
83
|
+
# Husky
|
|
84
|
+
npm install -D husky
|
|
85
|
+
|
|
86
|
+
# Lint-staged
|
|
87
|
+
npm install -D lint-staged
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Inicializar Husky
|
|
91
|
+
```bash
|
|
92
|
+
npx husky init
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Paso 2: Workflow de CI Principal
|
|
96
|
+
|
|
97
|
+
### .github/workflows/ci.yml
|
|
98
|
+
```yaml
|
|
99
|
+
name: CI
|
|
100
|
+
|
|
101
|
+
on:
|
|
102
|
+
push:
|
|
103
|
+
branches: [main, develop]
|
|
104
|
+
pull_request:
|
|
105
|
+
branches: [main, develop]
|
|
106
|
+
|
|
107
|
+
concurrency:
|
|
108
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
109
|
+
cancel-in-progress: true
|
|
110
|
+
|
|
111
|
+
env:
|
|
112
|
+
NODE_VERSION: '20'
|
|
113
|
+
PNPM_VERSION: '9'
|
|
114
|
+
|
|
115
|
+
jobs:
|
|
116
|
+
# ============================================
|
|
117
|
+
# Lint & Format Check
|
|
118
|
+
# ============================================
|
|
119
|
+
lint:
|
|
120
|
+
name: Lint & Format
|
|
121
|
+
runs-on: ubuntu-latest
|
|
122
|
+
steps:
|
|
123
|
+
- name: Checkout
|
|
124
|
+
uses: actions/checkout@v4
|
|
125
|
+
|
|
126
|
+
- name: Setup pnpm
|
|
127
|
+
uses: pnpm/action-setup@v4
|
|
128
|
+
with:
|
|
129
|
+
version: ${{ env.PNPM_VERSION }}
|
|
130
|
+
|
|
131
|
+
- name: Setup Node.js
|
|
132
|
+
uses: actions/setup-node@v4
|
|
133
|
+
with:
|
|
134
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
135
|
+
cache: 'pnpm'
|
|
136
|
+
|
|
137
|
+
- name: Install dependencies
|
|
138
|
+
run: pnpm install --frozen-lockfile
|
|
139
|
+
|
|
140
|
+
- name: Run ESLint
|
|
141
|
+
run: pnpm lint
|
|
142
|
+
|
|
143
|
+
- name: Check formatting
|
|
144
|
+
run: pnpm format:check
|
|
145
|
+
|
|
146
|
+
- name: Type check
|
|
147
|
+
run: pnpm type-check
|
|
148
|
+
|
|
149
|
+
# ============================================
|
|
150
|
+
# Unit & Integration Tests
|
|
151
|
+
# ============================================
|
|
152
|
+
test:
|
|
153
|
+
name: Tests
|
|
154
|
+
runs-on: ubuntu-latest
|
|
155
|
+
needs: lint
|
|
156
|
+
strategy:
|
|
157
|
+
matrix:
|
|
158
|
+
node-version: [18, 20, 22]
|
|
159
|
+
steps:
|
|
160
|
+
- name: Checkout
|
|
161
|
+
uses: actions/checkout@v4
|
|
162
|
+
|
|
163
|
+
- name: Setup pnpm
|
|
164
|
+
uses: pnpm/action-setup@v4
|
|
165
|
+
with:
|
|
166
|
+
version: ${{ env.PNPM_VERSION }}
|
|
167
|
+
|
|
168
|
+
- name: Setup Node.js ${{ matrix.node-version }}
|
|
169
|
+
uses: actions/setup-node@v4
|
|
170
|
+
with:
|
|
171
|
+
node-version: ${{ matrix.node-version }}
|
|
172
|
+
cache: 'pnpm'
|
|
173
|
+
|
|
174
|
+
- name: Install dependencies
|
|
175
|
+
run: pnpm install --frozen-lockfile
|
|
176
|
+
|
|
177
|
+
- name: Run tests with coverage
|
|
178
|
+
run: pnpm test:coverage
|
|
179
|
+
|
|
180
|
+
- name: Upload coverage to Codecov
|
|
181
|
+
uses: codecov/codecov-action@v4
|
|
182
|
+
if: matrix.node-version == 20
|
|
183
|
+
with:
|
|
184
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
185
|
+
files: ./coverage/lcov.info
|
|
186
|
+
fail_ci_if_error: false
|
|
187
|
+
|
|
188
|
+
# ============================================
|
|
189
|
+
# E2E Tests
|
|
190
|
+
# ============================================
|
|
191
|
+
e2e:
|
|
192
|
+
name: E2E Tests
|
|
193
|
+
runs-on: ubuntu-latest
|
|
194
|
+
needs: lint
|
|
195
|
+
steps:
|
|
196
|
+
- name: Checkout
|
|
197
|
+
uses: actions/checkout@v4
|
|
198
|
+
|
|
199
|
+
- name: Setup pnpm
|
|
200
|
+
uses: pnpm/action-setup@v4
|
|
201
|
+
with:
|
|
202
|
+
version: ${{ env.PNPM_VERSION }}
|
|
203
|
+
|
|
204
|
+
- name: Setup Node.js
|
|
205
|
+
uses: actions/setup-node@v4
|
|
206
|
+
with:
|
|
207
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
208
|
+
cache: 'pnpm'
|
|
209
|
+
|
|
210
|
+
- name: Install dependencies
|
|
211
|
+
run: pnpm install --frozen-lockfile
|
|
212
|
+
|
|
213
|
+
- name: Install Playwright browsers
|
|
214
|
+
run: pnpm exec playwright install --with-deps chromium
|
|
215
|
+
|
|
216
|
+
- name: Build application
|
|
217
|
+
run: pnpm build
|
|
218
|
+
|
|
219
|
+
- name: Run E2E tests
|
|
220
|
+
run: pnpm test:e2e
|
|
221
|
+
|
|
222
|
+
- name: Upload Playwright report
|
|
223
|
+
uses: actions/upload-artifact@v4
|
|
224
|
+
if: failure()
|
|
225
|
+
with:
|
|
226
|
+
name: playwright-report
|
|
227
|
+
path: playwright-report/
|
|
228
|
+
retention-days: 7
|
|
229
|
+
|
|
230
|
+
# ============================================
|
|
231
|
+
# Build
|
|
232
|
+
# ============================================
|
|
233
|
+
build:
|
|
234
|
+
name: Build
|
|
235
|
+
runs-on: ubuntu-latest
|
|
236
|
+
needs: [test, e2e]
|
|
237
|
+
steps:
|
|
238
|
+
- name: Checkout
|
|
239
|
+
uses: actions/checkout@v4
|
|
240
|
+
|
|
241
|
+
- name: Setup pnpm
|
|
242
|
+
uses: pnpm/action-setup@v4
|
|
243
|
+
with:
|
|
244
|
+
version: ${{ env.PNPM_VERSION }}
|
|
245
|
+
|
|
246
|
+
- name: Setup Node.js
|
|
247
|
+
uses: actions/setup-node@v4
|
|
248
|
+
with:
|
|
249
|
+
node-version: ${{ env.NODE_VERSION }}
|
|
250
|
+
cache: 'pnpm'
|
|
251
|
+
|
|
252
|
+
- name: Install dependencies
|
|
253
|
+
run: pnpm install --frozen-lockfile
|
|
254
|
+
|
|
255
|
+
- name: Build
|
|
256
|
+
run: pnpm build
|
|
257
|
+
|
|
258
|
+
- name: Upload build artifacts
|
|
259
|
+
uses: actions/upload-artifact@v4
|
|
260
|
+
with:
|
|
261
|
+
name: build
|
|
262
|
+
path: |
|
|
263
|
+
.next/
|
|
264
|
+
dist/
|
|
265
|
+
out/
|
|
266
|
+
retention-days: 7
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Paso 3: Preview Deployments
|
|
270
|
+
|
|
271
|
+
### .github/workflows/deploy-preview.yml
|
|
272
|
+
```yaml
|
|
273
|
+
name: Preview Deployment
|
|
274
|
+
|
|
275
|
+
on:
|
|
276
|
+
pull_request:
|
|
277
|
+
types: [opened, synchronize, reopened]
|
|
278
|
+
|
|
279
|
+
env:
|
|
280
|
+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
|
281
|
+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
|
282
|
+
|
|
283
|
+
jobs:
|
|
284
|
+
deploy-preview:
|
|
285
|
+
name: Deploy Preview
|
|
286
|
+
runs-on: ubuntu-latest
|
|
287
|
+
environment:
|
|
288
|
+
name: preview
|
|
289
|
+
url: ${{ steps.deploy.outputs.preview-url }}
|
|
290
|
+
steps:
|
|
291
|
+
- name: Checkout
|
|
292
|
+
uses: actions/checkout@v4
|
|
293
|
+
|
|
294
|
+
- name: Setup pnpm
|
|
295
|
+
uses: pnpm/action-setup@v4
|
|
296
|
+
with:
|
|
297
|
+
version: '9'
|
|
298
|
+
|
|
299
|
+
- name: Setup Node.js
|
|
300
|
+
uses: actions/setup-node@v4
|
|
301
|
+
with:
|
|
302
|
+
node-version: '20'
|
|
303
|
+
cache: 'pnpm'
|
|
304
|
+
|
|
305
|
+
- name: Install Vercel CLI
|
|
306
|
+
run: pnpm add -g vercel@latest
|
|
307
|
+
|
|
308
|
+
- name: Pull Vercel Environment
|
|
309
|
+
run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}
|
|
310
|
+
|
|
311
|
+
- name: Build Project
|
|
312
|
+
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
|
|
313
|
+
|
|
314
|
+
- name: Deploy to Vercel
|
|
315
|
+
id: deploy
|
|
316
|
+
run: |
|
|
317
|
+
url=$(vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }})
|
|
318
|
+
echo "preview-url=$url" >> $GITHUB_OUTPUT
|
|
319
|
+
|
|
320
|
+
- name: Comment on PR
|
|
321
|
+
uses: actions/github-script@v7
|
|
322
|
+
with:
|
|
323
|
+
script: |
|
|
324
|
+
const url = '${{ steps.deploy.outputs.preview-url }}';
|
|
325
|
+
const body = `## Preview Deployment
|
|
326
|
+
|
|
327
|
+
| Status | URL |
|
|
328
|
+
|--------|-----|
|
|
329
|
+
| Deployed | [${url}](${url}) |
|
|
330
|
+
|
|
331
|
+
> Commit: \`${{ github.sha }}\`
|
|
332
|
+
`;
|
|
333
|
+
|
|
334
|
+
// Find existing comment
|
|
335
|
+
const { data: comments } = await github.rest.issues.listComments({
|
|
336
|
+
owner: context.repo.owner,
|
|
337
|
+
repo: context.repo.repo,
|
|
338
|
+
issue_number: context.issue.number,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
const botComment = comments.find(c =>
|
|
342
|
+
c.user.type === 'Bot' &&
|
|
343
|
+
c.body.includes('Preview Deployment')
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
if (botComment) {
|
|
347
|
+
await github.rest.issues.updateComment({
|
|
348
|
+
owner: context.repo.owner,
|
|
349
|
+
repo: context.repo.repo,
|
|
350
|
+
comment_id: botComment.id,
|
|
351
|
+
body,
|
|
352
|
+
});
|
|
353
|
+
} else {
|
|
354
|
+
await github.rest.issues.createComment({
|
|
355
|
+
owner: context.repo.owner,
|
|
356
|
+
repo: context.repo.repo,
|
|
357
|
+
issue_number: context.issue.number,
|
|
358
|
+
body,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
## Paso 4: Production Deployment
|
|
364
|
+
|
|
365
|
+
### .github/workflows/deploy-prod.yml
|
|
366
|
+
```yaml
|
|
367
|
+
name: Production Deployment
|
|
368
|
+
|
|
369
|
+
on:
|
|
370
|
+
push:
|
|
371
|
+
branches: [main]
|
|
372
|
+
workflow_dispatch:
|
|
373
|
+
inputs:
|
|
374
|
+
environment:
|
|
375
|
+
description: 'Environment to deploy to'
|
|
376
|
+
required: true
|
|
377
|
+
default: 'production'
|
|
378
|
+
type: choice
|
|
379
|
+
options:
|
|
380
|
+
- production
|
|
381
|
+
- staging
|
|
382
|
+
|
|
383
|
+
env:
|
|
384
|
+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
|
385
|
+
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
|
|
386
|
+
|
|
387
|
+
jobs:
|
|
388
|
+
# ============================================
|
|
389
|
+
# Run Tests First
|
|
390
|
+
# ============================================
|
|
391
|
+
test:
|
|
392
|
+
name: Run Tests
|
|
393
|
+
uses: ./.github/workflows/ci.yml
|
|
394
|
+
secrets: inherit
|
|
395
|
+
|
|
396
|
+
# ============================================
|
|
397
|
+
# Deploy to Production
|
|
398
|
+
# ============================================
|
|
399
|
+
deploy:
|
|
400
|
+
name: Deploy to Production
|
|
401
|
+
runs-on: ubuntu-latest
|
|
402
|
+
needs: test
|
|
403
|
+
environment:
|
|
404
|
+
name: production
|
|
405
|
+
url: ${{ steps.deploy.outputs.production-url }}
|
|
406
|
+
steps:
|
|
407
|
+
- name: Checkout
|
|
408
|
+
uses: actions/checkout@v4
|
|
409
|
+
|
|
410
|
+
- name: Setup pnpm
|
|
411
|
+
uses: pnpm/action-setup@v4
|
|
412
|
+
with:
|
|
413
|
+
version: '9'
|
|
414
|
+
|
|
415
|
+
- name: Setup Node.js
|
|
416
|
+
uses: actions/setup-node@v4
|
|
417
|
+
with:
|
|
418
|
+
node-version: '20'
|
|
419
|
+
cache: 'pnpm'
|
|
420
|
+
|
|
421
|
+
- name: Install Vercel CLI
|
|
422
|
+
run: pnpm add -g vercel@latest
|
|
423
|
+
|
|
424
|
+
- name: Pull Vercel Environment
|
|
425
|
+
run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
|
|
426
|
+
|
|
427
|
+
- name: Build Project
|
|
428
|
+
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
|
|
429
|
+
|
|
430
|
+
- name: Deploy to Production
|
|
431
|
+
id: deploy
|
|
432
|
+
run: |
|
|
433
|
+
url=$(vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }})
|
|
434
|
+
echo "production-url=$url" >> $GITHUB_OUTPUT
|
|
435
|
+
|
|
436
|
+
- name: Create deployment status
|
|
437
|
+
uses: actions/github-script@v7
|
|
438
|
+
with:
|
|
439
|
+
script: |
|
|
440
|
+
await github.rest.repos.createDeploymentStatus({
|
|
441
|
+
owner: context.repo.owner,
|
|
442
|
+
repo: context.repo.repo,
|
|
443
|
+
deployment_id: context.payload.deployment?.id || 0,
|
|
444
|
+
state: 'success',
|
|
445
|
+
environment_url: '${{ steps.deploy.outputs.production-url }}',
|
|
446
|
+
description: 'Deployment successful'
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
# ============================================
|
|
450
|
+
# Post-deployment checks
|
|
451
|
+
# ============================================
|
|
452
|
+
smoke-test:
|
|
453
|
+
name: Smoke Tests
|
|
454
|
+
runs-on: ubuntu-latest
|
|
455
|
+
needs: deploy
|
|
456
|
+
steps:
|
|
457
|
+
- name: Checkout
|
|
458
|
+
uses: actions/checkout@v4
|
|
459
|
+
|
|
460
|
+
- name: Setup pnpm
|
|
461
|
+
uses: pnpm/action-setup@v4
|
|
462
|
+
with:
|
|
463
|
+
version: '9'
|
|
464
|
+
|
|
465
|
+
- name: Setup Node.js
|
|
466
|
+
uses: actions/setup-node@v4
|
|
467
|
+
with:
|
|
468
|
+
node-version: '20'
|
|
469
|
+
cache: 'pnpm'
|
|
470
|
+
|
|
471
|
+
- name: Install dependencies
|
|
472
|
+
run: pnpm install --frozen-lockfile
|
|
473
|
+
|
|
474
|
+
- name: Install Playwright
|
|
475
|
+
run: pnpm exec playwright install chromium
|
|
476
|
+
|
|
477
|
+
- name: Run smoke tests
|
|
478
|
+
run: pnpm test:e2e:smoke
|
|
479
|
+
env:
|
|
480
|
+
PLAYWRIGHT_BASE_URL: ${{ needs.deploy.outputs.production-url }}
|
|
481
|
+
|
|
482
|
+
- name: Notify on failure
|
|
483
|
+
if: failure()
|
|
484
|
+
uses: actions/github-script@v7
|
|
485
|
+
with:
|
|
486
|
+
script: |
|
|
487
|
+
await github.rest.issues.create({
|
|
488
|
+
owner: context.repo.owner,
|
|
489
|
+
repo: context.repo.repo,
|
|
490
|
+
title: 'Production smoke tests failed',
|
|
491
|
+
body: `Smoke tests failed after deployment.
|
|
492
|
+
|
|
493
|
+
- Commit: ${{ github.sha }}
|
|
494
|
+
- Workflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
495
|
+
|
|
496
|
+
Please investigate immediately.`,
|
|
497
|
+
labels: ['bug', 'priority:high']
|
|
498
|
+
});
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
## Paso 5: Semantic Release
|
|
502
|
+
|
|
503
|
+
### .github/workflows/release.yml
|
|
504
|
+
```yaml
|
|
505
|
+
name: Release
|
|
506
|
+
|
|
507
|
+
on:
|
|
508
|
+
push:
|
|
509
|
+
branches: [main]
|
|
510
|
+
workflow_dispatch:
|
|
511
|
+
|
|
512
|
+
permissions:
|
|
513
|
+
contents: write
|
|
514
|
+
issues: write
|
|
515
|
+
pull-requests: write
|
|
516
|
+
id-token: write
|
|
517
|
+
|
|
518
|
+
jobs:
|
|
519
|
+
release:
|
|
520
|
+
name: Release
|
|
521
|
+
runs-on: ubuntu-latest
|
|
522
|
+
steps:
|
|
523
|
+
- name: Checkout
|
|
524
|
+
uses: actions/checkout@v4
|
|
525
|
+
with:
|
|
526
|
+
fetch-depth: 0
|
|
527
|
+
persist-credentials: false
|
|
528
|
+
|
|
529
|
+
- name: Setup pnpm
|
|
530
|
+
uses: pnpm/action-setup@v4
|
|
531
|
+
with:
|
|
532
|
+
version: '9'
|
|
533
|
+
|
|
534
|
+
- name: Setup Node.js
|
|
535
|
+
uses: actions/setup-node@v4
|
|
536
|
+
with:
|
|
537
|
+
node-version: '20'
|
|
538
|
+
cache: 'pnpm'
|
|
539
|
+
|
|
540
|
+
- name: Install dependencies
|
|
541
|
+
run: pnpm install --frozen-lockfile
|
|
542
|
+
|
|
543
|
+
- name: Build
|
|
544
|
+
run: pnpm build
|
|
545
|
+
|
|
546
|
+
- name: Run semantic-release
|
|
547
|
+
env:
|
|
548
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
549
|
+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
550
|
+
run: pnpm exec semantic-release
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### .releaserc.json
|
|
554
|
+
```json
|
|
555
|
+
{
|
|
556
|
+
"branches": [
|
|
557
|
+
"main",
|
|
558
|
+
{
|
|
559
|
+
"name": "beta",
|
|
560
|
+
"prerelease": true
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
"name": "alpha",
|
|
564
|
+
"prerelease": true
|
|
565
|
+
}
|
|
566
|
+
],
|
|
567
|
+
"plugins": [
|
|
568
|
+
[
|
|
569
|
+
"@semantic-release/commit-analyzer",
|
|
570
|
+
{
|
|
571
|
+
"preset": "conventionalcommits",
|
|
572
|
+
"releaseRules": [
|
|
573
|
+
{ "type": "feat", "release": "minor" },
|
|
574
|
+
{ "type": "fix", "release": "patch" },
|
|
575
|
+
{ "type": "perf", "release": "patch" },
|
|
576
|
+
{ "type": "revert", "release": "patch" },
|
|
577
|
+
{ "type": "docs", "scope": "README", "release": "patch" },
|
|
578
|
+
{ "type": "refactor", "release": "patch" },
|
|
579
|
+
{ "breaking": true, "release": "major" }
|
|
580
|
+
]
|
|
581
|
+
}
|
|
582
|
+
],
|
|
583
|
+
[
|
|
584
|
+
"@semantic-release/release-notes-generator",
|
|
585
|
+
{
|
|
586
|
+
"preset": "conventionalcommits",
|
|
587
|
+
"presetConfig": {
|
|
588
|
+
"types": [
|
|
589
|
+
{ "type": "feat", "section": "Features" },
|
|
590
|
+
{ "type": "fix", "section": "Bug Fixes" },
|
|
591
|
+
{ "type": "perf", "section": "Performance" },
|
|
592
|
+
{ "type": "revert", "section": "Reverts" },
|
|
593
|
+
{ "type": "docs", "section": "Documentation" },
|
|
594
|
+
{ "type": "refactor", "section": "Code Refactoring" },
|
|
595
|
+
{ "type": "test", "section": "Tests", "hidden": true },
|
|
596
|
+
{ "type": "chore", "section": "Miscellaneous", "hidden": true }
|
|
597
|
+
]
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
],
|
|
601
|
+
[
|
|
602
|
+
"@semantic-release/changelog",
|
|
603
|
+
{
|
|
604
|
+
"changelogFile": "CHANGELOG.md"
|
|
605
|
+
}
|
|
606
|
+
],
|
|
607
|
+
[
|
|
608
|
+
"@semantic-release/npm",
|
|
609
|
+
{
|
|
610
|
+
"npmPublish": false
|
|
611
|
+
}
|
|
612
|
+
],
|
|
613
|
+
[
|
|
614
|
+
"@semantic-release/git",
|
|
615
|
+
{
|
|
616
|
+
"assets": ["CHANGELOG.md", "package.json", "package-lock.json", "pnpm-lock.yaml"],
|
|
617
|
+
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
618
|
+
}
|
|
619
|
+
],
|
|
620
|
+
"@semantic-release/github"
|
|
621
|
+
]
|
|
622
|
+
}
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
## Paso 6: Security Scanning
|
|
626
|
+
|
|
627
|
+
### .github/workflows/codeql.yml
|
|
628
|
+
```yaml
|
|
629
|
+
name: CodeQL Analysis
|
|
630
|
+
|
|
631
|
+
on:
|
|
632
|
+
push:
|
|
633
|
+
branches: [main, develop]
|
|
634
|
+
pull_request:
|
|
635
|
+
branches: [main, develop]
|
|
636
|
+
schedule:
|
|
637
|
+
- cron: '0 6 * * 1' # Every Monday at 6 AM
|
|
638
|
+
|
|
639
|
+
jobs:
|
|
640
|
+
analyze:
|
|
641
|
+
name: Analyze
|
|
642
|
+
runs-on: ubuntu-latest
|
|
643
|
+
permissions:
|
|
644
|
+
security-events: write
|
|
645
|
+
actions: read
|
|
646
|
+
contents: read
|
|
647
|
+
|
|
648
|
+
strategy:
|
|
649
|
+
fail-fast: false
|
|
650
|
+
matrix:
|
|
651
|
+
language: ['javascript-typescript']
|
|
652
|
+
|
|
653
|
+
steps:
|
|
654
|
+
- name: Checkout
|
|
655
|
+
uses: actions/checkout@v4
|
|
656
|
+
|
|
657
|
+
- name: Initialize CodeQL
|
|
658
|
+
uses: github/codeql-action/init@v3
|
|
659
|
+
with:
|
|
660
|
+
languages: ${{ matrix.language }}
|
|
661
|
+
queries: +security-and-quality
|
|
662
|
+
|
|
663
|
+
- name: Autobuild
|
|
664
|
+
uses: github/codeql-action/autobuild@v3
|
|
665
|
+
|
|
666
|
+
- name: Perform CodeQL Analysis
|
|
667
|
+
uses: github/codeql-action/analyze@v3
|
|
668
|
+
with:
|
|
669
|
+
category: '/language:${{ matrix.language }}'
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
## Paso 7: Configurar Dependabot
|
|
673
|
+
|
|
674
|
+
### .github/dependabot.yml
|
|
675
|
+
```yaml
|
|
676
|
+
version: 2
|
|
677
|
+
updates:
|
|
678
|
+
# NPM dependencies
|
|
679
|
+
- package-ecosystem: 'npm'
|
|
680
|
+
directory: '/'
|
|
681
|
+
schedule:
|
|
682
|
+
interval: 'weekly'
|
|
683
|
+
day: 'monday'
|
|
684
|
+
time: '09:00'
|
|
685
|
+
open-pull-requests-limit: 10
|
|
686
|
+
reviewers:
|
|
687
|
+
- 'team-leads'
|
|
688
|
+
labels:
|
|
689
|
+
- 'dependencies'
|
|
690
|
+
- 'automated'
|
|
691
|
+
commit-message:
|
|
692
|
+
prefix: 'chore(deps)'
|
|
693
|
+
groups:
|
|
694
|
+
# Group minor/patch updates
|
|
695
|
+
minor-and-patch:
|
|
696
|
+
patterns:
|
|
697
|
+
- '*'
|
|
698
|
+
update-types:
|
|
699
|
+
- 'minor'
|
|
700
|
+
- 'patch'
|
|
701
|
+
# Keep major updates separate
|
|
702
|
+
major:
|
|
703
|
+
patterns:
|
|
704
|
+
- '*'
|
|
705
|
+
update-types:
|
|
706
|
+
- 'major'
|
|
707
|
+
|
|
708
|
+
# GitHub Actions
|
|
709
|
+
- package-ecosystem: 'github-actions'
|
|
710
|
+
directory: '/'
|
|
711
|
+
schedule:
|
|
712
|
+
interval: 'weekly'
|
|
713
|
+
day: 'monday'
|
|
714
|
+
labels:
|
|
715
|
+
- 'dependencies'
|
|
716
|
+
- 'github-actions'
|
|
717
|
+
commit-message:
|
|
718
|
+
prefix: 'chore(ci)'
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
## Paso 8: Git Hooks con Husky
|
|
722
|
+
|
|
723
|
+
### .husky/pre-commit
|
|
724
|
+
```bash
|
|
725
|
+
#!/usr/bin/env sh
|
|
726
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
727
|
+
|
|
728
|
+
# Run lint-staged
|
|
729
|
+
npx lint-staged
|
|
730
|
+
|
|
731
|
+
# Type check
|
|
732
|
+
npm run type-check
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
### .husky/commit-msg
|
|
736
|
+
```bash
|
|
737
|
+
#!/usr/bin/env sh
|
|
738
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
739
|
+
|
|
740
|
+
npx --no -- commitlint --edit "$1"
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
### .husky/pre-push
|
|
744
|
+
```bash
|
|
745
|
+
#!/usr/bin/env sh
|
|
746
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
747
|
+
|
|
748
|
+
# Run tests before push
|
|
749
|
+
npm run test
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
### commitlint.config.js
|
|
753
|
+
```javascript
|
|
754
|
+
module.exports = {
|
|
755
|
+
extends: ['@commitlint/config-conventional'],
|
|
756
|
+
rules: {
|
|
757
|
+
'type-enum': [
|
|
758
|
+
2,
|
|
759
|
+
'always',
|
|
760
|
+
[
|
|
761
|
+
'feat', // New feature
|
|
762
|
+
'fix', // Bug fix
|
|
763
|
+
'docs', // Documentation
|
|
764
|
+
'style', // Formatting, missing semicolons, etc
|
|
765
|
+
'refactor', // Code refactoring
|
|
766
|
+
'perf', // Performance improvements
|
|
767
|
+
'test', // Adding tests
|
|
768
|
+
'chore', // Maintenance
|
|
769
|
+
'revert', // Revert changes
|
|
770
|
+
'ci', // CI/CD changes
|
|
771
|
+
'build', // Build system changes
|
|
772
|
+
],
|
|
773
|
+
],
|
|
774
|
+
'subject-case': [2, 'always', 'lower-case'],
|
|
775
|
+
'subject-max-length': [2, 'always', 72],
|
|
776
|
+
'body-max-line-length': [2, 'always', 100],
|
|
777
|
+
},
|
|
778
|
+
};
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
### lint-staged.config.js
|
|
782
|
+
```javascript
|
|
783
|
+
module.exports = {
|
|
784
|
+
// TypeScript/JavaScript
|
|
785
|
+
'*.{ts,tsx,js,jsx}': [
|
|
786
|
+
'eslint --fix',
|
|
787
|
+
'prettier --write',
|
|
788
|
+
],
|
|
789
|
+
// JSON, YAML, Markdown
|
|
790
|
+
'*.{json,yaml,yml,md}': [
|
|
791
|
+
'prettier --write',
|
|
792
|
+
],
|
|
793
|
+
// CSS
|
|
794
|
+
'*.{css,scss}': [
|
|
795
|
+
'prettier --write',
|
|
796
|
+
],
|
|
797
|
+
};
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
## Paso 9: GitHub Configuration Files
|
|
801
|
+
|
|
802
|
+
### .github/CODEOWNERS
|
|
803
|
+
```
|
|
804
|
+
# Default owners
|
|
805
|
+
* @team-leads
|
|
806
|
+
|
|
807
|
+
# Frontend
|
|
808
|
+
/src/components/ @frontend-team
|
|
809
|
+
/src/styles/ @frontend-team
|
|
810
|
+
|
|
811
|
+
# Backend
|
|
812
|
+
/src/api/ @backend-team
|
|
813
|
+
/src/lib/ @backend-team
|
|
814
|
+
|
|
815
|
+
# Infrastructure
|
|
816
|
+
/.github/ @devops-team
|
|
817
|
+
/docker/ @devops-team
|
|
818
|
+
|
|
819
|
+
# Documentation
|
|
820
|
+
/docs/ @docs-team
|
|
821
|
+
*.md @docs-team
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
### .github/PULL_REQUEST_TEMPLATE.md
|
|
825
|
+
```markdown
|
|
826
|
+
## Description
|
|
827
|
+
|
|
828
|
+
<!-- Describe your changes in detail -->
|
|
829
|
+
|
|
830
|
+
## Type of Change
|
|
831
|
+
|
|
832
|
+
- [ ] Bug fix (non-breaking change that fixes an issue)
|
|
833
|
+
- [ ] New feature (non-breaking change that adds functionality)
|
|
834
|
+
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
|
835
|
+
- [ ] Documentation update
|
|
836
|
+
- [ ] Refactoring (no functional changes)
|
|
837
|
+
|
|
838
|
+
## Related Issues
|
|
839
|
+
|
|
840
|
+
<!-- Link to related issues: Fixes #123, Closes #456 -->
|
|
841
|
+
|
|
842
|
+
## Checklist
|
|
843
|
+
|
|
844
|
+
- [ ] My code follows the project's style guidelines
|
|
845
|
+
- [ ] I have performed a self-review of my code
|
|
846
|
+
- [ ] I have commented my code, particularly in hard-to-understand areas
|
|
847
|
+
- [ ] I have made corresponding changes to the documentation
|
|
848
|
+
- [ ] My changes generate no new warnings
|
|
849
|
+
- [ ] I have added tests that prove my fix is effective or that my feature works
|
|
850
|
+
- [ ] New and existing unit tests pass locally with my changes
|
|
851
|
+
- [ ] Any dependent changes have been merged and published
|
|
852
|
+
|
|
853
|
+
## Screenshots (if applicable)
|
|
854
|
+
|
|
855
|
+
<!-- Add screenshots to help explain your changes -->
|
|
856
|
+
|
|
857
|
+
## Additional Notes
|
|
858
|
+
|
|
859
|
+
<!-- Add any other context about the PR here -->
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
## Paso 10: Scripts en package.json
|
|
863
|
+
|
|
864
|
+
```json
|
|
865
|
+
{
|
|
866
|
+
"scripts": {
|
|
867
|
+
"dev": "next dev",
|
|
868
|
+
"build": "next build",
|
|
869
|
+
"start": "next start",
|
|
870
|
+
"lint": "eslint . --ext .ts,.tsx,.js,.jsx",
|
|
871
|
+
"lint:fix": "eslint . --ext .ts,.tsx,.js,.jsx --fix",
|
|
872
|
+
"format": "prettier --write .",
|
|
873
|
+
"format:check": "prettier --check .",
|
|
874
|
+
"type-check": "tsc --noEmit",
|
|
875
|
+
"test": "vitest run",
|
|
876
|
+
"test:watch": "vitest",
|
|
877
|
+
"test:coverage": "vitest run --coverage",
|
|
878
|
+
"test:e2e": "playwright test",
|
|
879
|
+
"test:e2e:smoke": "playwright test --grep @smoke",
|
|
880
|
+
"prepare": "husky",
|
|
881
|
+
"release": "semantic-release",
|
|
882
|
+
"release:dry": "semantic-release --dry-run"
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
## Paso 11: Netlify Alternative
|
|
888
|
+
|
|
889
|
+
### netlify.toml
|
|
890
|
+
```toml
|
|
891
|
+
[build]
|
|
892
|
+
command = "npm run build"
|
|
893
|
+
publish = ".next"
|
|
894
|
+
|
|
895
|
+
[build.environment]
|
|
896
|
+
NODE_VERSION = "20"
|
|
897
|
+
|
|
898
|
+
# Production context
|
|
899
|
+
[context.production]
|
|
900
|
+
command = "npm run build"
|
|
901
|
+
|
|
902
|
+
[context.production.environment]
|
|
903
|
+
NODE_ENV = "production"
|
|
904
|
+
|
|
905
|
+
# Deploy previews
|
|
906
|
+
[context.deploy-preview]
|
|
907
|
+
command = "npm run build"
|
|
908
|
+
|
|
909
|
+
[context.deploy-preview.environment]
|
|
910
|
+
NODE_ENV = "preview"
|
|
911
|
+
|
|
912
|
+
# Branch deploys
|
|
913
|
+
[context.branch-deploy]
|
|
914
|
+
command = "npm run build"
|
|
915
|
+
|
|
916
|
+
# Redirects
|
|
917
|
+
[[redirects]]
|
|
918
|
+
from = "/api/*"
|
|
919
|
+
to = "/.netlify/functions/:splat"
|
|
920
|
+
status = 200
|
|
921
|
+
|
|
922
|
+
[[redirects]]
|
|
923
|
+
from = "/*"
|
|
924
|
+
to = "/index.html"
|
|
925
|
+
status = 200
|
|
926
|
+
|
|
927
|
+
# Headers
|
|
928
|
+
[[headers]]
|
|
929
|
+
for = "/*"
|
|
930
|
+
[headers.values]
|
|
931
|
+
X-Frame-Options = "DENY"
|
|
932
|
+
X-XSS-Protection = "1; mode=block"
|
|
933
|
+
X-Content-Type-Options = "nosniff"
|
|
934
|
+
Referrer-Policy = "strict-origin-when-cross-origin"
|
|
935
|
+
|
|
936
|
+
[[headers]]
|
|
937
|
+
for = "/_next/static/*"
|
|
938
|
+
[headers.values]
|
|
939
|
+
Cache-Control = "public, max-age=31536000, immutable"
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
### .github/workflows/deploy-netlify.yml (Alternative)
|
|
943
|
+
```yaml
|
|
944
|
+
name: Deploy to Netlify
|
|
945
|
+
|
|
946
|
+
on:
|
|
947
|
+
push:
|
|
948
|
+
branches: [main]
|
|
949
|
+
pull_request:
|
|
950
|
+
branches: [main]
|
|
951
|
+
|
|
952
|
+
jobs:
|
|
953
|
+
deploy:
|
|
954
|
+
runs-on: ubuntu-latest
|
|
955
|
+
steps:
|
|
956
|
+
- uses: actions/checkout@v4
|
|
957
|
+
|
|
958
|
+
- name: Setup Node.js
|
|
959
|
+
uses: actions/setup-node@v4
|
|
960
|
+
with:
|
|
961
|
+
node-version: '20'
|
|
962
|
+
cache: 'npm'
|
|
963
|
+
|
|
964
|
+
- name: Install dependencies
|
|
965
|
+
run: npm ci
|
|
966
|
+
|
|
967
|
+
- name: Build
|
|
968
|
+
run: npm run build
|
|
969
|
+
|
|
970
|
+
- name: Deploy to Netlify
|
|
971
|
+
uses: nwtgck/actions-netlify@v3
|
|
972
|
+
with:
|
|
973
|
+
publish-dir: '.next'
|
|
974
|
+
production-branch: main
|
|
975
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
976
|
+
deploy-message: 'Deploy from GitHub Actions'
|
|
977
|
+
enable-pull-request-comment: true
|
|
978
|
+
enable-commit-comment: true
|
|
979
|
+
overwrites-pull-request-comment: true
|
|
980
|
+
env:
|
|
981
|
+
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
|
982
|
+
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
|
983
|
+
```
|
|
984
|
+
</setup_steps>
|
|
985
|
+
|
|
986
|
+
<secrets_setup>
|
|
987
|
+
## Configuracion de Secrets
|
|
988
|
+
|
|
989
|
+
### Secrets Requeridos en GitHub
|
|
990
|
+
|
|
991
|
+
1. **VERCEL_TOKEN**
|
|
992
|
+
```
|
|
993
|
+
Settings > Secrets > Actions > New repository secret
|
|
994
|
+
Nombre: VERCEL_TOKEN
|
|
995
|
+
Valor: Token de Vercel (Settings > Tokens)
|
|
996
|
+
```
|
|
997
|
+
|
|
998
|
+
2. **VERCEL_ORG_ID**
|
|
999
|
+
```
|
|
1000
|
+
Obtener de: .vercel/project.json despues de `vercel link`
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
3. **VERCEL_PROJECT_ID**
|
|
1004
|
+
```
|
|
1005
|
+
Obtener de: .vercel/project.json despues de `vercel link`
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
4. **NPM_TOKEN** (si publicas paquetes)
|
|
1009
|
+
```
|
|
1010
|
+
Obtener de: npm.js > Access Tokens > Generate New Token
|
|
1011
|
+
Tipo: Automation
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
5. **CODECOV_TOKEN** (para coverage)
|
|
1015
|
+
```
|
|
1016
|
+
Obtener de: codecov.io > Settings > Repository Upload Token
|
|
1017
|
+
```
|
|
1018
|
+
|
|
1019
|
+
### Secrets para Netlify (alternativo)
|
|
1020
|
+
|
|
1021
|
+
1. **NETLIFY_AUTH_TOKEN**
|
|
1022
|
+
```
|
|
1023
|
+
Obtener de: Netlify > User Settings > Applications > Personal access tokens
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
2. **NETLIFY_SITE_ID**
|
|
1027
|
+
```
|
|
1028
|
+
Obtener de: Netlify > Site Settings > General > Site ID
|
|
1029
|
+
```
|
|
1030
|
+
</secrets_setup>
|
|
1031
|
+
|
|
1032
|
+
<environments>
|
|
1033
|
+
## Configuracion de Environments
|
|
1034
|
+
|
|
1035
|
+
### GitHub Environments
|
|
1036
|
+
|
|
1037
|
+
Ir a: Settings > Environments
|
|
1038
|
+
|
|
1039
|
+
1. **preview**
|
|
1040
|
+
- No protection rules
|
|
1041
|
+
- Secrets: ninguno adicional
|
|
1042
|
+
|
|
1043
|
+
2. **staging**
|
|
1044
|
+
- Wait timer: 0 minutes
|
|
1045
|
+
- Required reviewers: 0
|
|
1046
|
+
- Secrets: staging-specific
|
|
1047
|
+
|
|
1048
|
+
3. **production**
|
|
1049
|
+
- Required reviewers: 1-2 personas
|
|
1050
|
+
- Wait timer: 5 minutes (opcional)
|
|
1051
|
+
- Branch protection: solo `main`
|
|
1052
|
+
- Secrets: production-specific
|
|
1053
|
+
|
|
1054
|
+
### Branch Protection Rules
|
|
1055
|
+
|
|
1056
|
+
Ir a: Settings > Branches > Add rule
|
|
1057
|
+
|
|
1058
|
+
**main branch:**
|
|
1059
|
+
```
|
|
1060
|
+
- Require a pull request before merging
|
|
1061
|
+
- Require approvals: 1
|
|
1062
|
+
- Dismiss stale PR approvals when new commits are pushed
|
|
1063
|
+
- Require status checks to pass
|
|
1064
|
+
- Require branches to be up to date
|
|
1065
|
+
- Status checks: lint, test, e2e, build
|
|
1066
|
+
- Require conversation resolution before merging
|
|
1067
|
+
- Do not allow bypassing the above settings
|
|
1068
|
+
```
|
|
1069
|
+
</environments>
|
|
1070
|
+
|
|
1071
|
+
<verification>
|
|
1072
|
+
## Verificacion
|
|
1073
|
+
|
|
1074
|
+
1. **CI Workflow**
|
|
1075
|
+
```bash
|
|
1076
|
+
# Push a un branch feature
|
|
1077
|
+
git checkout -b feature/test-ci
|
|
1078
|
+
git commit --allow-empty -m "test: verify CI workflow"
|
|
1079
|
+
git push origin feature/test-ci
|
|
1080
|
+
# Verificar que CI corre en GitHub Actions
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
2. **Preview Deployment**
|
|
1084
|
+
```bash
|
|
1085
|
+
# Crear PR
|
|
1086
|
+
gh pr create --title "Test preview" --body "Testing preview deployment"
|
|
1087
|
+
# Verificar comentario con URL de preview
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
3. **Production Deployment**
|
|
1091
|
+
```bash
|
|
1092
|
+
# Merge PR a main
|
|
1093
|
+
gh pr merge
|
|
1094
|
+
# Verificar deploy a produccion en GitHub Actions
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
4. **Semantic Release**
|
|
1098
|
+
```bash
|
|
1099
|
+
# Hacer commit con conventional commit
|
|
1100
|
+
git commit -m "feat: add new feature"
|
|
1101
|
+
git push origin main
|
|
1102
|
+
# Verificar que se crea release en GitHub
|
|
1103
|
+
```
|
|
1104
|
+
|
|
1105
|
+
5. **Commit Lint**
|
|
1106
|
+
```bash
|
|
1107
|
+
# Intentar commit con mensaje invalido
|
|
1108
|
+
git commit -m "bad message"
|
|
1109
|
+
# Deberia fallar con error de commitlint
|
|
1110
|
+
```
|
|
1111
|
+
</verification>
|
|
1112
|
+
|
|
1113
|
+
<troubleshooting>
|
|
1114
|
+
## Solucion de Problemas
|
|
1115
|
+
|
|
1116
|
+
### Error: "Resource not accessible by integration"
|
|
1117
|
+
```
|
|
1118
|
+
Ir a Settings > Actions > General
|
|
1119
|
+
- Workflow permissions: Read and write permissions
|
|
1120
|
+
- Allow GitHub Actions to create and approve pull requests
|
|
1121
|
+
```
|
|
1122
|
+
|
|
1123
|
+
### Error: "Vercel token expired"
|
|
1124
|
+
```
|
|
1125
|
+
1. Generar nuevo token en Vercel
|
|
1126
|
+
2. Actualizar secret VERCEL_TOKEN en GitHub
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
### Semantic Release no crea release
|
|
1130
|
+
```
|
|
1131
|
+
1. Verificar que commits siguen conventional commits
|
|
1132
|
+
2. Verificar GITHUB_TOKEN tiene permisos
|
|
1133
|
+
3. Verificar .releaserc.json es valido
|
|
1134
|
+
4. Correr: npx semantic-release --dry-run
|
|
1135
|
+
```
|
|
1136
|
+
|
|
1137
|
+
### Preview deploy falla
|
|
1138
|
+
```
|
|
1139
|
+
1. Verificar VERCEL_ORG_ID y VERCEL_PROJECT_ID
|
|
1140
|
+
2. Correr localmente: vercel --debug
|
|
1141
|
+
3. Verificar que proyecto esta linked
|
|
1142
|
+
```
|
|
1143
|
+
|
|
1144
|
+
### Husky hooks no corren
|
|
1145
|
+
```bash
|
|
1146
|
+
# Reinstalar husky
|
|
1147
|
+
rm -rf .husky
|
|
1148
|
+
npm run prepare
|
|
1149
|
+
npx husky add .husky/pre-commit "npx lint-staged"
|
|
1150
|
+
npx husky add .husky/commit-msg "npx --no -- commitlint --edit \$1"
|
|
1151
|
+
```
|
|
1152
|
+
|
|
1153
|
+
### Tests fallan en CI pero pasan local
|
|
1154
|
+
```
|
|
1155
|
+
1. Verificar versiones de Node coinciden
|
|
1156
|
+
2. Verificar variables de entorno
|
|
1157
|
+
3. Limpiar cache: rm -rf node_modules && npm ci
|
|
1158
|
+
4. Verificar que no hay dependencia de orden de tests
|
|
1159
|
+
```
|
|
1160
|
+
</troubleshooting>
|
|
1161
|
+
|
|
1162
|
+
<best_practices>
|
|
1163
|
+
## Mejores Practicas
|
|
1164
|
+
|
|
1165
|
+
### 1. Conventional Commits
|
|
1166
|
+
```
|
|
1167
|
+
feat: nueva funcionalidad (minor version)
|
|
1168
|
+
fix: correccion de bug (patch version)
|
|
1169
|
+
feat!: breaking change (major version)
|
|
1170
|
+
docs: documentacion
|
|
1171
|
+
chore: mantenimiento
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
### 2. Branch Strategy
|
|
1175
|
+
```
|
|
1176
|
+
main <- produccion, protegido
|
|
1177
|
+
develop <- desarrollo, preview
|
|
1178
|
+
feature/* <- nuevas funcionalidades
|
|
1179
|
+
fix/* <- correcciones
|
|
1180
|
+
release/* <- preparacion de release
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
### 3. PR Workflow
|
|
1184
|
+
```
|
|
1185
|
+
1. Crear branch desde develop
|
|
1186
|
+
2. Hacer commits con conventional commits
|
|
1187
|
+
3. Crear PR a develop
|
|
1188
|
+
4. CI corre automaticamente
|
|
1189
|
+
5. Preview deploy se crea
|
|
1190
|
+
6. Codigo review
|
|
1191
|
+
7. Merge a develop
|
|
1192
|
+
8. Cuando listo: merge develop -> main
|
|
1193
|
+
9. Deploy automatico a produccion
|
|
1194
|
+
10. Release automatico con semantic-release
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
### 4. Rollback Strategy
|
|
1198
|
+
```bash
|
|
1199
|
+
# Revertir ultimo deploy
|
|
1200
|
+
vercel rollback
|
|
1201
|
+
|
|
1202
|
+
# O revertir commit en main
|
|
1203
|
+
git revert <commit-hash>
|
|
1204
|
+
git push origin main
|
|
1205
|
+
```
|
|
1206
|
+
</best_practices>
|