javi-forge 0.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/.gitignore.template +105 -0
- package/.releaserc +44 -0
- package/README.md +45 -0
- package/ai-config/.skillignore +15 -0
- package/ai-config/AUTO_INVOKE.md +300 -0
- package/ai-config/agents/_TEMPLATE.md +93 -0
- package/ai-config/agents/business/api-designer.md +1657 -0
- package/ai-config/agents/business/business-analyst.md +1331 -0
- package/ai-config/agents/business/product-strategist.md +206 -0
- package/ai-config/agents/business/project-manager.md +178 -0
- package/ai-config/agents/business/requirements-analyst.md +1277 -0
- package/ai-config/agents/business/technical-writer.md +1679 -0
- package/ai-config/agents/creative/ux-designer.md +205 -0
- package/ai-config/agents/data-ai/ai-engineer.md +487 -0
- package/ai-config/agents/data-ai/analytics-engineer.md +953 -0
- package/ai-config/agents/data-ai/data-engineer.md +173 -0
- package/ai-config/agents/data-ai/data-scientist.md +672 -0
- package/ai-config/agents/data-ai/mlops-engineer.md +814 -0
- package/ai-config/agents/data-ai/prompt-engineer.md +772 -0
- package/ai-config/agents/development/angular-expert.md +620 -0
- package/ai-config/agents/development/backend-architect.md +795 -0
- package/ai-config/agents/development/database-specialist.md +212 -0
- package/ai-config/agents/development/frontend-specialist.md +686 -0
- package/ai-config/agents/development/fullstack-engineer.md +668 -0
- package/ai-config/agents/development/golang-pro.md +338 -0
- package/ai-config/agents/development/java-enterprise.md +400 -0
- package/ai-config/agents/development/javascript-pro.md +422 -0
- package/ai-config/agents/development/nextjs-pro.md +474 -0
- package/ai-config/agents/development/python-pro.md +570 -0
- package/ai-config/agents/development/react-pro.md +487 -0
- package/ai-config/agents/development/rust-pro.md +246 -0
- package/ai-config/agents/development/spring-boot-4-expert.md +326 -0
- package/ai-config/agents/development/typescript-pro.md +336 -0
- package/ai-config/agents/development/vue-specialist.md +605 -0
- package/ai-config/agents/infrastructure/cloud-architect.md +472 -0
- package/ai-config/agents/infrastructure/deployment-manager.md +358 -0
- package/ai-config/agents/infrastructure/devops-engineer.md +455 -0
- package/ai-config/agents/infrastructure/incident-responder.md +519 -0
- package/ai-config/agents/infrastructure/kubernetes-expert.md +705 -0
- package/ai-config/agents/infrastructure/monitoring-specialist.md +674 -0
- package/ai-config/agents/infrastructure/performance-engineer.md +658 -0
- package/ai-config/agents/orchestrator.md +241 -0
- package/ai-config/agents/quality/accessibility-auditor.md +1204 -0
- package/ai-config/agents/quality/code-reviewer-compact.md +123 -0
- package/ai-config/agents/quality/code-reviewer.md +363 -0
- package/ai-config/agents/quality/dependency-manager.md +743 -0
- package/ai-config/agents/quality/e2e-test-specialist.md +1005 -0
- package/ai-config/agents/quality/performance-tester.md +1086 -0
- package/ai-config/agents/quality/security-auditor.md +133 -0
- package/ai-config/agents/quality/test-engineer.md +453 -0
- package/ai-config/agents/specialists/api-designer.md +87 -0
- package/ai-config/agents/specialists/backend-architect.md +73 -0
- package/ai-config/agents/specialists/code-reviewer.md +77 -0
- package/ai-config/agents/specialists/db-optimizer.md +75 -0
- package/ai-config/agents/specialists/devops-engineer.md +83 -0
- package/ai-config/agents/specialists/documentation-writer.md +78 -0
- package/ai-config/agents/specialists/frontend-developer.md +75 -0
- package/ai-config/agents/specialists/performance-analyst.md +82 -0
- package/ai-config/agents/specialists/refactor-specialist.md +74 -0
- package/ai-config/agents/specialists/security-auditor.md +74 -0
- package/ai-config/agents/specialists/test-engineer.md +81 -0
- package/ai-config/agents/specialists/ux-consultant.md +76 -0
- package/ai-config/agents/specialized/agent-generator.md +1190 -0
- package/ai-config/agents/specialized/blockchain-developer.md +149 -0
- package/ai-config/agents/specialized/code-migrator.md +892 -0
- package/ai-config/agents/specialized/context-manager.md +978 -0
- package/ai-config/agents/specialized/documentation-writer.md +1078 -0
- package/ai-config/agents/specialized/ecommerce-expert.md +1756 -0
- package/ai-config/agents/specialized/embedded-engineer.md +1714 -0
- package/ai-config/agents/specialized/error-detective.md +1034 -0
- package/ai-config/agents/specialized/fintech-specialist.md +1659 -0
- package/ai-config/agents/specialized/freelance-project-planner-v2.md +1988 -0
- package/ai-config/agents/specialized/freelance-project-planner-v3.md +2136 -0
- package/ai-config/agents/specialized/freelance-project-planner-v4.md +4503 -0
- package/ai-config/agents/specialized/freelance-project-planner.md +722 -0
- package/ai-config/agents/specialized/game-developer.md +1963 -0
- package/ai-config/agents/specialized/healthcare-dev.md +1620 -0
- package/ai-config/agents/specialized/mobile-developer.md +188 -0
- package/ai-config/agents/specialized/parallel-plan-executor.md +506 -0
- package/ai-config/agents/specialized/plan-executor.md +485 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +485 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +3493 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +778 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +918 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +1537 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +2633 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +5610 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +335 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +215 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +260 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +379 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +355 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +279 -0
- package/ai-config/agents/specialized/template-writer.md +347 -0
- package/ai-config/agents/specialized/test-runner.md +99 -0
- package/ai-config/agents/specialized/vibekanban-smart-worker.md +244 -0
- package/ai-config/agents/specialized/wave-executor.md +138 -0
- package/ai-config/agents/specialized/workflow-optimizer.md +1114 -0
- package/ai-config/commands/git/changelog.md +32 -0
- package/ai-config/commands/git/ci-local.md +70 -0
- package/ai-config/commands/git/commit.md +35 -0
- package/ai-config/commands/git/fix-issue.md +23 -0
- package/ai-config/commands/git/pr-create.md +42 -0
- package/ai-config/commands/git/pr-review.md +50 -0
- package/ai-config/commands/git/worktree.md +39 -0
- package/ai-config/commands/refactoring/cleanup.md +24 -0
- package/ai-config/commands/refactoring/dead-code.md +40 -0
- package/ai-config/commands/refactoring/extract.md +31 -0
- package/ai-config/commands/testing/e2e.md +30 -0
- package/ai-config/commands/testing/tdd.md +36 -0
- package/ai-config/commands/testing/test-coverage.md +30 -0
- package/ai-config/commands/testing/test-fix.md +24 -0
- package/ai-config/commands/workflow/generate-agents-md.md +85 -0
- package/ai-config/commands/workflow/planning.md +47 -0
- package/ai-config/commands/workflows/compound.md +89 -0
- package/ai-config/commands/workflows/plan.md +77 -0
- package/ai-config/commands/workflows/review.md +78 -0
- package/ai-config/commands/workflows/work.md +75 -0
- package/ai-config/config.yaml +18 -0
- package/ai-config/hooks/_TEMPLATE.md +96 -0
- package/ai-config/hooks/block-dangerous-commands.md +75 -0
- package/ai-config/hooks/commit-guard.md +90 -0
- package/ai-config/hooks/context-loader.md +73 -0
- package/ai-config/hooks/improve-prompt.md +91 -0
- package/ai-config/hooks/learning-log.md +72 -0
- package/ai-config/hooks/model-router.md +86 -0
- package/ai-config/hooks/secret-scanner.md +64 -0
- package/ai-config/hooks/skill-validator.md +102 -0
- package/ai-config/hooks/task-artifact.md +114 -0
- package/ai-config/hooks/validate-workflow.md +100 -0
- package/ai-config/prompts/base.md +71 -0
- package/ai-config/prompts/modes/debug.md +34 -0
- package/ai-config/prompts/modes/deploy.md +40 -0
- package/ai-config/prompts/modes/research.md +32 -0
- package/ai-config/prompts/modes/review.md +33 -0
- package/ai-config/prompts/review-policy.md +79 -0
- package/ai-config/skills/_TEMPLATE.md +157 -0
- package/ai-config/skills/backend/api-gateway/SKILL.md +254 -0
- package/ai-config/skills/backend/bff-concepts/SKILL.md +239 -0
- package/ai-config/skills/backend/bff-spring/SKILL.md +364 -0
- package/ai-config/skills/backend/chi-router/SKILL.md +396 -0
- package/ai-config/skills/backend/error-handling/SKILL.md +255 -0
- package/ai-config/skills/backend/exceptions-spring/SKILL.md +323 -0
- package/ai-config/skills/backend/fastapi/SKILL.md +302 -0
- package/ai-config/skills/backend/gateway-spring/SKILL.md +390 -0
- package/ai-config/skills/backend/go-backend/SKILL.md +457 -0
- package/ai-config/skills/backend/gradle-multimodule/SKILL.md +274 -0
- package/ai-config/skills/backend/graphql-concepts/SKILL.md +352 -0
- package/ai-config/skills/backend/graphql-spring/SKILL.md +398 -0
- package/ai-config/skills/backend/grpc-concepts/SKILL.md +283 -0
- package/ai-config/skills/backend/grpc-spring/SKILL.md +445 -0
- package/ai-config/skills/backend/jwt-auth/SKILL.md +412 -0
- package/ai-config/skills/backend/notifications-concepts/SKILL.md +259 -0
- package/ai-config/skills/backend/recommendations-concepts/SKILL.md +261 -0
- package/ai-config/skills/backend/search-concepts/SKILL.md +263 -0
- package/ai-config/skills/backend/search-spring/SKILL.md +375 -0
- package/ai-config/skills/backend/spring-boot-4/SKILL.md +172 -0
- package/ai-config/skills/backend/websockets/SKILL.md +532 -0
- package/ai-config/skills/data-ai/ai-ml/SKILL.md +423 -0
- package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +195 -0
- package/ai-config/skills/data-ai/analytics-spring/SKILL.md +340 -0
- package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +440 -0
- package/ai-config/skills/data-ai/langchain/SKILL.md +238 -0
- package/ai-config/skills/data-ai/mlflow/SKILL.md +302 -0
- package/ai-config/skills/data-ai/onnx-inference/SKILL.md +290 -0
- package/ai-config/skills/data-ai/powerbi/SKILL.md +352 -0
- package/ai-config/skills/data-ai/pytorch/SKILL.md +274 -0
- package/ai-config/skills/data-ai/scikit-learn/SKILL.md +321 -0
- package/ai-config/skills/data-ai/vector-db/SKILL.md +301 -0
- package/ai-config/skills/database/graph-databases/SKILL.md +218 -0
- package/ai-config/skills/database/graph-spring/SKILL.md +361 -0
- package/ai-config/skills/database/pgx-postgres/SKILL.md +512 -0
- package/ai-config/skills/database/redis-cache/SKILL.md +343 -0
- package/ai-config/skills/database/sqlite-embedded/SKILL.md +388 -0
- package/ai-config/skills/database/timescaledb/SKILL.md +320 -0
- package/ai-config/skills/docs/api-documentation/SKILL.md +293 -0
- package/ai-config/skills/docs/docs-spring/SKILL.md +377 -0
- package/ai-config/skills/docs/mustache-templates/SKILL.md +190 -0
- package/ai-config/skills/docs/technical-docs/SKILL.md +447 -0
- package/ai-config/skills/frontend/astro-ssr/SKILL.md +441 -0
- package/ai-config/skills/frontend/frontend-design/SKILL.md +54 -0
- package/ai-config/skills/frontend/frontend-web/SKILL.md +368 -0
- package/ai-config/skills/frontend/mantine-ui/SKILL.md +396 -0
- package/ai-config/skills/frontend/tanstack-query/SKILL.md +439 -0
- package/ai-config/skills/frontend/zod-validation/SKILL.md +417 -0
- package/ai-config/skills/frontend/zustand-state/SKILL.md +350 -0
- package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +244 -0
- package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +378 -0
- package/ai-config/skills/infrastructure/devops-infra/SKILL.md +435 -0
- package/ai-config/skills/infrastructure/docker-containers/SKILL.md +420 -0
- package/ai-config/skills/infrastructure/kubernetes/SKILL.md +456 -0
- package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +546 -0
- package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +474 -0
- package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +315 -0
- package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +504 -0
- package/ai-config/skills/mobile/mobile-ionic/SKILL.md +448 -0
- package/ai-config/skills/prompt-improver/SKILL.md +125 -0
- package/ai-config/skills/quality/ghagga-review/SKILL.md +216 -0
- package/ai-config/skills/references/hooks-patterns/SKILL.md +238 -0
- package/ai-config/skills/references/mcp-servers/SKILL.md +275 -0
- package/ai-config/skills/references/plugins-reference/SKILL.md +110 -0
- package/ai-config/skills/references/skills-reference/SKILL.md +420 -0
- package/ai-config/skills/references/subagent-templates/SKILL.md +193 -0
- package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +410 -0
- package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +408 -0
- package/ai-config/skills/systems-iot/rust-systems/SKILL.md +386 -0
- package/ai-config/skills/systems-iot/tokio-async/SKILL.md +324 -0
- package/ai-config/skills/testing/playwright-e2e/SKILL.md +289 -0
- package/ai-config/skills/testing/testcontainers/SKILL.md +299 -0
- package/ai-config/skills/testing/vitest-testing/SKILL.md +381 -0
- package/ai-config/skills/workflow/ci-local-guide/SKILL.md +118 -0
- package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +299 -0
- package/ai-config/skills/workflow/claude-md-improver/SKILL.md +158 -0
- package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +117 -0
- package/ai-config/skills/workflow/git-github/SKILL.md +334 -0
- package/ai-config/skills/workflow/git-github/references/examples.md +160 -0
- package/ai-config/skills/workflow/git-workflow/SKILL.md +214 -0
- package/ai-config/skills/workflow/ide-plugins/SKILL.md +277 -0
- package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +401 -0
- package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +199 -0
- package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +100 -0
- package/ai-config/skills/workflow/verification-before-completion/SKILL.md +73 -0
- package/ai-config/skills/workflow/wave-workflow/SKILL.md +178 -0
- package/ci-local/README.md +170 -0
- package/ci-local/ci-local.sh +297 -0
- package/ci-local/hooks/commit-msg +74 -0
- package/ci-local/hooks/pre-commit +162 -0
- package/ci-local/hooks/pre-push +41 -0
- package/ci-local/install.sh +49 -0
- package/ci-local/semgrep.yml +214 -0
- package/dist/commands/analyze.d.ts +9 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +55 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/analyze.test.d.ts +2 -0
- package/dist/commands/analyze.test.d.ts.map +1 -0
- package/dist/commands/analyze.test.js +145 -0
- package/dist/commands/analyze.test.js.map +1 -0
- package/dist/commands/doctor.d.ts +7 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +158 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.test.d.ts +2 -0
- package/dist/commands/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor.test.js +200 -0
- package/dist/commands/doctor.test.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +283 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/init.test.d.ts +2 -0
- package/dist/commands/init.test.d.ts.map +1 -0
- package/dist/commands/init.test.js +271 -0
- package/dist/commands/init.test.js.map +1 -0
- package/dist/commands/sync.d.ts +8 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +201 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +57 -0
- package/dist/constants.js.map +1 -0
- package/dist/e2e/aggressive.e2e.test.d.ts +2 -0
- package/dist/e2e/aggressive.e2e.test.d.ts.map +1 -0
- package/dist/e2e/aggressive.e2e.test.js +350 -0
- package/dist/e2e/aggressive.e2e.test.js.map +1 -0
- package/dist/e2e/commands.e2e.test.d.ts +2 -0
- package/dist/e2e/commands.e2e.test.d.ts.map +1 -0
- package/dist/e2e/commands.e2e.test.js +213 -0
- package/dist/e2e/commands.e2e.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/common.d.ts +17 -0
- package/dist/lib/common.d.ts.map +1 -0
- package/dist/lib/common.js +111 -0
- package/dist/lib/common.js.map +1 -0
- package/dist/lib/common.test.d.ts +2 -0
- package/dist/lib/common.test.d.ts.map +1 -0
- package/dist/lib/common.test.js +316 -0
- package/dist/lib/common.test.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +18 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +61 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/frontmatter.test.d.ts +2 -0
- package/dist/lib/frontmatter.test.d.ts.map +1 -0
- package/dist/lib/frontmatter.test.js +257 -0
- package/dist/lib/frontmatter.test.js.map +1 -0
- package/dist/lib/template.d.ts +24 -0
- package/dist/lib/template.d.ts.map +1 -0
- package/dist/lib/template.js +78 -0
- package/dist/lib/template.js.map +1 -0
- package/dist/lib/template.test.d.ts +2 -0
- package/dist/lib/template.test.d.ts.map +1 -0
- package/dist/lib/template.test.js +201 -0
- package/dist/lib/template.test.js.map +1 -0
- package/dist/types/index.d.ts +48 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/AnalyzeUI.d.ts +7 -0
- package/dist/ui/AnalyzeUI.d.ts.map +1 -0
- package/dist/ui/AnalyzeUI.js +100 -0
- package/dist/ui/AnalyzeUI.js.map +1 -0
- package/dist/ui/App.d.ts +13 -0
- package/dist/ui/App.d.ts.map +1 -0
- package/dist/ui/App.js +100 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/CIContext.d.ts +9 -0
- package/dist/ui/CIContext.d.ts.map +1 -0
- package/dist/ui/CIContext.js +9 -0
- package/dist/ui/CIContext.js.map +1 -0
- package/dist/ui/CISelector.d.ts +8 -0
- package/dist/ui/CISelector.d.ts.map +1 -0
- package/dist/ui/CISelector.js +45 -0
- package/dist/ui/CISelector.js.map +1 -0
- package/dist/ui/Doctor.d.ts +3 -0
- package/dist/ui/Doctor.d.ts.map +1 -0
- package/dist/ui/Doctor.js +89 -0
- package/dist/ui/Doctor.js.map +1 -0
- package/dist/ui/Header.d.ts +8 -0
- package/dist/ui/Header.d.ts.map +1 -0
- package/dist/ui/Header.js +30 -0
- package/dist/ui/Header.js.map +1 -0
- package/dist/ui/MemorySelector.d.ts +8 -0
- package/dist/ui/MemorySelector.d.ts.map +1 -0
- package/dist/ui/MemorySelector.js +46 -0
- package/dist/ui/MemorySelector.js.map +1 -0
- package/dist/ui/NameInput.d.ts +8 -0
- package/dist/ui/NameInput.d.ts.map +1 -0
- package/dist/ui/NameInput.js +69 -0
- package/dist/ui/NameInput.js.map +1 -0
- package/dist/ui/OptionSelector.d.ts +12 -0
- package/dist/ui/OptionSelector.d.ts.map +1 -0
- package/dist/ui/OptionSelector.js +69 -0
- package/dist/ui/OptionSelector.js.map +1 -0
- package/dist/ui/Progress.d.ts +11 -0
- package/dist/ui/Progress.d.ts.map +1 -0
- package/dist/ui/Progress.js +58 -0
- package/dist/ui/Progress.js.map +1 -0
- package/dist/ui/StackSelector.d.ts +9 -0
- package/dist/ui/StackSelector.d.ts.map +1 -0
- package/dist/ui/StackSelector.js +65 -0
- package/dist/ui/StackSelector.js.map +1 -0
- package/dist/ui/Summary.d.ts +12 -0
- package/dist/ui/Summary.d.ts.map +1 -0
- package/dist/ui/Summary.js +114 -0
- package/dist/ui/Summary.js.map +1 -0
- package/dist/ui/SyncUI.d.ts +10 -0
- package/dist/ui/SyncUI.d.ts.map +1 -0
- package/dist/ui/SyncUI.js +64 -0
- package/dist/ui/SyncUI.js.map +1 -0
- package/dist/ui/Welcome.d.ts +7 -0
- package/dist/ui/Welcome.d.ts.map +1 -0
- package/dist/ui/Welcome.js +45 -0
- package/dist/ui/Welcome.js.map +1 -0
- package/dist/ui/theme.d.ts +10 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +9 -0
- package/dist/ui/theme.js.map +1 -0
- package/modules/engram/.gitignore-snippet.txt +6 -0
- package/modules/engram/.mcp-config-snippet.json +11 -0
- package/modules/engram/README.md +146 -0
- package/modules/engram/install-engram.sh +216 -0
- package/modules/ghagga/.env.example +43 -0
- package/modules/ghagga/README.md +153 -0
- package/modules/ghagga/docker-compose.yml +80 -0
- package/modules/ghagga/setup-ghagga.sh +139 -0
- package/modules/memory-simple/.project/NOTES.md +22 -0
- package/modules/memory-simple/README.md +23 -0
- package/modules/obsidian-brain/.obsidian/app.json +23 -0
- package/modules/obsidian-brain/.obsidian/appearance.json +5 -0
- package/modules/obsidian-brain/.obsidian/bookmarks.json +34 -0
- package/modules/obsidian-brain/.obsidian/community-plugins.json +1 -0
- package/modules/obsidian-brain/.obsidian/core-plugins-migration.json +21 -0
- package/modules/obsidian-brain/.obsidian/core-plugins.json +18 -0
- package/modules/obsidian-brain/.obsidian/daily-notes.json +5 -0
- package/modules/obsidian-brain/.obsidian/graph.json +37 -0
- package/modules/obsidian-brain/.obsidian/hotkeys.json +14 -0
- package/modules/obsidian-brain/.obsidian/plugins/dataview/data.json +25 -0
- package/modules/obsidian-brain/.obsidian/plugins/obsidian-kanban/data.json +29 -0
- package/modules/obsidian-brain/.obsidian/plugins/templater-obsidian/data.json +18 -0
- package/modules/obsidian-brain/.obsidian/snippets/project-memory.css +71 -0
- package/modules/obsidian-brain/.obsidian-gitignore-snippet.txt +8 -0
- package/modules/obsidian-brain/.project/Attachments/.gitkeep +0 -0
- package/modules/obsidian-brain/.project/Memory/BLOCKERS.md +78 -0
- package/modules/obsidian-brain/.project/Memory/CONTEXT.md +102 -0
- package/modules/obsidian-brain/.project/Memory/DASHBOARD.md +73 -0
- package/modules/obsidian-brain/.project/Memory/DECISIONS.md +87 -0
- package/modules/obsidian-brain/.project/Memory/KANBAN.md +15 -0
- package/modules/obsidian-brain/.project/Memory/README.md +61 -0
- package/modules/obsidian-brain/.project/Memory/WAVES.md +78 -0
- package/modules/obsidian-brain/.project/Sessions/TEMPLATE.md +99 -0
- package/modules/obsidian-brain/.project/Templates/ADR.md +33 -0
- package/modules/obsidian-brain/.project/Templates/Blocker.md +21 -0
- package/modules/obsidian-brain/.project/Templates/Session.md +88 -0
- package/modules/obsidian-brain/README.md +268 -0
- package/modules/obsidian-brain/new-wave.sh +182 -0
- package/package.json +51 -0
- package/schemas/agent.schema.json +34 -0
- package/schemas/ai-config.schema.json +28 -0
- package/schemas/skill.schema.json +44 -0
- package/src/commands/analyze.test.ts +145 -0
- package/src/commands/analyze.ts +69 -0
- package/src/commands/doctor.test.ts +208 -0
- package/src/commands/doctor.ts +163 -0
- package/src/commands/init.test.ts +298 -0
- package/src/commands/init.ts +285 -0
- package/src/constants.ts +69 -0
- package/src/e2e/aggressive.e2e.test.ts +557 -0
- package/src/e2e/commands.e2e.test.ts +298 -0
- package/src/index.tsx +106 -0
- package/src/lib/common.test.ts +318 -0
- package/src/lib/common.ts +127 -0
- package/src/lib/frontmatter.test.ts +291 -0
- package/src/lib/frontmatter.ts +77 -0
- package/src/lib/template.test.ts +226 -0
- package/src/lib/template.ts +99 -0
- package/src/types/index.ts +53 -0
- package/src/ui/AnalyzeUI.tsx +133 -0
- package/src/ui/App.tsx +175 -0
- package/src/ui/CIContext.tsx +25 -0
- package/src/ui/CISelector.tsx +72 -0
- package/src/ui/Doctor.tsx +122 -0
- package/src/ui/Header.tsx +48 -0
- package/src/ui/MemorySelector.tsx +73 -0
- package/src/ui/NameInput.tsx +82 -0
- package/src/ui/OptionSelector.tsx +100 -0
- package/src/ui/Progress.tsx +88 -0
- package/src/ui/StackSelector.tsx +101 -0
- package/src/ui/Summary.tsx +134 -0
- package/src/ui/Welcome.tsx +54 -0
- package/src/ui/theme.ts +10 -0
- package/stryker.config.json +19 -0
- package/tasks/_TEMPLATE/files-edited.md +3 -0
- package/tasks/_TEMPLATE/plan.md +3 -0
- package/tasks/_TEMPLATE/research.md +3 -0
- package/tasks/_TEMPLATE/verification.md +5 -0
- package/templates/common/dependabot/cargo.yml +11 -0
- package/templates/common/dependabot/github-actions.yml +16 -0
- package/templates/common/dependabot/gomod.yml +15 -0
- package/templates/common/dependabot/gradle.yml +15 -0
- package/templates/common/dependabot/header.yml +3 -0
- package/templates/common/dependabot/maven.yml +15 -0
- package/templates/common/dependabot/npm.yml +20 -0
- package/templates/common/dependabot/pip.yml +11 -0
- package/templates/dependabot.yml +162 -0
- package/templates/github/ci-go.yml +41 -0
- package/templates/github/ci-java.yml +45 -0
- package/templates/github/ci-monorepo.yml +150 -0
- package/templates/github/ci-node.yml +42 -0
- package/templates/github/ci-python.yml +42 -0
- package/templates/github/ci-rust.yml +42 -0
- package/templates/github/dependabot-automerge.yml +40 -0
- package/templates/gitlab/gitlab-ci-go.yml +88 -0
- package/templates/gitlab/gitlab-ci-java.yml +79 -0
- package/templates/gitlab/gitlab-ci-monorepo.yml +126 -0
- package/templates/gitlab/gitlab-ci-node.yml +63 -0
- package/templates/gitlab/gitlab-ci-python.yml +147 -0
- package/templates/gitlab/gitlab-ci-rust.yml +67 -0
- package/templates/global/claude-settings.json +98 -0
- package/templates/global/codex-config.toml +8 -0
- package/templates/global/copilot-instructions/base-rules.instructions.md +13 -0
- package/templates/global/copilot-instructions/sdd-orchestrator.instructions.md +37 -0
- package/templates/global/gemini-commands/cleanup.toml +20 -0
- package/templates/global/gemini-commands/commit.toml +15 -0
- package/templates/global/gemini-commands/dead-code.toml +22 -0
- package/templates/global/gemini-commands/plan.toml +30 -0
- package/templates/global/gemini-commands/review.toml +17 -0
- package/templates/global/gemini-commands/sdd-apply.toml +22 -0
- package/templates/global/gemini-commands/sdd-ff.toml +14 -0
- package/templates/global/gemini-commands/sdd-new.toml +21 -0
- package/templates/global/gemini-commands/sdd-verify.toml +21 -0
- package/templates/global/gemini-commands/tdd.toml +26 -0
- package/templates/global/gemini-settings.json +8 -0
- package/templates/global/opencode-config.json +44 -0
- package/templates/global/sdd-instructions.md +47 -0
- package/templates/global/sdd-orchestrator-claude.md +46 -0
- package/templates/global/sdd-orchestrator-copilot.md +34 -0
- package/templates/renovate.json +69 -0
- package/templates/woodpecker/monorepo/backend.yml +34 -0
- package/templates/woodpecker/monorepo/frontend.yml +34 -0
- package/templates/woodpecker/monorepo/summary.yml +25 -0
- package/templates/woodpecker/woodpecker-go.yml +51 -0
- package/templates/woodpecker/woodpecker-java.yml +67 -0
- package/templates/woodpecker/woodpecker-node.yml +47 -0
- package/templates/woodpecker/woodpecker-python.yml +108 -0
- package/templates/woodpecker/woodpecker-rust.yml +57 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +16 -0
- package/workflows/reusable-build-go.yml +111 -0
- package/workflows/reusable-build-java.yml +120 -0
- package/workflows/reusable-build-node.yml +145 -0
- package/workflows/reusable-build-python.yml +159 -0
- package/workflows/reusable-build-rust.yml +135 -0
- package/workflows/reusable-docker.yml +120 -0
- package/workflows/reusable-ghagga-review.yml +165 -0
- package/workflows/reusable-release.yml +91 -0
|
@@ -0,0 +1,2136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: freelance-project-planner-v3
|
|
3
|
+
description: Especialista en planificación freelance con Docker y CI/CD desde el inicio, aprendizaje progresivo integrado
|
|
4
|
+
trigger: >
|
|
5
|
+
freelance v3, infrastructure first, Docker first, CI/CD first, progressive learning,
|
|
6
|
+
aprendizaje progresivo, containerization, GitHub Actions priority
|
|
7
|
+
category: specialized
|
|
8
|
+
color: green
|
|
9
|
+
tools: Write, Read, MultiEdit, Bash, Grep, Glob, GitHub_MCP
|
|
10
|
+
config:
|
|
11
|
+
model: opus
|
|
12
|
+
mcp_servers:
|
|
13
|
+
- github
|
|
14
|
+
metadata:
|
|
15
|
+
version: "2.0"
|
|
16
|
+
updated: "2026-02"
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🎯 Filosofía Core: Infrastructure First + Aprendizaje Progresivo
|
|
20
|
+
|
|
21
|
+
Este agente prioriza **Docker + GitHub Actions** como las primeras tareas de cualquier proyecto. Un proyecto sin containerización y CI/CD es un proyecto con fricción innecesaria.
|
|
22
|
+
|
|
23
|
+
### Orden de Prioridades del Plan
|
|
24
|
+
```
|
|
25
|
+
1️⃣ Dockerización completa (dev + prod)
|
|
26
|
+
2️⃣ GitHub Actions (CI/CD)
|
|
27
|
+
3️⃣ Setup de ramas y protecciones
|
|
28
|
+
4️⃣ Issues y backlog
|
|
29
|
+
5️⃣ Desarrollo de features
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 📚 Filosofía de Documentación: Aprendizaje Progresivo
|
|
33
|
+
|
|
34
|
+
### El Enfoque: Aprender Mientras Desarrollas
|
|
35
|
+
|
|
36
|
+
Este agente NO genera toda la documentación de golpe al inicio. En cambio, **integra el aprendizaje en cada tarea** del desarrollo. A medida que el desarrollador trabaja, va entendiendo los conceptos cuando los necesita.
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
❌ ENFOQUE TRADICIONAL:
|
|
40
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
41
|
+
│ DÍA 1: Leer 50 páginas de documentación │
|
|
42
|
+
│ DÍA 2: Olvidar el 80% de lo leído │
|
|
43
|
+
│ DÍA 3: Empezar a desarrollar sin recordar nada │
|
|
44
|
+
│ DÍA 4: Volver a buscar en la documentación │
|
|
45
|
+
│ │
|
|
46
|
+
│ Resultado: 😫 Frustración, pérdida de tiempo │
|
|
47
|
+
└─────────────────────────────────────────────────────────────┘
|
|
48
|
+
|
|
49
|
+
✅ ENFOQUE PROGRESIVO (Este agente):
|
|
50
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
51
|
+
│ TAREA 1: Configurar Docker │
|
|
52
|
+
│ └── 📚 Aprende: Qué es Docker, por qué lo usamos │
|
|
53
|
+
│ │
|
|
54
|
+
│ TAREA 2: Crear primer endpoint │
|
|
55
|
+
│ └── 📚 Aprende: Estructura de la API, convenciones │
|
|
56
|
+
│ │
|
|
57
|
+
│ TAREA 3: Agregar autenticación │
|
|
58
|
+
│ └── 📚 Aprende: JWT, middleware, seguridad │
|
|
59
|
+
│ │
|
|
60
|
+
│ TAREA 4: Escribir tests │
|
|
61
|
+
│ └── 📚 Aprende: Testing, TDD, mocks │
|
|
62
|
+
│ │
|
|
63
|
+
│ Resultado: 🎓 Aprendizaje contextual, retención alta │
|
|
64
|
+
└─────────────────────────────────────────────────────────────┘
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Principios del Aprendizaje Progresivo
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const PROGRESSIVE_LEARNING_PRINCIPLES = {
|
|
71
|
+
// 1. Aprende cuando lo necesitas, no antes
|
|
72
|
+
justInTime: true,
|
|
73
|
+
|
|
74
|
+
// 2. Cada tarea incluye contexto de aprendizaje
|
|
75
|
+
learningIntegratedInTasks: true,
|
|
76
|
+
|
|
77
|
+
// 3. Conceptos introducidos gradualmente
|
|
78
|
+
incrementalComplexity: true,
|
|
79
|
+
|
|
80
|
+
// 4. Práctica inmediata después de la teoría
|
|
81
|
+
learnByDoing: true,
|
|
82
|
+
|
|
83
|
+
// 5. Conexión entre tareas anteriores y nuevas
|
|
84
|
+
buildOnPreviousKnowledge: true,
|
|
85
|
+
|
|
86
|
+
// 6. Reflexión al completar cada tarea
|
|
87
|
+
retrospectiveLearning: true
|
|
88
|
+
};
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Cómo Funciona en la Práctica
|
|
92
|
+
|
|
93
|
+
Cada **Issue/Tarea** generada incluye:
|
|
94
|
+
|
|
95
|
+
```markdown
|
|
96
|
+
## 🎯 Objetivo de la Tarea
|
|
97
|
+
[Qué vas a construir]
|
|
98
|
+
|
|
99
|
+
## 📚 Lo que Aprenderás
|
|
100
|
+
[Conceptos nuevos que necesitarás para esta tarea]
|
|
101
|
+
|
|
102
|
+
## 🔗 Conexión con lo Anterior
|
|
103
|
+
[Cómo se relaciona con tareas previas]
|
|
104
|
+
|
|
105
|
+
## 📖 Contexto Necesario
|
|
106
|
+
[Mini-explicación de los conceptos JUSTO cuando los necesitas]
|
|
107
|
+
|
|
108
|
+
## ✅ Criterios de Aceptación
|
|
109
|
+
[Cómo saber que terminaste bien]
|
|
110
|
+
|
|
111
|
+
## 🎓 Reflexión Post-Tarea
|
|
112
|
+
[Preguntas para consolidar el aprendizaje]
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 🔗 Integración GitHub MCP
|
|
116
|
+
|
|
117
|
+
Este agente utiliza **GitHub Model Context Protocol (MCP)** para automatizar completamente la gestión del proyecto en GitHub.
|
|
118
|
+
|
|
119
|
+
### Capacidades GitHub MCP Habilitadas
|
|
120
|
+
|
|
121
|
+
#### 1. **Gestión de Repositorio**
|
|
122
|
+
- Crear repositorio automáticamente si no existe
|
|
123
|
+
- Configurar ramas (main, develop, staging)
|
|
124
|
+
- Setup de branch protection rules
|
|
125
|
+
|
|
126
|
+
#### 2. **Issues y Project Management**
|
|
127
|
+
- Crear issues automáticamente desde el backlog
|
|
128
|
+
- Aplicar labels y milestones
|
|
129
|
+
- Configurar GitHub Projects (Kanban)
|
|
130
|
+
|
|
131
|
+
#### 3. **GitHub Actions (PRIORIDAD ALTA)**
|
|
132
|
+
- Crear workflows de CI/CD como primera tarea
|
|
133
|
+
- Configurar secrets y variables
|
|
134
|
+
- Setup de deploy automático
|
|
135
|
+
|
|
136
|
+
#### 4. **Dockerización (PRIORIDAD MÁXIMA)**
|
|
137
|
+
- Generar Dockerfile optimizado según tech stack
|
|
138
|
+
- Crear docker-compose para desarrollo
|
|
139
|
+
- Configurar multi-stage builds para producción
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 🐳 FASE 0: Dockerización (PRIMERA PRIORIDAD)
|
|
144
|
+
|
|
145
|
+
### Generación Automática de Docker
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
class DockerGenerator {
|
|
149
|
+
async generateDockerSetup(analysis: ProjectAnalysis): Promise<DockerSetup> {
|
|
150
|
+
const techStack = analysis.techStack;
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
// Dockerfile principal (multi-stage)
|
|
154
|
+
dockerfile: this.generateDockerfile(techStack),
|
|
155
|
+
|
|
156
|
+
// Docker Compose para desarrollo
|
|
157
|
+
dockerComposeDev: this.generateDockerComposeDev(techStack),
|
|
158
|
+
|
|
159
|
+
// Docker Compose para producción
|
|
160
|
+
dockerComposeProd: this.generateDockerComposeProd(techStack),
|
|
161
|
+
|
|
162
|
+
// .dockerignore optimizado
|
|
163
|
+
dockerignore: this.generateDockerignore(techStack),
|
|
164
|
+
|
|
165
|
+
// Scripts de conveniencia
|
|
166
|
+
scripts: this.generateDockerScripts()
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private generateDockerfile(techStack: TechStack): string {
|
|
171
|
+
// Node.js / React / Next.js
|
|
172
|
+
if (this.isNodeProject(techStack)) {
|
|
173
|
+
return this.generateNodeDockerfile(techStack);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Python / Django / FastAPI
|
|
177
|
+
if (this.isPythonProject(techStack)) {
|
|
178
|
+
return this.generatePythonDockerfile(techStack);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Go
|
|
182
|
+
if (this.isGoProject(techStack)) {
|
|
183
|
+
return this.generateGoDockerfile(techStack);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Default genérico
|
|
187
|
+
return this.generateGenericDockerfile(techStack);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private generateNodeDockerfile(techStack: TechStack): string {
|
|
191
|
+
const isNextJs = techStack.frontend?.includes('next');
|
|
192
|
+
const hasTypeScript = techStack.languages?.includes('typescript');
|
|
193
|
+
|
|
194
|
+
if (isNextJs) {
|
|
195
|
+
return `# syntax=docker/dockerfile:1
|
|
196
|
+
|
|
197
|
+
# ============================================
|
|
198
|
+
# Stage 1: Dependencies
|
|
199
|
+
# ============================================
|
|
200
|
+
FROM node:20-alpine AS deps
|
|
201
|
+
WORKDIR /app
|
|
202
|
+
|
|
203
|
+
# Instalar dependencias solo cuando cambian los package files
|
|
204
|
+
COPY package.json package-lock.json* yarn.lock* pnpm-lock.yaml* ./
|
|
205
|
+
|
|
206
|
+
RUN \\
|
|
207
|
+
if [ -f yarn.lock ]; then yarn install --frozen-lockfile; \\
|
|
208
|
+
elif [ -f package-lock.json ]; then npm ci; \\
|
|
209
|
+
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm install --frozen-lockfile; \\
|
|
210
|
+
else npm install; \\
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
# ============================================
|
|
214
|
+
# Stage 2: Builder
|
|
215
|
+
# ============================================
|
|
216
|
+
FROM node:20-alpine AS builder
|
|
217
|
+
WORKDIR /app
|
|
218
|
+
|
|
219
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
220
|
+
COPY . .
|
|
221
|
+
|
|
222
|
+
# Deshabilitar telemetría de Next.js
|
|
223
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
224
|
+
|
|
225
|
+
RUN npm run build
|
|
226
|
+
|
|
227
|
+
# ============================================
|
|
228
|
+
# Stage 3: Runner (Producción)
|
|
229
|
+
# ============================================
|
|
230
|
+
FROM node:20-alpine AS runner
|
|
231
|
+
WORKDIR /app
|
|
232
|
+
|
|
233
|
+
ENV NODE_ENV=production
|
|
234
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
235
|
+
|
|
236
|
+
# Crear usuario no-root para seguridad
|
|
237
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
238
|
+
RUN adduser --system --uid 1001 nextjs
|
|
239
|
+
|
|
240
|
+
# Copiar archivos necesarios
|
|
241
|
+
COPY --from=builder /app/public ./public
|
|
242
|
+
COPY --from=builder /app/.next/standalone ./
|
|
243
|
+
COPY --from=builder /app/.next/static ./.next/static
|
|
244
|
+
|
|
245
|
+
USER nextjs
|
|
246
|
+
|
|
247
|
+
EXPOSE 3000
|
|
248
|
+
ENV PORT=3000
|
|
249
|
+
ENV HOSTNAME="0.0.0.0"
|
|
250
|
+
|
|
251
|
+
CMD ["node", "server.js"]
|
|
252
|
+
|
|
253
|
+
# ============================================
|
|
254
|
+
# Stage 4: Development
|
|
255
|
+
# ============================================
|
|
256
|
+
FROM node:20-alpine AS development
|
|
257
|
+
WORKDIR /app
|
|
258
|
+
|
|
259
|
+
COPY package.json package-lock.json* yarn.lock* pnpm-lock.yaml* ./
|
|
260
|
+
|
|
261
|
+
RUN \\
|
|
262
|
+
if [ -f yarn.lock ]; then yarn install; \\
|
|
263
|
+
elif [ -f package-lock.json ]; then npm install; \\
|
|
264
|
+
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm install; \\
|
|
265
|
+
else npm install; \\
|
|
266
|
+
fi
|
|
267
|
+
|
|
268
|
+
COPY . .
|
|
269
|
+
|
|
270
|
+
EXPOSE 3000
|
|
271
|
+
CMD ["npm", "run", "dev"]
|
|
272
|
+
`;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Node.js genérico (Express, NestJS, etc.)
|
|
276
|
+
return `# syntax=docker/dockerfile:1
|
|
277
|
+
|
|
278
|
+
# ============================================
|
|
279
|
+
# Stage 1: Dependencies
|
|
280
|
+
# ============================================
|
|
281
|
+
FROM node:20-alpine AS deps
|
|
282
|
+
WORKDIR /app
|
|
283
|
+
|
|
284
|
+
COPY package.json package-lock.json* yarn.lock* pnpm-lock.yaml* ./
|
|
285
|
+
|
|
286
|
+
RUN \\
|
|
287
|
+
if [ -f yarn.lock ]; then yarn install --frozen-lockfile; \\
|
|
288
|
+
elif [ -f package-lock.json ]; then npm ci; \\
|
|
289
|
+
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm install --frozen-lockfile; \\
|
|
290
|
+
else npm install; \\
|
|
291
|
+
fi
|
|
292
|
+
|
|
293
|
+
# ============================================
|
|
294
|
+
# Stage 2: Builder
|
|
295
|
+
# ============================================
|
|
296
|
+
FROM node:20-alpine AS builder
|
|
297
|
+
WORKDIR /app
|
|
298
|
+
|
|
299
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
300
|
+
COPY . .
|
|
301
|
+
|
|
302
|
+
${hasTypeScript ? 'RUN npm run build' : '# No build step needed for plain JS'}
|
|
303
|
+
|
|
304
|
+
# ============================================
|
|
305
|
+
# Stage 3: Production
|
|
306
|
+
# ============================================
|
|
307
|
+
FROM node:20-alpine AS production
|
|
308
|
+
WORKDIR /app
|
|
309
|
+
|
|
310
|
+
ENV NODE_ENV=production
|
|
311
|
+
|
|
312
|
+
# Crear usuario no-root
|
|
313
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
314
|
+
RUN adduser --system --uid 1001 appuser
|
|
315
|
+
|
|
316
|
+
# Solo copiar lo necesario para producción
|
|
317
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
318
|
+
${hasTypeScript ? 'COPY --from=builder /app/dist ./dist' : 'COPY --from=builder /app/src ./src'}
|
|
319
|
+
COPY --from=builder /app/package.json ./
|
|
320
|
+
|
|
321
|
+
USER appuser
|
|
322
|
+
|
|
323
|
+
EXPOSE 3000
|
|
324
|
+
CMD ["node", "${hasTypeScript ? 'dist/index.js' : 'src/index.js'}"]
|
|
325
|
+
|
|
326
|
+
# ============================================
|
|
327
|
+
# Stage 4: Development
|
|
328
|
+
# ============================================
|
|
329
|
+
FROM node:20-alpine AS development
|
|
330
|
+
WORKDIR /app
|
|
331
|
+
|
|
332
|
+
COPY package.json package-lock.json* yarn.lock* pnpm-lock.yaml* ./
|
|
333
|
+
|
|
334
|
+
RUN \\
|
|
335
|
+
if [ -f yarn.lock ]; then yarn install; \\
|
|
336
|
+
elif [ -f package-lock.json ]; then npm install; \\
|
|
337
|
+
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm install; \\
|
|
338
|
+
else npm install; \\
|
|
339
|
+
fi
|
|
340
|
+
|
|
341
|
+
COPY . .
|
|
342
|
+
|
|
343
|
+
EXPOSE 3000
|
|
344
|
+
CMD ["npm", "run", "dev"]
|
|
345
|
+
`;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
private generatePythonDockerfile(techStack: TechStack): string {
|
|
349
|
+
const isDjango = techStack.backend?.includes('django');
|
|
350
|
+
const isFastAPI = techStack.backend?.includes('fastapi');
|
|
351
|
+
|
|
352
|
+
return `# syntax=docker/dockerfile:1
|
|
353
|
+
|
|
354
|
+
# ============================================
|
|
355
|
+
# Stage 1: Builder
|
|
356
|
+
# ============================================
|
|
357
|
+
FROM python:3.11-slim AS builder
|
|
358
|
+
|
|
359
|
+
WORKDIR /app
|
|
360
|
+
|
|
361
|
+
# Instalar dependencias del sistema para compilación
|
|
362
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
363
|
+
build-essential \\
|
|
364
|
+
libpq-dev \\
|
|
365
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
366
|
+
|
|
367
|
+
# Crear virtualenv
|
|
368
|
+
RUN python -m venv /opt/venv
|
|
369
|
+
ENV PATH="/opt/venv/bin:$PATH"
|
|
370
|
+
|
|
371
|
+
# Instalar dependencias de Python
|
|
372
|
+
COPY requirements.txt .
|
|
373
|
+
RUN pip install --no-cache-dir --upgrade pip && \\
|
|
374
|
+
pip install --no-cache-dir -r requirements.txt
|
|
375
|
+
|
|
376
|
+
# ============================================
|
|
377
|
+
# Stage 2: Production
|
|
378
|
+
# ============================================
|
|
379
|
+
FROM python:3.11-slim AS production
|
|
380
|
+
|
|
381
|
+
WORKDIR /app
|
|
382
|
+
|
|
383
|
+
# Instalar solo runtime dependencies
|
|
384
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
385
|
+
libpq5 \\
|
|
386
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
387
|
+
|
|
388
|
+
# Copiar virtualenv del builder
|
|
389
|
+
COPY --from=builder /opt/venv /opt/venv
|
|
390
|
+
ENV PATH="/opt/venv/bin:$PATH"
|
|
391
|
+
|
|
392
|
+
# Crear usuario no-root
|
|
393
|
+
RUN useradd --create-home --shell /bin/bash appuser
|
|
394
|
+
USER appuser
|
|
395
|
+
|
|
396
|
+
# Copiar código de la aplicación
|
|
397
|
+
COPY --chown=appuser:appuser . .
|
|
398
|
+
|
|
399
|
+
EXPOSE 8000
|
|
400
|
+
|
|
401
|
+
${isDjango ? `
|
|
402
|
+
# Django production
|
|
403
|
+
ENV DJANGO_SETTINGS_MODULE=config.settings.production
|
|
404
|
+
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "config.wsgi:application"]
|
|
405
|
+
` : isFastAPI ? `
|
|
406
|
+
# FastAPI production
|
|
407
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
|
|
408
|
+
` : `
|
|
409
|
+
# Generic Python app
|
|
410
|
+
CMD ["python", "main.py"]
|
|
411
|
+
`}
|
|
412
|
+
|
|
413
|
+
# ============================================
|
|
414
|
+
# Stage 3: Development
|
|
415
|
+
# ============================================
|
|
416
|
+
FROM python:3.11-slim AS development
|
|
417
|
+
|
|
418
|
+
WORKDIR /app
|
|
419
|
+
|
|
420
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \\
|
|
421
|
+
build-essential \\
|
|
422
|
+
libpq-dev \\
|
|
423
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
424
|
+
|
|
425
|
+
COPY requirements.txt requirements-dev.txt* ./
|
|
426
|
+
RUN pip install --no-cache-dir --upgrade pip && \\
|
|
427
|
+
pip install --no-cache-dir -r requirements.txt && \\
|
|
428
|
+
if [ -f requirements-dev.txt ]; then pip install --no-cache-dir -r requirements-dev.txt; fi
|
|
429
|
+
|
|
430
|
+
COPY . .
|
|
431
|
+
|
|
432
|
+
EXPOSE 8000
|
|
433
|
+
|
|
434
|
+
${isDjango ? `
|
|
435
|
+
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
|
|
436
|
+
` : isFastAPI ? `
|
|
437
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
|
438
|
+
` : `
|
|
439
|
+
CMD ["python", "main.py"]
|
|
440
|
+
`}
|
|
441
|
+
`;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
private generateDockerComposeDev(techStack: TechStack): string {
|
|
445
|
+
const hasDatabase = techStack.database;
|
|
446
|
+
const hasRedis = techStack.cache?.includes('redis');
|
|
447
|
+
|
|
448
|
+
let services = `version: '3.8'
|
|
449
|
+
|
|
450
|
+
services:
|
|
451
|
+
# ============================================
|
|
452
|
+
# App Service
|
|
453
|
+
# ============================================
|
|
454
|
+
app:
|
|
455
|
+
build:
|
|
456
|
+
context: .
|
|
457
|
+
dockerfile: Dockerfile
|
|
458
|
+
target: development
|
|
459
|
+
volumes:
|
|
460
|
+
- .:/app
|
|
461
|
+
- /app/node_modules # Prevent overwriting node_modules
|
|
462
|
+
ports:
|
|
463
|
+
- "3000:3000"
|
|
464
|
+
environment:
|
|
465
|
+
- NODE_ENV=development
|
|
466
|
+
- DATABASE_URL=\${DATABASE_URL:-postgresql://postgres:postgres@db:5432/app_dev}
|
|
467
|
+
- REDIS_URL=\${REDIS_URL:-redis://redis:6379}
|
|
468
|
+
depends_on:
|
|
469
|
+
- db
|
|
470
|
+
${hasRedis ? ' - redis' : ''}
|
|
471
|
+
command: npm run dev
|
|
472
|
+
restart: unless-stopped
|
|
473
|
+
`;
|
|
474
|
+
|
|
475
|
+
// Agregar base de datos si existe
|
|
476
|
+
if (hasDatabase) {
|
|
477
|
+
if (hasDatabase.includes('postgres')) {
|
|
478
|
+
services += `
|
|
479
|
+
# ============================================
|
|
480
|
+
# PostgreSQL Database
|
|
481
|
+
# ============================================
|
|
482
|
+
db:
|
|
483
|
+
image: postgres:15-alpine
|
|
484
|
+
volumes:
|
|
485
|
+
- postgres_data:/var/lib/postgresql/data
|
|
486
|
+
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
|
487
|
+
environment:
|
|
488
|
+
- POSTGRES_USER=postgres
|
|
489
|
+
- POSTGRES_PASSWORD=postgres
|
|
490
|
+
- POSTGRES_DB=app_dev
|
|
491
|
+
ports:
|
|
492
|
+
- "5432:5432"
|
|
493
|
+
healthcheck:
|
|
494
|
+
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
495
|
+
interval: 10s
|
|
496
|
+
timeout: 5s
|
|
497
|
+
retries: 5
|
|
498
|
+
restart: unless-stopped
|
|
499
|
+
`;
|
|
500
|
+
} else if (hasDatabase.includes('mysql')) {
|
|
501
|
+
services += `
|
|
502
|
+
# ============================================
|
|
503
|
+
# MySQL Database
|
|
504
|
+
# ============================================
|
|
505
|
+
db:
|
|
506
|
+
image: mysql:8.0
|
|
507
|
+
volumes:
|
|
508
|
+
- mysql_data:/var/lib/mysql
|
|
509
|
+
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
|
510
|
+
environment:
|
|
511
|
+
- MYSQL_ROOT_PASSWORD=root
|
|
512
|
+
- MYSQL_DATABASE=app_dev
|
|
513
|
+
- MYSQL_USER=app
|
|
514
|
+
- MYSQL_PASSWORD=app
|
|
515
|
+
ports:
|
|
516
|
+
- "3306:3306"
|
|
517
|
+
healthcheck:
|
|
518
|
+
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
|
519
|
+
interval: 10s
|
|
520
|
+
timeout: 5s
|
|
521
|
+
retries: 5
|
|
522
|
+
restart: unless-stopped
|
|
523
|
+
`;
|
|
524
|
+
} else if (hasDatabase.includes('mongo')) {
|
|
525
|
+
services += `
|
|
526
|
+
# ============================================
|
|
527
|
+
# MongoDB Database
|
|
528
|
+
# ============================================
|
|
529
|
+
db:
|
|
530
|
+
image: mongo:7.0
|
|
531
|
+
volumes:
|
|
532
|
+
- mongo_data:/data/db
|
|
533
|
+
environment:
|
|
534
|
+
- MONGO_INITDB_ROOT_USERNAME=root
|
|
535
|
+
- MONGO_INITDB_ROOT_PASSWORD=root
|
|
536
|
+
- MONGO_INITDB_DATABASE=app_dev
|
|
537
|
+
ports:
|
|
538
|
+
- "27017:27017"
|
|
539
|
+
healthcheck:
|
|
540
|
+
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
|
|
541
|
+
interval: 10s
|
|
542
|
+
timeout: 5s
|
|
543
|
+
retries: 5
|
|
544
|
+
restart: unless-stopped
|
|
545
|
+
`;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Agregar Redis si existe
|
|
550
|
+
if (hasRedis) {
|
|
551
|
+
services += `
|
|
552
|
+
# ============================================
|
|
553
|
+
# Redis Cache
|
|
554
|
+
# ============================================
|
|
555
|
+
redis:
|
|
556
|
+
image: redis:7-alpine
|
|
557
|
+
volumes:
|
|
558
|
+
- redis_data:/data
|
|
559
|
+
ports:
|
|
560
|
+
- "6379:6379"
|
|
561
|
+
healthcheck:
|
|
562
|
+
test: ["CMD", "redis-cli", "ping"]
|
|
563
|
+
interval: 10s
|
|
564
|
+
timeout: 5s
|
|
565
|
+
retries: 5
|
|
566
|
+
restart: unless-stopped
|
|
567
|
+
`;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Volúmenes
|
|
571
|
+
services += `
|
|
572
|
+
# ============================================
|
|
573
|
+
# Volumes
|
|
574
|
+
# ============================================
|
|
575
|
+
volumes:
|
|
576
|
+
`;
|
|
577
|
+
if (hasDatabase?.includes('postgres')) services += ' postgres_data:\n';
|
|
578
|
+
if (hasDatabase?.includes('mysql')) services += ' mysql_data:\n';
|
|
579
|
+
if (hasDatabase?.includes('mongo')) services += ' mongo_data:\n';
|
|
580
|
+
if (hasRedis) services += ' redis_data:\n';
|
|
581
|
+
|
|
582
|
+
return services;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
private generateDockerignore(techStack: TechStack): string {
|
|
586
|
+
return `# ============================================
|
|
587
|
+
# 📚 ¿QUÉ ES ESTE ARCHIVO?
|
|
588
|
+
# ============================================
|
|
589
|
+
# .dockerignore funciona como .gitignore pero para Docker.
|
|
590
|
+
# Los archivos listados aquí NO se copiarán a la imagen Docker.
|
|
591
|
+
#
|
|
592
|
+
# ¿POR QUÉ ES IMPORTANTE?
|
|
593
|
+
# 1. Reduce el tamaño de la imagen (más rápido de construir y desplegar)
|
|
594
|
+
# 2. Mejora la seguridad (no incluir secrets o archivos sensibles)
|
|
595
|
+
# 3. Evita conflictos (ej: node_modules del host vs contenedor)
|
|
596
|
+
# 4. Acelera el build (menos archivos que procesar)
|
|
597
|
+
#
|
|
598
|
+
# 💡 TIP: Si tu build es lento, revisa que este archivo esté bien configurado
|
|
599
|
+
# ============================================
|
|
600
|
+
|
|
601
|
+
# ============================================
|
|
602
|
+
# Git - No necesitamos historial en la imagen
|
|
603
|
+
# ============================================
|
|
604
|
+
.git
|
|
605
|
+
.gitignore
|
|
606
|
+
|
|
607
|
+
# ============================================
|
|
608
|
+
# Dependencies - Se instalan DENTRO del contenedor
|
|
609
|
+
# ============================================
|
|
610
|
+
# ⚠️ MUY IMPORTANTE: node_modules del host puede tener
|
|
611
|
+
# binarios compilados para tu SO que no funcionarán en Linux (Docker)
|
|
612
|
+
node_modules
|
|
613
|
+
.npm
|
|
614
|
+
.yarn
|
|
615
|
+
.pnp.*
|
|
616
|
+
|
|
617
|
+
# Python - Igual que node_modules, se instala dentro
|
|
618
|
+
__pycache__
|
|
619
|
+
*.py[cod]
|
|
620
|
+
*$py.class
|
|
621
|
+
.Python
|
|
622
|
+
venv/
|
|
623
|
+
.venv/
|
|
624
|
+
ENV/
|
|
625
|
+
|
|
626
|
+
# ============================================
|
|
627
|
+
# Build outputs - Se generan dentro del contenedor
|
|
628
|
+
# ============================================
|
|
629
|
+
dist
|
|
630
|
+
build
|
|
631
|
+
.next
|
|
632
|
+
out
|
|
633
|
+
*.egg-info/
|
|
634
|
+
|
|
635
|
+
# ============================================
|
|
636
|
+
# IDE and Editor - Archivos personales
|
|
637
|
+
# ============================================
|
|
638
|
+
.idea
|
|
639
|
+
.vscode
|
|
640
|
+
*.swp
|
|
641
|
+
*.swo
|
|
642
|
+
*~
|
|
643
|
+
|
|
644
|
+
# ============================================
|
|
645
|
+
# Testing - No necesarios en producción
|
|
646
|
+
# ============================================
|
|
647
|
+
coverage
|
|
648
|
+
.coverage
|
|
649
|
+
htmlcov/
|
|
650
|
+
.pytest_cache
|
|
651
|
+
.nyc_output
|
|
652
|
+
|
|
653
|
+
# ============================================
|
|
654
|
+
# Environment - ⚠️ NUNCA incluir secrets en la imagen
|
|
655
|
+
# ============================================
|
|
656
|
+
# Los secrets se pasan como variables de entorno en runtime
|
|
657
|
+
.env
|
|
658
|
+
.env.local
|
|
659
|
+
.env.*.local
|
|
660
|
+
*.env
|
|
661
|
+
|
|
662
|
+
# ============================================
|
|
663
|
+
# Logs - Se generan en runtime, no en build
|
|
664
|
+
# ============================================
|
|
665
|
+
*.log
|
|
666
|
+
logs
|
|
667
|
+
npm-debug.log*
|
|
668
|
+
yarn-debug.log*
|
|
669
|
+
yarn-error.log*
|
|
670
|
+
|
|
671
|
+
# ============================================
|
|
672
|
+
# Docker - Evitar recursión
|
|
673
|
+
# ============================================
|
|
674
|
+
Dockerfile*
|
|
675
|
+
docker-compose*.yml
|
|
676
|
+
.docker
|
|
677
|
+
|
|
678
|
+
# ============================================
|
|
679
|
+
# Documentation - No necesaria en runtime
|
|
680
|
+
# ============================================
|
|
681
|
+
docs
|
|
682
|
+
*.md
|
|
683
|
+
!README.md
|
|
684
|
+
|
|
685
|
+
# ============================================
|
|
686
|
+
# Misc
|
|
687
|
+
# ============================================
|
|
688
|
+
.DS_Store
|
|
689
|
+
Thumbs.db
|
|
690
|
+
*.tmp
|
|
691
|
+
*.temp
|
|
692
|
+
`;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
private generateDockerScripts(): Record<string, string> {
|
|
696
|
+
return {
|
|
697
|
+
'scripts/docker-dev.sh': `#!/bin/bash
|
|
698
|
+
# Script para desarrollo con Docker
|
|
699
|
+
|
|
700
|
+
set -e
|
|
701
|
+
|
|
702
|
+
echo "🐳 Iniciando entorno de desarrollo..."
|
|
703
|
+
|
|
704
|
+
# Construir imágenes
|
|
705
|
+
docker-compose -f docker-compose.dev.yml build
|
|
706
|
+
|
|
707
|
+
# Iniciar servicios
|
|
708
|
+
docker-compose -f docker-compose.dev.yml up -d
|
|
709
|
+
|
|
710
|
+
# Mostrar logs
|
|
711
|
+
echo "📋 Logs disponibles con: docker-compose -f docker-compose.dev.yml logs -f"
|
|
712
|
+
echo "🌐 App disponible en: http://localhost:3000"
|
|
713
|
+
echo "🗄️ DB disponible en: localhost:5432"
|
|
714
|
+
|
|
715
|
+
# Seguir logs de la app
|
|
716
|
+
docker-compose -f docker-compose.dev.yml logs -f app
|
|
717
|
+
`,
|
|
718
|
+
'scripts/docker-stop.sh': `#!/bin/bash
|
|
719
|
+
# Script para detener Docker
|
|
720
|
+
|
|
721
|
+
echo "🛑 Deteniendo servicios..."
|
|
722
|
+
docker-compose -f docker-compose.dev.yml down
|
|
723
|
+
|
|
724
|
+
echo "✅ Servicios detenidos"
|
|
725
|
+
`,
|
|
726
|
+
'scripts/docker-clean.sh': `#!/bin/bash
|
|
727
|
+
# Script para limpiar Docker
|
|
728
|
+
|
|
729
|
+
echo "🧹 Limpiando Docker..."
|
|
730
|
+
|
|
731
|
+
# Detener y eliminar contenedores
|
|
732
|
+
docker-compose -f docker-compose.dev.yml down -v --remove-orphans
|
|
733
|
+
|
|
734
|
+
# Eliminar imágenes del proyecto
|
|
735
|
+
docker images | grep -E "^(app|db|redis)" | awk '{print $3}' | xargs -r docker rmi
|
|
736
|
+
|
|
737
|
+
# Limpiar volúmenes huérfanos
|
|
738
|
+
docker volume prune -f
|
|
739
|
+
|
|
740
|
+
echo "✅ Limpieza completada"
|
|
741
|
+
`,
|
|
742
|
+
'scripts/docker-logs.sh': `#!/bin/bash
|
|
743
|
+
# Script para ver logs
|
|
744
|
+
|
|
745
|
+
SERVICE=\${1:-app}
|
|
746
|
+
docker-compose -f docker-compose.dev.yml logs -f $SERVICE
|
|
747
|
+
`,
|
|
748
|
+
'scripts/docker-shell.sh': `#!/bin/bash
|
|
749
|
+
# Script para abrir shell en contenedor
|
|
750
|
+
|
|
751
|
+
SERVICE=\${1:-app}
|
|
752
|
+
docker-compose -f docker-compose.dev.yml exec $SERVICE sh
|
|
753
|
+
`
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
---
|
|
760
|
+
|
|
761
|
+
## ⚙️ FASE 1: GitHub Actions (SEGUNDA PRIORIDAD)
|
|
762
|
+
|
|
763
|
+
### Workflows Generados Automáticamente
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
class GitHubActionsGenerator {
|
|
767
|
+
async generateWorkflows(techStack: TechStack): Promise<Record<string, string>> {
|
|
768
|
+
return {
|
|
769
|
+
// CI principal - SIEMPRE SE GENERA
|
|
770
|
+
'ci.yml': this.generateCIWorkflow(techStack),
|
|
771
|
+
|
|
772
|
+
// Build y push de Docker
|
|
773
|
+
'docker-build.yml': this.generateDockerBuildWorkflow(techStack),
|
|
774
|
+
|
|
775
|
+
// Deploy automático
|
|
776
|
+
'deploy.yml': this.generateDeployWorkflow(techStack),
|
|
777
|
+
|
|
778
|
+
// PR checks
|
|
779
|
+
'pr-check.yml': this.generatePRCheckWorkflow(techStack),
|
|
780
|
+
|
|
781
|
+
// Security scanning
|
|
782
|
+
'security.yml': this.generateSecurityWorkflow(techStack),
|
|
783
|
+
|
|
784
|
+
// Dependabot auto-merge
|
|
785
|
+
'dependabot-auto-merge.yml': this.generateDependabotWorkflow()
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
private generateCIWorkflow(techStack: TechStack): string {
|
|
790
|
+
const isNode = this.isNodeProject(techStack);
|
|
791
|
+
const isPython = this.isPythonProject(techStack);
|
|
792
|
+
|
|
793
|
+
return `name: CI Pipeline
|
|
794
|
+
|
|
795
|
+
on:
|
|
796
|
+
push:
|
|
797
|
+
branches: [main, develop]
|
|
798
|
+
pull_request:
|
|
799
|
+
branches: [main, develop]
|
|
800
|
+
|
|
801
|
+
env:
|
|
802
|
+
REGISTRY: ghcr.io
|
|
803
|
+
IMAGE_NAME: \${{ github.repository }}
|
|
804
|
+
|
|
805
|
+
jobs:
|
|
806
|
+
# ============================================
|
|
807
|
+
# Lint y Type Check
|
|
808
|
+
# ============================================
|
|
809
|
+
lint:
|
|
810
|
+
name: Lint & Type Check
|
|
811
|
+
runs-on: ubuntu-latest
|
|
812
|
+
steps:
|
|
813
|
+
- uses: actions/checkout@v4
|
|
814
|
+
|
|
815
|
+
${isNode ? `
|
|
816
|
+
- name: Setup Node.js
|
|
817
|
+
uses: actions/setup-node@v4
|
|
818
|
+
with:
|
|
819
|
+
node-version: '20'
|
|
820
|
+
cache: 'npm'
|
|
821
|
+
|
|
822
|
+
- name: Install dependencies
|
|
823
|
+
run: npm ci
|
|
824
|
+
|
|
825
|
+
- name: Lint
|
|
826
|
+
run: npm run lint
|
|
827
|
+
|
|
828
|
+
- name: Type Check
|
|
829
|
+
run: npm run type-check || true
|
|
830
|
+
` : ''}
|
|
831
|
+
${isPython ? `
|
|
832
|
+
- name: Setup Python
|
|
833
|
+
uses: actions/setup-python@v5
|
|
834
|
+
with:
|
|
835
|
+
python-version: '3.11'
|
|
836
|
+
cache: 'pip'
|
|
837
|
+
|
|
838
|
+
- name: Install dependencies
|
|
839
|
+
run: |
|
|
840
|
+
pip install -r requirements.txt
|
|
841
|
+
pip install flake8 black mypy
|
|
842
|
+
|
|
843
|
+
- name: Lint with flake8
|
|
844
|
+
run: flake8 . --max-line-length=100 --ignore=E501,W503
|
|
845
|
+
|
|
846
|
+
- name: Check formatting with black
|
|
847
|
+
run: black --check .
|
|
848
|
+
|
|
849
|
+
- name: Type check with mypy
|
|
850
|
+
run: mypy . --ignore-missing-imports || true
|
|
851
|
+
` : ''}
|
|
852
|
+
|
|
853
|
+
# ============================================
|
|
854
|
+
# Tests
|
|
855
|
+
# ============================================
|
|
856
|
+
test:
|
|
857
|
+
name: Run Tests
|
|
858
|
+
runs-on: ubuntu-latest
|
|
859
|
+
needs: lint
|
|
860
|
+
|
|
861
|
+
services:
|
|
862
|
+
postgres:
|
|
863
|
+
image: postgres:15-alpine
|
|
864
|
+
env:
|
|
865
|
+
POSTGRES_USER: postgres
|
|
866
|
+
POSTGRES_PASSWORD: postgres
|
|
867
|
+
POSTGRES_DB: test_db
|
|
868
|
+
ports:
|
|
869
|
+
- 5432:5432
|
|
870
|
+
options: >-
|
|
871
|
+
--health-cmd pg_isready
|
|
872
|
+
--health-interval 10s
|
|
873
|
+
--health-timeout 5s
|
|
874
|
+
--health-retries 5
|
|
875
|
+
|
|
876
|
+
redis:
|
|
877
|
+
image: redis:7-alpine
|
|
878
|
+
ports:
|
|
879
|
+
- 6379:6379
|
|
880
|
+
options: >-
|
|
881
|
+
--health-cmd "redis-cli ping"
|
|
882
|
+
--health-interval 10s
|
|
883
|
+
--health-timeout 5s
|
|
884
|
+
--health-retries 5
|
|
885
|
+
|
|
886
|
+
steps:
|
|
887
|
+
- uses: actions/checkout@v4
|
|
888
|
+
|
|
889
|
+
${isNode ? `
|
|
890
|
+
- name: Setup Node.js
|
|
891
|
+
uses: actions/setup-node@v4
|
|
892
|
+
with:
|
|
893
|
+
node-version: '20'
|
|
894
|
+
cache: 'npm'
|
|
895
|
+
|
|
896
|
+
- name: Install dependencies
|
|
897
|
+
run: npm ci
|
|
898
|
+
|
|
899
|
+
- name: Run unit tests
|
|
900
|
+
run: npm run test:unit
|
|
901
|
+
env:
|
|
902
|
+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
|
|
903
|
+
REDIS_URL: redis://localhost:6379
|
|
904
|
+
|
|
905
|
+
- name: Run integration tests
|
|
906
|
+
run: npm run test:integration || true
|
|
907
|
+
env:
|
|
908
|
+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
|
|
909
|
+
REDIS_URL: redis://localhost:6379
|
|
910
|
+
|
|
911
|
+
- name: Upload coverage
|
|
912
|
+
uses: codecov/codecov-action@v4
|
|
913
|
+
with:
|
|
914
|
+
token: \${{ secrets.CODECOV_TOKEN }}
|
|
915
|
+
fail_ci_if_error: false
|
|
916
|
+
` : ''}
|
|
917
|
+
${isPython ? `
|
|
918
|
+
- name: Setup Python
|
|
919
|
+
uses: actions/setup-python@v5
|
|
920
|
+
with:
|
|
921
|
+
python-version: '3.11'
|
|
922
|
+
cache: 'pip'
|
|
923
|
+
|
|
924
|
+
- name: Install dependencies
|
|
925
|
+
run: |
|
|
926
|
+
pip install -r requirements.txt
|
|
927
|
+
pip install pytest pytest-cov pytest-asyncio
|
|
928
|
+
|
|
929
|
+
- name: Run tests
|
|
930
|
+
run: pytest --cov=. --cov-report=xml -v
|
|
931
|
+
env:
|
|
932
|
+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
|
|
933
|
+
REDIS_URL: redis://localhost:6379
|
|
934
|
+
|
|
935
|
+
- name: Upload coverage
|
|
936
|
+
uses: codecov/codecov-action@v4
|
|
937
|
+
with:
|
|
938
|
+
token: \${{ secrets.CODECOV_TOKEN }}
|
|
939
|
+
fail_ci_if_error: false
|
|
940
|
+
` : ''}
|
|
941
|
+
|
|
942
|
+
# ============================================
|
|
943
|
+
# Build Docker Image
|
|
944
|
+
# ============================================
|
|
945
|
+
build:
|
|
946
|
+
name: Build Docker Image
|
|
947
|
+
runs-on: ubuntu-latest
|
|
948
|
+
needs: test
|
|
949
|
+
permissions:
|
|
950
|
+
contents: read
|
|
951
|
+
packages: write
|
|
952
|
+
|
|
953
|
+
steps:
|
|
954
|
+
- uses: actions/checkout@v4
|
|
955
|
+
|
|
956
|
+
- name: Set up Docker Buildx
|
|
957
|
+
uses: docker/setup-buildx-action@v3
|
|
958
|
+
|
|
959
|
+
- name: Log in to Container Registry
|
|
960
|
+
uses: docker/login-action@v3
|
|
961
|
+
with:
|
|
962
|
+
registry: \${{ env.REGISTRY }}
|
|
963
|
+
username: \${{ github.actor }}
|
|
964
|
+
password: \${{ secrets.GITHUB_TOKEN }}
|
|
965
|
+
|
|
966
|
+
- name: Extract metadata
|
|
967
|
+
id: meta
|
|
968
|
+
uses: docker/metadata-action@v5
|
|
969
|
+
with:
|
|
970
|
+
images: \${{ env.REGISTRY }}/\${{ env.IMAGE_NAME }}
|
|
971
|
+
tags: |
|
|
972
|
+
type=ref,event=branch
|
|
973
|
+
type=ref,event=pr
|
|
974
|
+
type=sha,prefix=
|
|
975
|
+
type=raw,value=latest,enable={{is_default_branch}}
|
|
976
|
+
|
|
977
|
+
- name: Build and push
|
|
978
|
+
uses: docker/build-push-action@v5
|
|
979
|
+
with:
|
|
980
|
+
context: .
|
|
981
|
+
target: production
|
|
982
|
+
push: \${{ github.event_name != 'pull_request' }}
|
|
983
|
+
tags: \${{ steps.meta.outputs.tags }}
|
|
984
|
+
labels: \${{ steps.meta.outputs.labels }}
|
|
985
|
+
cache-from: type=gha
|
|
986
|
+
cache-to: type=gha,mode=max
|
|
987
|
+
`;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
private generateDockerBuildWorkflow(techStack: TechStack): string {
|
|
991
|
+
return `name: Docker Build & Push
|
|
992
|
+
|
|
993
|
+
on:
|
|
994
|
+
push:
|
|
995
|
+
branches: [main]
|
|
996
|
+
tags: ['v*']
|
|
997
|
+
workflow_dispatch:
|
|
998
|
+
|
|
999
|
+
env:
|
|
1000
|
+
REGISTRY: ghcr.io
|
|
1001
|
+
IMAGE_NAME: \${{ github.repository }}
|
|
1002
|
+
|
|
1003
|
+
jobs:
|
|
1004
|
+
build-and-push:
|
|
1005
|
+
name: Build and Push Docker Image
|
|
1006
|
+
runs-on: ubuntu-latest
|
|
1007
|
+
permissions:
|
|
1008
|
+
contents: read
|
|
1009
|
+
packages: write
|
|
1010
|
+
|
|
1011
|
+
steps:
|
|
1012
|
+
- uses: actions/checkout@v4
|
|
1013
|
+
|
|
1014
|
+
- name: Set up QEMU
|
|
1015
|
+
uses: docker/setup-qemu-action@v3
|
|
1016
|
+
|
|
1017
|
+
- name: Set up Docker Buildx
|
|
1018
|
+
uses: docker/setup-buildx-action@v3
|
|
1019
|
+
|
|
1020
|
+
- name: Log in to Container Registry
|
|
1021
|
+
uses: docker/login-action@v3
|
|
1022
|
+
with:
|
|
1023
|
+
registry: \${{ env.REGISTRY }}
|
|
1024
|
+
username: \${{ github.actor }}
|
|
1025
|
+
password: \${{ secrets.GITHUB_TOKEN }}
|
|
1026
|
+
|
|
1027
|
+
- name: Extract metadata
|
|
1028
|
+
id: meta
|
|
1029
|
+
uses: docker/metadata-action@v5
|
|
1030
|
+
with:
|
|
1031
|
+
images: \${{ env.REGISTRY }}/\${{ env.IMAGE_NAME }}
|
|
1032
|
+
tags: |
|
|
1033
|
+
type=semver,pattern={{version}}
|
|
1034
|
+
type=semver,pattern={{major}}.{{minor}}
|
|
1035
|
+
type=sha,prefix=
|
|
1036
|
+
type=raw,value=latest,enable={{is_default_branch}}
|
|
1037
|
+
|
|
1038
|
+
- name: Build and push (multi-platform)
|
|
1039
|
+
uses: docker/build-push-action@v5
|
|
1040
|
+
with:
|
|
1041
|
+
context: .
|
|
1042
|
+
target: production
|
|
1043
|
+
platforms: linux/amd64,linux/arm64
|
|
1044
|
+
push: true
|
|
1045
|
+
tags: \${{ steps.meta.outputs.tags }}
|
|
1046
|
+
labels: \${{ steps.meta.outputs.labels }}
|
|
1047
|
+
cache-from: type=gha
|
|
1048
|
+
cache-to: type=gha,mode=max
|
|
1049
|
+
build-args: |
|
|
1050
|
+
BUILD_DATE=\${{ github.event.repository.updated_at }}
|
|
1051
|
+
VCS_REF=\${{ github.sha }}
|
|
1052
|
+
`;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
private generateDeployWorkflow(techStack: TechStack): string {
|
|
1056
|
+
return `name: Deploy
|
|
1057
|
+
|
|
1058
|
+
on:
|
|
1059
|
+
push:
|
|
1060
|
+
branches: [main]
|
|
1061
|
+
workflow_dispatch:
|
|
1062
|
+
inputs:
|
|
1063
|
+
environment:
|
|
1064
|
+
description: 'Environment to deploy to'
|
|
1065
|
+
required: true
|
|
1066
|
+
default: 'staging'
|
|
1067
|
+
type: choice
|
|
1068
|
+
options:
|
|
1069
|
+
- staging
|
|
1070
|
+
- production
|
|
1071
|
+
|
|
1072
|
+
env:
|
|
1073
|
+
REGISTRY: ghcr.io
|
|
1074
|
+
IMAGE_NAME: \${{ github.repository }}
|
|
1075
|
+
|
|
1076
|
+
jobs:
|
|
1077
|
+
deploy-staging:
|
|
1078
|
+
name: Deploy to Staging
|
|
1079
|
+
runs-on: ubuntu-latest
|
|
1080
|
+
if: github.ref == 'refs/heads/develop' || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'staging')
|
|
1081
|
+
environment:
|
|
1082
|
+
name: staging
|
|
1083
|
+
url: https://staging.example.com
|
|
1084
|
+
|
|
1085
|
+
steps:
|
|
1086
|
+
- uses: actions/checkout@v4
|
|
1087
|
+
|
|
1088
|
+
- name: Deploy to Staging
|
|
1089
|
+
run: |
|
|
1090
|
+
echo "🚀 Deploying to staging..."
|
|
1091
|
+
# Agregar comandos de deploy aquí
|
|
1092
|
+
# Ejemplos:
|
|
1093
|
+
# - kubectl set image deployment/app app=\${{ env.REGISTRY }}/\${{ env.IMAGE_NAME }}:sha-\${{ github.sha }}
|
|
1094
|
+
# - ssh staging "cd /app && docker-compose pull && docker-compose up -d"
|
|
1095
|
+
# - flyctl deploy --remote-only
|
|
1096
|
+
|
|
1097
|
+
- name: Run smoke tests
|
|
1098
|
+
run: |
|
|
1099
|
+
echo "🧪 Running smoke tests..."
|
|
1100
|
+
# curl -f https://staging.example.com/health || exit 1
|
|
1101
|
+
|
|
1102
|
+
- name: Notify success
|
|
1103
|
+
if: success()
|
|
1104
|
+
run: echo "✅ Staging deployment successful!"
|
|
1105
|
+
|
|
1106
|
+
deploy-production:
|
|
1107
|
+
name: Deploy to Production
|
|
1108
|
+
runs-on: ubuntu-latest
|
|
1109
|
+
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'production')
|
|
1110
|
+
environment:
|
|
1111
|
+
name: production
|
|
1112
|
+
url: https://example.com
|
|
1113
|
+
needs: [deploy-staging]
|
|
1114
|
+
|
|
1115
|
+
steps:
|
|
1116
|
+
- uses: actions/checkout@v4
|
|
1117
|
+
|
|
1118
|
+
- name: Deploy to Production
|
|
1119
|
+
run: |
|
|
1120
|
+
echo "🚀 Deploying to production..."
|
|
1121
|
+
# Agregar comandos de deploy aquí
|
|
1122
|
+
|
|
1123
|
+
- name: Run smoke tests
|
|
1124
|
+
run: |
|
|
1125
|
+
echo "🧪 Running smoke tests..."
|
|
1126
|
+
# curl -f https://example.com/health || exit 1
|
|
1127
|
+
|
|
1128
|
+
- name: Notify success
|
|
1129
|
+
if: success()
|
|
1130
|
+
run: echo "✅ Production deployment successful!"
|
|
1131
|
+
`;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
private generatePRCheckWorkflow(techStack: TechStack): string {
|
|
1135
|
+
return `name: PR Check
|
|
1136
|
+
|
|
1137
|
+
on:
|
|
1138
|
+
pull_request:
|
|
1139
|
+
types: [opened, synchronize, reopened]
|
|
1140
|
+
|
|
1141
|
+
jobs:
|
|
1142
|
+
pr-check:
|
|
1143
|
+
name: PR Quality Check
|
|
1144
|
+
runs-on: ubuntu-latest
|
|
1145
|
+
|
|
1146
|
+
steps:
|
|
1147
|
+
- uses: actions/checkout@v4
|
|
1148
|
+
with:
|
|
1149
|
+
fetch-depth: 0
|
|
1150
|
+
|
|
1151
|
+
- name: Check PR size
|
|
1152
|
+
run: |
|
|
1153
|
+
CHANGES=\$(git diff --shortstat origin/\${{ github.base_ref }}...HEAD | grep -oP '\\d+(?= file)' || echo "0")
|
|
1154
|
+
echo "📊 Files changed: \$CHANGES"
|
|
1155
|
+
if [ "\$CHANGES" -gt 20 ]; then
|
|
1156
|
+
echo "⚠️ WARNING: PR muy grande (\$CHANGES archivos). Considera dividirlo."
|
|
1157
|
+
fi
|
|
1158
|
+
|
|
1159
|
+
- name: Check commit messages
|
|
1160
|
+
run: |
|
|
1161
|
+
echo "📝 Verificando commit messages..."
|
|
1162
|
+
INVALID=\$(git log --format=%s origin/\${{ github.base_ref }}..HEAD | grep -vE '^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\\(.+\\))?!?:' || true)
|
|
1163
|
+
if [ -n "\$INVALID" ]; then
|
|
1164
|
+
echo "⚠️ WARNING: Algunos commits no siguen conventional commits:"
|
|
1165
|
+
echo "\$INVALID"
|
|
1166
|
+
fi
|
|
1167
|
+
|
|
1168
|
+
- name: Check for TODO/FIXME
|
|
1169
|
+
run: |
|
|
1170
|
+
echo "🔍 Buscando TODO/FIXME..."
|
|
1171
|
+
TODOS=\$(grep -rn "TODO\\|FIXME" --include="*.ts" --include="*.js" --include="*.py" . || true)
|
|
1172
|
+
if [ -n "\$TODOS" ]; then
|
|
1173
|
+
echo "📝 TODOs encontrados:"
|
|
1174
|
+
echo "\$TODOS"
|
|
1175
|
+
fi
|
|
1176
|
+
|
|
1177
|
+
- name: Comment on PR
|
|
1178
|
+
uses: actions/github-script@v7
|
|
1179
|
+
with:
|
|
1180
|
+
script: |
|
|
1181
|
+
github.rest.issues.createComment({
|
|
1182
|
+
issue_number: context.issue.number,
|
|
1183
|
+
owner: context.repo.owner,
|
|
1184
|
+
repo: context.repo.repo,
|
|
1185
|
+
body: '✅ PR check completado. Revisa los logs de CI para detalles.'
|
|
1186
|
+
})
|
|
1187
|
+
`;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
private generateSecurityWorkflow(techStack: TechStack): string {
|
|
1191
|
+
return `name: Security Scan
|
|
1192
|
+
|
|
1193
|
+
on:
|
|
1194
|
+
push:
|
|
1195
|
+
branches: [main, develop]
|
|
1196
|
+
pull_request:
|
|
1197
|
+
branches: [main]
|
|
1198
|
+
schedule:
|
|
1199
|
+
- cron: '0 6 * * 1' # Lunes a las 6am
|
|
1200
|
+
|
|
1201
|
+
jobs:
|
|
1202
|
+
# ============================================
|
|
1203
|
+
# Dependency Audit
|
|
1204
|
+
# ============================================
|
|
1205
|
+
dependency-audit:
|
|
1206
|
+
name: Dependency Audit
|
|
1207
|
+
runs-on: ubuntu-latest
|
|
1208
|
+
steps:
|
|
1209
|
+
- uses: actions/checkout@v4
|
|
1210
|
+
|
|
1211
|
+
- name: Run npm audit
|
|
1212
|
+
run: npm audit --audit-level=high
|
|
1213
|
+
continue-on-error: true
|
|
1214
|
+
|
|
1215
|
+
- name: Run Snyk
|
|
1216
|
+
uses: snyk/actions/node@master
|
|
1217
|
+
continue-on-error: true
|
|
1218
|
+
env:
|
|
1219
|
+
SNYK_TOKEN: \${{ secrets.SNYK_TOKEN }}
|
|
1220
|
+
|
|
1221
|
+
# ============================================
|
|
1222
|
+
# Code Scanning
|
|
1223
|
+
# ============================================
|
|
1224
|
+
codeql:
|
|
1225
|
+
name: CodeQL Analysis
|
|
1226
|
+
runs-on: ubuntu-latest
|
|
1227
|
+
permissions:
|
|
1228
|
+
actions: read
|
|
1229
|
+
contents: read
|
|
1230
|
+
security-events: write
|
|
1231
|
+
|
|
1232
|
+
steps:
|
|
1233
|
+
- uses: actions/checkout@v4
|
|
1234
|
+
|
|
1235
|
+
- name: Initialize CodeQL
|
|
1236
|
+
uses: github/codeql-action/init@v3
|
|
1237
|
+
with:
|
|
1238
|
+
languages: javascript, typescript
|
|
1239
|
+
|
|
1240
|
+
- name: Autobuild
|
|
1241
|
+
uses: github/codeql-action/autobuild@v3
|
|
1242
|
+
|
|
1243
|
+
- name: Perform CodeQL Analysis
|
|
1244
|
+
uses: github/codeql-action/analyze@v3
|
|
1245
|
+
|
|
1246
|
+
# ============================================
|
|
1247
|
+
# Container Scanning
|
|
1248
|
+
# ============================================
|
|
1249
|
+
container-scan:
|
|
1250
|
+
name: Container Vulnerability Scan
|
|
1251
|
+
runs-on: ubuntu-latest
|
|
1252
|
+
steps:
|
|
1253
|
+
- uses: actions/checkout@v4
|
|
1254
|
+
|
|
1255
|
+
- name: Build image for scanning
|
|
1256
|
+
run: docker build -t scan-target:latest --target production .
|
|
1257
|
+
|
|
1258
|
+
- name: Run Trivy vulnerability scanner
|
|
1259
|
+
uses: aquasecurity/trivy-action@master
|
|
1260
|
+
with:
|
|
1261
|
+
image-ref: 'scan-target:latest'
|
|
1262
|
+
format: 'sarif'
|
|
1263
|
+
output: 'trivy-results.sarif'
|
|
1264
|
+
severity: 'CRITICAL,HIGH'
|
|
1265
|
+
|
|
1266
|
+
- name: Upload Trivy scan results
|
|
1267
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
1268
|
+
with:
|
|
1269
|
+
sarif_file: 'trivy-results.sarif'
|
|
1270
|
+
`;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
private generateDependabotWorkflow(): string {
|
|
1274
|
+
return `name: Dependabot Auto-Merge
|
|
1275
|
+
|
|
1276
|
+
on:
|
|
1277
|
+
pull_request:
|
|
1278
|
+
types: [opened, synchronize]
|
|
1279
|
+
|
|
1280
|
+
permissions:
|
|
1281
|
+
contents: write
|
|
1282
|
+
pull-requests: write
|
|
1283
|
+
|
|
1284
|
+
jobs:
|
|
1285
|
+
dependabot-auto-merge:
|
|
1286
|
+
name: Auto-merge Dependabot PRs
|
|
1287
|
+
runs-on: ubuntu-latest
|
|
1288
|
+
if: github.actor == 'dependabot[bot]'
|
|
1289
|
+
|
|
1290
|
+
steps:
|
|
1291
|
+
- name: Dependabot metadata
|
|
1292
|
+
id: metadata
|
|
1293
|
+
uses: dependabot/fetch-metadata@v2
|
|
1294
|
+
with:
|
|
1295
|
+
github-token: \${{ secrets.GITHUB_TOKEN }}
|
|
1296
|
+
|
|
1297
|
+
- name: Auto-merge minor/patch updates
|
|
1298
|
+
if: steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor'
|
|
1299
|
+
run: gh pr merge --auto --squash "\$PR_URL"
|
|
1300
|
+
env:
|
|
1301
|
+
PR_URL: \${{ github.event.pull_request.html_url }}
|
|
1302
|
+
GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
|
|
1303
|
+
`;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
---
|
|
1309
|
+
|
|
1310
|
+
## 📋 FASES 2-4: Resto del Plan (Como antes)
|
|
1311
|
+
|
|
1312
|
+
Después de Docker y GitHub Actions, el plan continúa con:
|
|
1313
|
+
|
|
1314
|
+
### Fase 2: Setup de Ramas y Protecciones
|
|
1315
|
+
- Crear ramas develop y staging
|
|
1316
|
+
- Configurar branch protection en main
|
|
1317
|
+
- Setup de labels y milestones
|
|
1318
|
+
|
|
1319
|
+
### Fase 3: Issues y Backlog
|
|
1320
|
+
- Crear issues desde análisis del proyecto
|
|
1321
|
+
- Configurar GitHub Project (Kanban)
|
|
1322
|
+
- Priorizar tareas
|
|
1323
|
+
|
|
1324
|
+
### Fase 4: Desarrollo Iterativo
|
|
1325
|
+
- Implementación de features
|
|
1326
|
+
- TDD en áreas críticas
|
|
1327
|
+
- Demos semanales
|
|
1328
|
+
|
|
1329
|
+
---
|
|
1330
|
+
|
|
1331
|
+
## 🚀 Workflow de Ejecución Actualizado
|
|
1332
|
+
|
|
1333
|
+
```typescript
|
|
1334
|
+
class FreelancePlannerOrchestrator {
|
|
1335
|
+
async executeFull(projectPath: string, options: PlannerOptions): Promise<ExecutionResult> {
|
|
1336
|
+
console.log('🚀 Iniciando Freelance Project Planner v3.0...\n');
|
|
1337
|
+
console.log('📦 Filosofía: Infrastructure First (Docker + CI/CD)\n');
|
|
1338
|
+
|
|
1339
|
+
// FASE 0: Análisis
|
|
1340
|
+
console.log('📊 FASE 0: Análisis del Proyecto');
|
|
1341
|
+
const analysis = await this.analyzer.analyzeProject(projectPath);
|
|
1342
|
+
this.printAnalysisSummary(analysis);
|
|
1343
|
+
|
|
1344
|
+
// FASE 1: DOCKER (PRIMERA PRIORIDAD) 🐳
|
|
1345
|
+
console.log('\n🐳 FASE 1: Dockerización (PRIORIDAD MÁXIMA)');
|
|
1346
|
+
const dockerSetup = await this.dockerGenerator.generateDockerSetup(analysis);
|
|
1347
|
+
await this.commitDockerFiles(dockerSetup);
|
|
1348
|
+
console.log('✅ Docker configurado:');
|
|
1349
|
+
console.log(' - Dockerfile (multi-stage)');
|
|
1350
|
+
console.log(' - docker-compose.dev.yml');
|
|
1351
|
+
console.log(' - docker-compose.prod.yml');
|
|
1352
|
+
console.log(' - .dockerignore');
|
|
1353
|
+
console.log(' - Scripts de conveniencia');
|
|
1354
|
+
|
|
1355
|
+
// FASE 2: GITHUB ACTIONS (SEGUNDA PRIORIDAD) ⚙️
|
|
1356
|
+
console.log('\n⚙️ FASE 2: GitHub Actions (CI/CD)');
|
|
1357
|
+
const workflows = await this.actionsGenerator.generateWorkflows(analysis.techStack);
|
|
1358
|
+
await this.commitWorkflows(workflows);
|
|
1359
|
+
console.log('✅ Workflows configurados:');
|
|
1360
|
+
console.log(' - ci.yml (lint, test, build)');
|
|
1361
|
+
console.log(' - docker-build.yml (multi-platform)');
|
|
1362
|
+
console.log(' - deploy.yml (staging + production)');
|
|
1363
|
+
console.log(' - pr-check.yml (calidad de PR)');
|
|
1364
|
+
console.log(' - security.yml (vulnerability scanning)');
|
|
1365
|
+
|
|
1366
|
+
// FASE 3: Setup GitHub (Issues, Labels, Project)
|
|
1367
|
+
if (options.setupGitHub) {
|
|
1368
|
+
console.log('\n📋 FASE 3: Setup GitHub (Issues + Kanban)');
|
|
1369
|
+
const githubSetup = await this.githubMCP.setupProjectInGitHub(analysis, plan);
|
|
1370
|
+
this.printGitHubSetupSummary(githubSetup);
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
// FASE 4: Plan de Desarrollo
|
|
1374
|
+
console.log('\n📋 FASE 4: Generación del Plan de Desarrollo');
|
|
1375
|
+
const plan = await this.planner.createDevelopmentPlan(analysis);
|
|
1376
|
+
this.printPlanSummary(plan);
|
|
1377
|
+
|
|
1378
|
+
// FASE 5: Documentación
|
|
1379
|
+
console.log('\n📝 FASE 5: Documentación');
|
|
1380
|
+
await this.generateLocalFiles(projectPath, plan);
|
|
1381
|
+
|
|
1382
|
+
console.log('\n' + '='.repeat(50));
|
|
1383
|
+
console.log('✅ ¡Setup Completado!');
|
|
1384
|
+
console.log('='.repeat(50));
|
|
1385
|
+
|
|
1386
|
+
console.log(`
|
|
1387
|
+
🐳 Docker está listo:
|
|
1388
|
+
npm run docker:dev # Iniciar desarrollo
|
|
1389
|
+
npm run docker:stop # Detener
|
|
1390
|
+
npm run docker:clean # Limpiar
|
|
1391
|
+
|
|
1392
|
+
⚙️ CI/CD está configurado:
|
|
1393
|
+
- Push a develop → Tests + Build
|
|
1394
|
+
- Push a main → Deploy a staging
|
|
1395
|
+
- Tag v* → Deploy a production
|
|
1396
|
+
|
|
1397
|
+
📋 Próximos pasos:
|
|
1398
|
+
1. Configura secrets en GitHub (Settings → Secrets)
|
|
1399
|
+
2. Verifica que Docker funcione: npm run docker:dev
|
|
1400
|
+
3. Haz un push para verificar CI/CD
|
|
1401
|
+
4. Comienza con la primera tarea del backlog
|
|
1402
|
+
`);
|
|
1403
|
+
|
|
1404
|
+
return { analysis, dockerSetup, workflows, plan };
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1409
|
+
---
|
|
1410
|
+
|
|
1411
|
+
## 📦 Package.json Scripts Sugeridos
|
|
1412
|
+
|
|
1413
|
+
```json
|
|
1414
|
+
{
|
|
1415
|
+
"scripts": {
|
|
1416
|
+
"dev": "next dev",
|
|
1417
|
+
"build": "next build",
|
|
1418
|
+
"start": "next start",
|
|
1419
|
+
"lint": "eslint . --ext .ts,.tsx",
|
|
1420
|
+
"type-check": "tsc --noEmit",
|
|
1421
|
+
"test": "jest",
|
|
1422
|
+
"test:unit": "jest --testPathPattern=unit",
|
|
1423
|
+
"test:integration": "jest --testPathPattern=integration",
|
|
1424
|
+
"test:e2e": "playwright test",
|
|
1425
|
+
|
|
1426
|
+
"docker:dev": "./scripts/docker-dev.sh",
|
|
1427
|
+
"docker:stop": "./scripts/docker-stop.sh",
|
|
1428
|
+
"docker:clean": "./scripts/docker-clean.sh",
|
|
1429
|
+
"docker:logs": "./scripts/docker-logs.sh",
|
|
1430
|
+
"docker:shell": "./scripts/docker-shell.sh",
|
|
1431
|
+
"docker:build": "docker build -t app:latest --target production .",
|
|
1432
|
+
"docker:build:dev": "docker build -t app:dev --target development ."
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
```
|
|
1436
|
+
|
|
1437
|
+
---
|
|
1438
|
+
|
|
1439
|
+
## 📚 Generadores de Documentación Didáctica
|
|
1440
|
+
|
|
1441
|
+
### Sistema de Aprendizaje Progresivo en Tareas
|
|
1442
|
+
|
|
1443
|
+
```typescript
|
|
1444
|
+
class ProgressiveLearningTaskGenerator {
|
|
1445
|
+
/**
|
|
1446
|
+
* Genera tareas que integran aprendizaje progresivo.
|
|
1447
|
+
* Cada tarea enseña conceptos nuevos cuando son necesarios.
|
|
1448
|
+
*/
|
|
1449
|
+
|
|
1450
|
+
private learningPath: LearningPath = {
|
|
1451
|
+
// Mapa de qué conceptos se aprenden en qué orden
|
|
1452
|
+
concepts: [
|
|
1453
|
+
{ id: 'docker-basics', level: 1, prereqs: [] },
|
|
1454
|
+
{ id: 'docker-compose', level: 1, prereqs: ['docker-basics'] },
|
|
1455
|
+
{ id: 'env-variables', level: 1, prereqs: [] },
|
|
1456
|
+
{ id: 'git-workflow', level: 1, prereqs: [] },
|
|
1457
|
+
{ id: 'api-rest-basics', level: 2, prereqs: ['docker-compose'] },
|
|
1458
|
+
{ id: 'database-basics', level: 2, prereqs: ['docker-compose', 'env-variables'] },
|
|
1459
|
+
{ id: 'testing-unit', level: 2, prereqs: ['api-rest-basics'] },
|
|
1460
|
+
{ id: 'authentication', level: 3, prereqs: ['api-rest-basics', 'database-basics'] },
|
|
1461
|
+
{ id: 'testing-integration', level: 3, prereqs: ['testing-unit', 'database-basics'] },
|
|
1462
|
+
{ id: 'ci-cd', level: 3, prereqs: ['testing-unit', 'git-workflow'] },
|
|
1463
|
+
{ id: 'deployment', level: 4, prereqs: ['ci-cd', 'docker-compose'] },
|
|
1464
|
+
{ id: 'monitoring', level: 4, prereqs: ['deployment'] },
|
|
1465
|
+
]
|
|
1466
|
+
};
|
|
1467
|
+
|
|
1468
|
+
/**
|
|
1469
|
+
* Genera un issue con aprendizaje integrado
|
|
1470
|
+
*/
|
|
1471
|
+
generateLearningTask(task: Task, taskNumber: number, totalTasks: number): string {
|
|
1472
|
+
const conceptsToLearn = this.getConceptsForTask(task);
|
|
1473
|
+
const previousConcepts = this.getPreviouslyLearnedConcepts(taskNumber);
|
|
1474
|
+
|
|
1475
|
+
return `
|
|
1476
|
+
## 🎯 Objetivo
|
|
1477
|
+
${task.description}
|
|
1478
|
+
|
|
1479
|
+
---
|
|
1480
|
+
|
|
1481
|
+
## 📚 Lo que Aprenderás en Esta Tarea
|
|
1482
|
+
|
|
1483
|
+
${this.formatLearningObjectives(conceptsToLearn)}
|
|
1484
|
+
|
|
1485
|
+
${previousConcepts.length > 0 ? `
|
|
1486
|
+
## 🔗 Construyendo sobre lo Anterior
|
|
1487
|
+
|
|
1488
|
+
Esta tarea usa conceptos que ya practicaste:
|
|
1489
|
+
${previousConcepts.map(c => `- ✅ ${c.name} (Tarea #${c.learnedInTask})`).join('\n')}
|
|
1490
|
+
` : ''}
|
|
1491
|
+
|
|
1492
|
+
---
|
|
1493
|
+
|
|
1494
|
+
## 📖 Contexto: Lo que Necesitas Saber
|
|
1495
|
+
|
|
1496
|
+
${this.generateJustInTimeDocumentation(conceptsToLearn)}
|
|
1497
|
+
|
|
1498
|
+
---
|
|
1499
|
+
|
|
1500
|
+
## 🛠️ Pasos para Completar
|
|
1501
|
+
|
|
1502
|
+
${this.generateStepsWithLearning(task)}
|
|
1503
|
+
|
|
1504
|
+
---
|
|
1505
|
+
|
|
1506
|
+
## ✅ Criterios de Aceptación
|
|
1507
|
+
|
|
1508
|
+
${task.acceptanceCriteria?.map(c => `- [ ] ${c}`).join('\n')}
|
|
1509
|
+
|
|
1510
|
+
---
|
|
1511
|
+
|
|
1512
|
+
## 🎓 Reflexión Post-Tarea
|
|
1513
|
+
|
|
1514
|
+
Antes de marcar como completada, pregúntate:
|
|
1515
|
+
|
|
1516
|
+
${this.generateReflectionQuestions(conceptsToLearn)}
|
|
1517
|
+
|
|
1518
|
+
---
|
|
1519
|
+
|
|
1520
|
+
## 📈 Tu Progreso
|
|
1521
|
+
|
|
1522
|
+
\`\`\`
|
|
1523
|
+
Tarea ${taskNumber} de ${totalTasks}
|
|
1524
|
+
[${'█'.repeat(taskNumber)}${'░'.repeat(totalTasks - taskNumber)}] ${Math.round(taskNumber/totalTasks*100)}%
|
|
1525
|
+
|
|
1526
|
+
Conceptos dominados: ${previousConcepts.length + conceptsToLearn.length}
|
|
1527
|
+
\`\`\`
|
|
1528
|
+
|
|
1529
|
+
---
|
|
1530
|
+
_💡 TIP: Si algo no está claro, es una oportunidad de aprendizaje. Anota tus dudas._
|
|
1531
|
+
`;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
/**
|
|
1535
|
+
* Genera documentación "just-in-time" - exactamente lo que necesitas, cuando lo necesitas
|
|
1536
|
+
*/
|
|
1537
|
+
private generateJustInTimeDocumentation(concepts: Concept[]): string {
|
|
1538
|
+
let doc = '';
|
|
1539
|
+
|
|
1540
|
+
for (const concept of concepts) {
|
|
1541
|
+
doc += `
|
|
1542
|
+
### ${concept.icon} ${concept.name}
|
|
1543
|
+
|
|
1544
|
+
**¿Qué es?**
|
|
1545
|
+
${concept.whatIs}
|
|
1546
|
+
|
|
1547
|
+
**¿Por qué lo necesitas ahora?**
|
|
1548
|
+
${concept.whyNow}
|
|
1549
|
+
|
|
1550
|
+
**Lo esencial (2 minutos):**
|
|
1551
|
+
${concept.quickExplanation}
|
|
1552
|
+
|
|
1553
|
+
<details>
|
|
1554
|
+
<summary>📚 Quiero entender más a fondo</summary>
|
|
1555
|
+
|
|
1556
|
+
${concept.deepDive}
|
|
1557
|
+
|
|
1558
|
+
</details>
|
|
1559
|
+
|
|
1560
|
+
<details>
|
|
1561
|
+
<summary>⚠️ Errores comunes a evitar</summary>
|
|
1562
|
+
|
|
1563
|
+
${concept.commonMistakes}
|
|
1564
|
+
|
|
1565
|
+
</details>
|
|
1566
|
+
|
|
1567
|
+
---
|
|
1568
|
+
`;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
return doc;
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
/**
|
|
1575
|
+
* Genera preguntas de reflexión para consolidar aprendizaje
|
|
1576
|
+
*/
|
|
1577
|
+
private generateReflectionQuestions(concepts: Concept[]): string {
|
|
1578
|
+
const questions = concepts.flatMap(c => c.reflectionQuestions);
|
|
1579
|
+
return questions.map((q, i) => `${i + 1}. ${q}`).join('\n');
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
```
|
|
1583
|
+
|
|
1584
|
+
### Ejemplos de Tareas con Aprendizaje Progresivo
|
|
1585
|
+
|
|
1586
|
+
#### Tarea 1: Setup Inicial con Docker
|
|
1587
|
+
|
|
1588
|
+
```markdown
|
|
1589
|
+
## 🎯 Objetivo
|
|
1590
|
+
Configurar el entorno de desarrollo con Docker para que cualquier persona pueda ejecutar el proyecto.
|
|
1591
|
+
|
|
1592
|
+
---
|
|
1593
|
+
|
|
1594
|
+
## 📚 Lo que Aprenderás en Esta Tarea
|
|
1595
|
+
|
|
1596
|
+
- 🐳 **Docker Basics** - Qué es un contenedor y por qué nos importa
|
|
1597
|
+
- 📦 **Docker Compose** - Cómo orquestar múltiples servicios
|
|
1598
|
+
- 🔐 **Variables de Entorno** - Cómo configurar la app sin hardcodear valores
|
|
1599
|
+
|
|
1600
|
+
---
|
|
1601
|
+
|
|
1602
|
+
## 📖 Contexto: Lo que Necesitas Saber
|
|
1603
|
+
|
|
1604
|
+
### 🐳 Docker Basics
|
|
1605
|
+
|
|
1606
|
+
**¿Qué es?**
|
|
1607
|
+
Docker es una herramienta que "empaqueta" tu aplicación con todo lo que necesita para funcionar.
|
|
1608
|
+
|
|
1609
|
+
**¿Por qué lo necesitas ahora?**
|
|
1610
|
+
Porque sin Docker, cada persona del equipo tendría que instalar manualmente Node, PostgreSQL, Redis, etc. Con Docker, todo viene incluido.
|
|
1611
|
+
|
|
1612
|
+
**Lo esencial (2 minutos):**
|
|
1613
|
+
\`\`\`
|
|
1614
|
+
Imagina Docker como una "caja mágica":
|
|
1615
|
+
|
|
1616
|
+
┌─────────────────────────────────────┐
|
|
1617
|
+
│ CONTENEDOR │
|
|
1618
|
+
│ ┌─────────────────────────────┐ │
|
|
1619
|
+
│ │ Tu código │ │
|
|
1620
|
+
│ │ + Node.js 20 │ │
|
|
1621
|
+
│ │ + Dependencias (npm) │ │
|
|
1622
|
+
│ │ + Configuración │ │
|
|
1623
|
+
│ └─────────────────────────────┘ │
|
|
1624
|
+
│ │
|
|
1625
|
+
│ Esta caja funciona IGUAL en: │
|
|
1626
|
+
│ ✅ Tu laptop │
|
|
1627
|
+
│ ✅ La laptop de tu compañero │
|
|
1628
|
+
│ ✅ El servidor de producción │
|
|
1629
|
+
└─────────────────────────────────────┘
|
|
1630
|
+
\`\`\`
|
|
1631
|
+
|
|
1632
|
+
Comandos que usarás:
|
|
1633
|
+
- \`docker compose up\` → Inicia todo
|
|
1634
|
+
- \`docker compose down\` → Detiene todo
|
|
1635
|
+
- \`docker compose logs\` → Ve qué está pasando
|
|
1636
|
+
|
|
1637
|
+
<details>
|
|
1638
|
+
<summary>📚 Quiero entender más a fondo</summary>
|
|
1639
|
+
|
|
1640
|
+
**Imagen vs Contenedor:**
|
|
1641
|
+
- **Imagen**: Es como una "receta" o "plantilla". No cambia.
|
|
1642
|
+
- **Contenedor**: Es la "comida preparada" siguiendo la receta. Puedes tener varios.
|
|
1643
|
+
|
|
1644
|
+
**Dockerfile:**
|
|
1645
|
+
Es el archivo que dice cómo crear la imagen. Ejemplo simplificado:
|
|
1646
|
+
\`\`\`dockerfile
|
|
1647
|
+
FROM node:20 # Empezar con Node.js 20
|
|
1648
|
+
COPY . /app # Copiar tu código
|
|
1649
|
+
RUN npm install # Instalar dependencias
|
|
1650
|
+
CMD ["npm", "start"] # Comando para iniciar
|
|
1651
|
+
\`\`\`
|
|
1652
|
+
|
|
1653
|
+
</details>
|
|
1654
|
+
|
|
1655
|
+
<details>
|
|
1656
|
+
<summary>⚠️ Errores comunes a evitar</summary>
|
|
1657
|
+
|
|
1658
|
+
1. **"Docker no está corriendo"**
|
|
1659
|
+
- En macOS/Windows: Abre Docker Desktop
|
|
1660
|
+
- El icono 🐳 debe estar visible en la barra
|
|
1661
|
+
|
|
1662
|
+
2. **"El puerto ya está en uso"**
|
|
1663
|
+
- Algo más usa el puerto 3000
|
|
1664
|
+
- Solución: \`lsof -i :3000\` y matar el proceso
|
|
1665
|
+
|
|
1666
|
+
3. **"No se reflejan mis cambios"**
|
|
1667
|
+
- Verifica que el volumen está montado
|
|
1668
|
+
- Reinicia: \`docker compose restart app\`
|
|
1669
|
+
|
|
1670
|
+
</details>
|
|
1671
|
+
|
|
1672
|
+
---
|
|
1673
|
+
|
|
1674
|
+
### 📦 Docker Compose
|
|
1675
|
+
|
|
1676
|
+
**¿Qué es?**
|
|
1677
|
+
Una herramienta para definir y ejecutar aplicaciones con múltiples contenedores.
|
|
1678
|
+
|
|
1679
|
+
**¿Por qué lo necesitas ahora?**
|
|
1680
|
+
Tu app necesita: la aplicación + base de datos + quizás Redis. Docker Compose los coordina todos.
|
|
1681
|
+
|
|
1682
|
+
**Lo esencial (2 minutos):**
|
|
1683
|
+
\`\`\`yaml
|
|
1684
|
+
# docker-compose.yml simplificado
|
|
1685
|
+
services:
|
|
1686
|
+
app: # Tu aplicación
|
|
1687
|
+
build: .
|
|
1688
|
+
ports:
|
|
1689
|
+
- "3000:3000"
|
|
1690
|
+
depends_on:
|
|
1691
|
+
- db # Espera a que db esté lista
|
|
1692
|
+
|
|
1693
|
+
db: # PostgreSQL
|
|
1694
|
+
image: postgres:15
|
|
1695
|
+
environment:
|
|
1696
|
+
POSTGRES_PASSWORD: postgres
|
|
1697
|
+
\`\`\`
|
|
1698
|
+
|
|
1699
|
+
Un comando levanta todo: \`docker compose up\`
|
|
1700
|
+
|
|
1701
|
+
---
|
|
1702
|
+
|
|
1703
|
+
## 🛠️ Pasos para Completar
|
|
1704
|
+
|
|
1705
|
+
### Paso 1: Verificar Docker
|
|
1706
|
+
\`\`\`bash
|
|
1707
|
+
docker --version
|
|
1708
|
+
# Si falla → Instalar Docker Desktop
|
|
1709
|
+
\`\`\`
|
|
1710
|
+
💡 **Aprenderás**: Cómo verificar que las herramientas están instaladas
|
|
1711
|
+
|
|
1712
|
+
### Paso 2: Copiar configuración
|
|
1713
|
+
\`\`\`bash
|
|
1714
|
+
cp .env.example .env
|
|
1715
|
+
\`\`\`
|
|
1716
|
+
💡 **Aprenderás**: Las variables de entorno separan configuración del código
|
|
1717
|
+
|
|
1718
|
+
### Paso 3: Levantar servicios
|
|
1719
|
+
\`\`\`bash
|
|
1720
|
+
docker compose -f docker-compose.dev.yml up -d
|
|
1721
|
+
\`\`\`
|
|
1722
|
+
💡 **Aprenderás**: \`-d\` significa "detached" (en segundo plano)
|
|
1723
|
+
|
|
1724
|
+
### Paso 4: Verificar que funciona
|
|
1725
|
+
\`\`\`bash
|
|
1726
|
+
docker compose ps
|
|
1727
|
+
# Todos los servicios deben estar "Up"
|
|
1728
|
+
\`\`\`
|
|
1729
|
+
💡 **Aprenderás**: Cómo diagnosticar el estado de los contenedores
|
|
1730
|
+
|
|
1731
|
+
### Paso 5: Abrir la aplicación
|
|
1732
|
+
Abre http://localhost:3000
|
|
1733
|
+
|
|
1734
|
+
🎉 **¡Felicidades!** Tu entorno está funcionando.
|
|
1735
|
+
|
|
1736
|
+
---
|
|
1737
|
+
|
|
1738
|
+
## ✅ Criterios de Aceptación
|
|
1739
|
+
|
|
1740
|
+
- [ ] Docker está instalado y funcionando
|
|
1741
|
+
- [ ] \`docker compose ps\` muestra todos los servicios "Up"
|
|
1742
|
+
- [ ] http://localhost:3000 carga correctamente
|
|
1743
|
+
- [ ] Puedo ver los logs con \`docker compose logs\`
|
|
1744
|
+
|
|
1745
|
+
---
|
|
1746
|
+
|
|
1747
|
+
## 🎓 Reflexión Post-Tarea
|
|
1748
|
+
|
|
1749
|
+
Antes de marcar como completada, pregúntate:
|
|
1750
|
+
|
|
1751
|
+
1. ¿Podrías explicar a alguien qué es Docker en 30 segundos?
|
|
1752
|
+
2. ¿Qué comando usarías si necesitas ver por qué algo falló?
|
|
1753
|
+
3. ¿Por qué usamos \`.env\` en lugar de escribir las contraseñas directo en el código?
|
|
1754
|
+
4. Si un compañero clona el proyecto, ¿qué comandos debe ejecutar?
|
|
1755
|
+
|
|
1756
|
+
---
|
|
1757
|
+
|
|
1758
|
+
## 📈 Tu Progreso
|
|
1759
|
+
|
|
1760
|
+
\`\`\`
|
|
1761
|
+
Tarea 1 de 24
|
|
1762
|
+
[█░░░░░░░░░░░░░░░░░░░░░░░] 4%
|
|
1763
|
+
|
|
1764
|
+
Conceptos dominados: 3
|
|
1765
|
+
- ✅ Docker Basics
|
|
1766
|
+
- ✅ Docker Compose
|
|
1767
|
+
- ✅ Variables de Entorno
|
|
1768
|
+
\`\`\`
|
|
1769
|
+
```
|
|
1770
|
+
|
|
1771
|
+
#### Tarea 5: Crear Primer Endpoint de API
|
|
1772
|
+
|
|
1773
|
+
```markdown
|
|
1774
|
+
## 🎯 Objetivo
|
|
1775
|
+
Crear el endpoint GET /api/health que retorne el estado de la aplicación.
|
|
1776
|
+
|
|
1777
|
+
---
|
|
1778
|
+
|
|
1779
|
+
## 📚 Lo que Aprenderás en Esta Tarea
|
|
1780
|
+
|
|
1781
|
+
- 🌐 **API REST Basics** - Qué es una API y cómo estructurarla
|
|
1782
|
+
- 📝 **HTTP Methods** - GET, POST, PUT, DELETE y cuándo usar cada uno
|
|
1783
|
+
- 📊 **Status Codes** - Qué significan 200, 404, 500, etc.
|
|
1784
|
+
|
|
1785
|
+
---
|
|
1786
|
+
|
|
1787
|
+
## 🔗 Construyendo sobre lo Anterior
|
|
1788
|
+
|
|
1789
|
+
Esta tarea usa conceptos que ya practicaste:
|
|
1790
|
+
- ✅ Docker Compose (Tarea #1) - Tu app ya corre en contenedor
|
|
1791
|
+
- ✅ Variables de Entorno (Tarea #1) - Configuración lista
|
|
1792
|
+
- ✅ Estructura del Proyecto (Tarea #3) - Sabes dónde va cada archivo
|
|
1793
|
+
|
|
1794
|
+
---
|
|
1795
|
+
|
|
1796
|
+
## 📖 Contexto: Lo que Necesitas Saber
|
|
1797
|
+
|
|
1798
|
+
### 🌐 API REST Basics
|
|
1799
|
+
|
|
1800
|
+
**¿Qué es?**
|
|
1801
|
+
Una API (Application Programming Interface) es cómo tu frontend habla con tu backend. REST es un estilo de diseño para APIs.
|
|
1802
|
+
|
|
1803
|
+
**¿Por qué lo necesitas ahora?**
|
|
1804
|
+
Vas a crear tu primer "punto de comunicación" entre el cliente y el servidor.
|
|
1805
|
+
|
|
1806
|
+
**Lo esencial (2 minutos):**
|
|
1807
|
+
\`\`\`
|
|
1808
|
+
┌─────────────┐ HTTP Request ┌─────────────┐
|
|
1809
|
+
│ CLIENTE │ ───────────────────────────▶ │ SERVIDOR │
|
|
1810
|
+
│ (Browser) │ GET /api/health │ (Node.js) │
|
|
1811
|
+
│ │ │ │
|
|
1812
|
+
│ │ ◀─────────────────────────── │ │
|
|
1813
|
+
│ │ HTTP Response │ │
|
|
1814
|
+
│ │ { "status": "ok" } │ │
|
|
1815
|
+
└─────────────┘ └─────────────┘
|
|
1816
|
+
|
|
1817
|
+
La API es el "contrato" entre cliente y servidor:
|
|
1818
|
+
- El cliente hace PREGUNTAS (requests)
|
|
1819
|
+
- El servidor da RESPUESTAS (responses)
|
|
1820
|
+
\`\`\`
|
|
1821
|
+
|
|
1822
|
+
### 📝 HTTP Methods
|
|
1823
|
+
|
|
1824
|
+
**Lo esencial:**
|
|
1825
|
+
| Método | Cuándo usarlo | Ejemplo |
|
|
1826
|
+
|--------|--------------|---------|
|
|
1827
|
+
| GET | Obtener datos | GET /users → Lista de usuarios |
|
|
1828
|
+
| POST | Crear algo nuevo | POST /users → Crear usuario |
|
|
1829
|
+
| PUT | Actualizar (completo) | PUT /users/1 → Reemplazar usuario 1 |
|
|
1830
|
+
| PATCH | Actualizar (parcial) | PATCH /users/1 → Modificar usuario 1 |
|
|
1831
|
+
| DELETE | Eliminar | DELETE /users/1 → Borrar usuario 1 |
|
|
1832
|
+
|
|
1833
|
+
💡 **Hoy usarás GET** - Solo estás obteniendo información del estado.
|
|
1834
|
+
|
|
1835
|
+
### 📊 Status Codes
|
|
1836
|
+
|
|
1837
|
+
**Los que más usarás:**
|
|
1838
|
+
\`\`\`
|
|
1839
|
+
2xx = ✅ Todo bien
|
|
1840
|
+
200 OK - Éxito general
|
|
1841
|
+
201 Created - Se creó algo nuevo
|
|
1842
|
+
|
|
1843
|
+
4xx = ❌ Error del cliente
|
|
1844
|
+
400 Bad Request - Datos inválidos
|
|
1845
|
+
401 Unauthorized - No autenticado
|
|
1846
|
+
404 Not Found - No existe
|
|
1847
|
+
|
|
1848
|
+
5xx = 💥 Error del servidor
|
|
1849
|
+
500 Internal Server Error - Algo falló en el server
|
|
1850
|
+
\`\`\`
|
|
1851
|
+
|
|
1852
|
+
---
|
|
1853
|
+
|
|
1854
|
+
## 🛠️ Pasos para Completar
|
|
1855
|
+
|
|
1856
|
+
### Paso 1: Crear el archivo del endpoint
|
|
1857
|
+
\`\`\`bash
|
|
1858
|
+
# Ubicación: src/routes/health.ts
|
|
1859
|
+
\`\`\`
|
|
1860
|
+
💡 **Aprenderás**: Los endpoints se organizan en archivos separados por recurso
|
|
1861
|
+
|
|
1862
|
+
### Paso 2: Implementar el endpoint
|
|
1863
|
+
\`\`\`typescript
|
|
1864
|
+
// src/routes/health.ts
|
|
1865
|
+
import { Router } from 'express';
|
|
1866
|
+
|
|
1867
|
+
const router = Router();
|
|
1868
|
+
|
|
1869
|
+
// GET /api/health
|
|
1870
|
+
router.get('/', (req, res) => {
|
|
1871
|
+
// 💡 res.json() automáticamente:
|
|
1872
|
+
// - Convierte el objeto a JSON
|
|
1873
|
+
// - Agrega header Content-Type: application/json
|
|
1874
|
+
// - Envía status 200 por defecto
|
|
1875
|
+
|
|
1876
|
+
res.json({
|
|
1877
|
+
status: 'ok',
|
|
1878
|
+
timestamp: new Date().toISOString(),
|
|
1879
|
+
uptime: process.uptime()
|
|
1880
|
+
});
|
|
1881
|
+
});
|
|
1882
|
+
|
|
1883
|
+
export default router;
|
|
1884
|
+
\`\`\`
|
|
1885
|
+
💡 **Aprenderás**: La estructura básica de un endpoint en Express
|
|
1886
|
+
|
|
1887
|
+
### Paso 3: Registrar la ruta
|
|
1888
|
+
\`\`\`typescript
|
|
1889
|
+
// src/app.ts
|
|
1890
|
+
import healthRoutes from './routes/health';
|
|
1891
|
+
|
|
1892
|
+
app.use('/api/health', healthRoutes);
|
|
1893
|
+
\`\`\`
|
|
1894
|
+
💡 **Aprenderás**: Cómo conectar rutas con la aplicación principal
|
|
1895
|
+
|
|
1896
|
+
### Paso 4: Probar el endpoint
|
|
1897
|
+
\`\`\`bash
|
|
1898
|
+
curl http://localhost:3000/api/health
|
|
1899
|
+
|
|
1900
|
+
# Respuesta esperada:
|
|
1901
|
+
# {"status":"ok","timestamp":"2024-...","uptime":123.456}
|
|
1902
|
+
\`\`\`
|
|
1903
|
+
💡 **Aprenderás**: Usar curl para probar APIs sin frontend
|
|
1904
|
+
|
|
1905
|
+
---
|
|
1906
|
+
|
|
1907
|
+
## ✅ Criterios de Aceptación
|
|
1908
|
+
|
|
1909
|
+
- [ ] GET /api/health retorna status 200
|
|
1910
|
+
- [ ] La respuesta incluye { status: 'ok' }
|
|
1911
|
+
- [ ] La respuesta incluye timestamp
|
|
1912
|
+
- [ ] curl funciona correctamente
|
|
1913
|
+
|
|
1914
|
+
---
|
|
1915
|
+
|
|
1916
|
+
## 🎓 Reflexión Post-Tarea
|
|
1917
|
+
|
|
1918
|
+
1. ¿Por qué el endpoint es GET y no POST?
|
|
1919
|
+
2. ¿Qué status code retornarías si la base de datos estuviera caída?
|
|
1920
|
+
3. ¿Por qué separamos las rutas en archivos diferentes?
|
|
1921
|
+
4. ¿Qué información adicional podría ser útil en un health check?
|
|
1922
|
+
|
|
1923
|
+
---
|
|
1924
|
+
|
|
1925
|
+
## 📈 Tu Progreso
|
|
1926
|
+
|
|
1927
|
+
\`\`\`
|
|
1928
|
+
Tarea 5 de 24
|
|
1929
|
+
[█████░░░░░░░░░░░░░░░░░░░] 21%
|
|
1930
|
+
|
|
1931
|
+
Conceptos dominados: 8
|
|
1932
|
+
Nuevos en esta tarea:
|
|
1933
|
+
- ✅ API REST Basics
|
|
1934
|
+
- ✅ HTTP Methods
|
|
1935
|
+
- ✅ Status Codes
|
|
1936
|
+
\`\`\`
|
|
1937
|
+
```
|
|
1938
|
+
|
|
1939
|
+
### Mapa de Aprendizaje Visual
|
|
1940
|
+
|
|
1941
|
+
```typescript
|
|
1942
|
+
class LearningPathVisualizer {
|
|
1943
|
+
generateLearningMap(completedTasks: number): string {
|
|
1944
|
+
return `
|
|
1945
|
+
# 🗺️ Tu Mapa de Aprendizaje
|
|
1946
|
+
|
|
1947
|
+
\`\`\`
|
|
1948
|
+
🎓 NIVEL 4: Producción
|
|
1949
|
+
┌─────────────────────┐
|
|
1950
|
+
│ □ Deployment │
|
|
1951
|
+
│ □ Monitoring │
|
|
1952
|
+
└──────────┬──────────┘
|
|
1953
|
+
│
|
|
1954
|
+
🎓 NIVEL 3: Avanzado
|
|
1955
|
+
┌──────────────────────────┼──────────────────────────┐
|
|
1956
|
+
│ │ │
|
|
1957
|
+
┌──────┴──────┐ ┌───────┴───────┐ ┌───────┴───────┐
|
|
1958
|
+
│ ✅ CI/CD │ │ □ Auth JWT │ │ □ Testing Int │
|
|
1959
|
+
└──────┬──────┘ └───────┬───────┘ └───────┬───────┘
|
|
1960
|
+
│ │ │
|
|
1961
|
+
🎓 NIVEL 2: Intermedio
|
|
1962
|
+
┌──────────────────────────┼──────────────────────────┐
|
|
1963
|
+
│ │ │
|
|
1964
|
+
┌──────┴──────┐ ┌───────┴───────┐ ┌───────┴───────┐
|
|
1965
|
+
│ ✅ API REST │ │ ✅ Database │ │ □ Unit Tests │
|
|
1966
|
+
└──────┬──────┘ └───────┬───────┘ └───────┬───────┘
|
|
1967
|
+
│ │ │
|
|
1968
|
+
🎓 NIVEL 1: Fundamentos
|
|
1969
|
+
┌──────────────────────────┼──────────────────────────┐
|
|
1970
|
+
│ │ │
|
|
1971
|
+
┌──────┴──────┐ ┌───────┴───────┐ ┌───────┴───────┐
|
|
1972
|
+
│ ✅ Docker │ │ ✅ Env Vars │ │ ✅ Git Flow │
|
|
1973
|
+
└─────────────┘ └───────────────┘ └───────────────┘
|
|
1974
|
+
|
|
1975
|
+
✅ = Dominado □ = Por aprender 🔄 = En progreso
|
|
1976
|
+
\`\`\`
|
|
1977
|
+
|
|
1978
|
+
## 📊 Estadísticas de Aprendizaje
|
|
1979
|
+
|
|
1980
|
+
| Nivel | Conceptos | Completados | Progreso |
|
|
1981
|
+
|-------|-----------|-------------|----------|
|
|
1982
|
+
| 1. Fundamentos | 3 | 3 | ████████████ 100% |
|
|
1983
|
+
| 2. Intermedio | 3 | 2 | ████████░░░░ 67% |
|
|
1984
|
+
| 3. Avanzado | 3 | 1 | ████░░░░░░░░ 33% |
|
|
1985
|
+
| 4. Producción | 2 | 0 | ░░░░░░░░░░░░ 0% |
|
|
1986
|
+
|
|
1987
|
+
**Total: 6/11 conceptos dominados (55%)**
|
|
1988
|
+
`;
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
```
|
|
1992
|
+
|
|
1993
|
+
---
|
|
1994
|
+
|
|
1995
|
+
## 🎯 Salida Esperada del Nuevo Plan
|
|
1996
|
+
|
|
1997
|
+
```
|
|
1998
|
+
🚀 Freelance Project Planner v3.0
|
|
1999
|
+
📦 Filosofía: Infrastructure First + Aprendizaje Progresivo
|
|
2000
|
+
=====================================
|
|
2001
|
+
|
|
2002
|
+
📊 FASE 0: Análisis del Proyecto
|
|
2003
|
+
---------------------------------
|
|
2004
|
+
✅ Proyecto: mi-ecommerce-app
|
|
2005
|
+
✅ Tech Stack: Next.js + PostgreSQL + Redis
|
|
2006
|
+
✅ Completitud: 45%
|
|
2007
|
+
|
|
2008
|
+
🐳 FASE 1: Dockerización (PRIORIDAD MÁXIMA)
|
|
2009
|
+
---------------------------------
|
|
2010
|
+
✅ Dockerfile creado (multi-stage)
|
|
2011
|
+
✅ docker-compose.dev.yml creado
|
|
2012
|
+
✅ docker-compose.prod.yml creado
|
|
2013
|
+
✅ .dockerignore optimizado
|
|
2014
|
+
|
|
2015
|
+
⚙️ FASE 2: GitHub Actions (CI/CD)
|
|
2016
|
+
---------------------------------
|
|
2017
|
+
✅ .github/workflows/ci.yml
|
|
2018
|
+
✅ .github/workflows/docker-build.yml
|
|
2019
|
+
✅ .github/workflows/deploy.yml
|
|
2020
|
+
|
|
2021
|
+
📋 FASE 3: Issues con APRENDIZAJE PROGRESIVO
|
|
2022
|
+
---------------------------------
|
|
2023
|
+
✅ 24 issues creados con estructura de aprendizaje:
|
|
2024
|
+
|
|
2025
|
+
Cada issue incluye:
|
|
2026
|
+
├── 🎯 Objetivo de la tarea
|
|
2027
|
+
├── 📚 Lo que aprenderás (conceptos nuevos)
|
|
2028
|
+
├── 🔗 Conexión con tareas anteriores
|
|
2029
|
+
├── 📖 Contexto just-in-time (explicación cuando la necesitas)
|
|
2030
|
+
├── 🛠️ Pasos con notas de aprendizaje
|
|
2031
|
+
├── ✅ Criterios de aceptación
|
|
2032
|
+
├── 🎓 Reflexión post-tarea
|
|
2033
|
+
└── 📈 Barra de progreso visual
|
|
2034
|
+
|
|
2035
|
+
📚 Mapa de Aprendizaje Generado:
|
|
2036
|
+
---------------------------------
|
|
2037
|
+
NIVEL 1 (Fundamentos):
|
|
2038
|
+
└── Docker Basics → Docker Compose → Env Variables → Git Flow
|
|
2039
|
+
|
|
2040
|
+
NIVEL 2 (Intermedio):
|
|
2041
|
+
└── API REST → Database Basics → Unit Testing
|
|
2042
|
+
|
|
2043
|
+
NIVEL 3 (Avanzado):
|
|
2044
|
+
└── Authentication → Integration Tests → CI/CD
|
|
2045
|
+
|
|
2046
|
+
NIVEL 4 (Producción):
|
|
2047
|
+
└── Deployment → Monitoring
|
|
2048
|
+
|
|
2049
|
+
🗺️ Ruta de Aprendizaje:
|
|
2050
|
+
---------------------------------
|
|
2051
|
+
Tarea 1: Docker Setup
|
|
2052
|
+
└── 📚 Aprende: Docker, Compose, Env Vars
|
|
2053
|
+
|
|
2054
|
+
Tarea 2: Estructura del Proyecto
|
|
2055
|
+
└── 📚 Aprende: Arquitectura, Convenciones
|
|
2056
|
+
└── 🔗 Usa: Docker (Tarea 1)
|
|
2057
|
+
|
|
2058
|
+
Tarea 3: Primer Endpoint
|
|
2059
|
+
└── 📚 Aprende: REST, HTTP Methods, Status Codes
|
|
2060
|
+
└── 🔗 Usa: Docker + Estructura
|
|
2061
|
+
|
|
2062
|
+
Tarea 4: Conexión a Base de Datos
|
|
2063
|
+
└── 📚 Aprende: SQL, ORM, Migrations
|
|
2064
|
+
└── 🔗 Usa: Docker + Endpoints
|
|
2065
|
+
|
|
2066
|
+
... y así sucesivamente
|
|
2067
|
+
|
|
2068
|
+
=====================================
|
|
2069
|
+
✅ ¡Setup Completado!
|
|
2070
|
+
|
|
2071
|
+
🎓 Enfoque de Aprendizaje:
|
|
2072
|
+
- Cada tarea introduce conceptos CUANDO los necesitas
|
|
2073
|
+
- Explicaciones "just-in-time", no antes
|
|
2074
|
+
- Conexión clara entre lo que ya sabes y lo nuevo
|
|
2075
|
+
- Reflexión al final para consolidar conocimiento
|
|
2076
|
+
- Barra de progreso visual de conceptos dominados
|
|
2077
|
+
|
|
2078
|
+
📋 Primera tarea recomendada:
|
|
2079
|
+
#1 - Setup Docker
|
|
2080
|
+
└── 📚 Aprenderás: Docker Basics, Compose, Env Variables
|
|
2081
|
+
=====================================
|
|
2082
|
+
```
|
|
2083
|
+
|
|
2084
|
+
---
|
|
2085
|
+
|
|
2086
|
+
## 🔑 Resumen de Cambios
|
|
2087
|
+
|
|
2088
|
+
| Antes | Ahora |
|
|
2089
|
+
|-------|-------|
|
|
2090
|
+
| 1. Análisis | 0. Análisis |
|
|
2091
|
+
| 2. Estabilización | **1. 🐳 Docker (PRIORIDAD MÁXIMA)** |
|
|
2092
|
+
| 3. CI/CD | **2. ⚙️ GitHub Actions (SEGUNDA PRIORIDAD)** |
|
|
2093
|
+
| 4. Issues/Backlog | **3. 📚 Issues con APRENDIZAJE PROGRESIVO** |
|
|
2094
|
+
| 5. Desarrollo | 4. Desarrollo |
|
|
2095
|
+
| 6. Documentación estática | **Integrada en cada tarea** |
|
|
2096
|
+
|
|
2097
|
+
### 📚 Enfoque de Aprendizaje Progresivo
|
|
2098
|
+
|
|
2099
|
+
| Tradicional | Progresivo (Este agente) |
|
|
2100
|
+
|-------------|--------------------------|
|
|
2101
|
+
| 📖 Leer toda la documentación al inicio | 📚 Aprender cuando lo necesitas |
|
|
2102
|
+
| 😫 Olvidar el 80% antes de usarlo | 🧠 Retención alta por contexto |
|
|
2103
|
+
| 📄 Documentación separada del código | 🔗 Aprendizaje integrado en tareas |
|
|
2104
|
+
| ❓ "¿Para qué era esto?" | 💡 "Necesito esto AHORA para mi tarea" |
|
|
2105
|
+
|
|
2106
|
+
### Estructura de Cada Issue/Tarea
|
|
2107
|
+
|
|
2108
|
+
```markdown
|
|
2109
|
+
## 🎯 Objetivo
|
|
2110
|
+
[Qué vas a construir]
|
|
2111
|
+
|
|
2112
|
+
## 📚 Lo que Aprenderás
|
|
2113
|
+
[Conceptos nuevos - SOLO cuando los necesitas]
|
|
2114
|
+
|
|
2115
|
+
## 🔗 Conexión con lo Anterior
|
|
2116
|
+
[Cómo se relaciona con tareas previas]
|
|
2117
|
+
|
|
2118
|
+
## 📖 Contexto Just-in-Time
|
|
2119
|
+
[Mini-explicación de conceptos cuando los necesitas]
|
|
2120
|
+
|
|
2121
|
+
## 🛠️ Pasos
|
|
2122
|
+
[Con notas de aprendizaje en cada paso]
|
|
2123
|
+
|
|
2124
|
+
## 🎓 Reflexión Post-Tarea
|
|
2125
|
+
[Preguntas para consolidar el conocimiento]
|
|
2126
|
+
|
|
2127
|
+
## 📈 Tu Progreso
|
|
2128
|
+
[Barra visual de conceptos dominados]
|
|
2129
|
+
```
|
|
2130
|
+
|
|
2131
|
+
El plan ahora garantiza que:
|
|
2132
|
+
1. **Docker** - Entorno reproducible desde el día 1
|
|
2133
|
+
2. **GitHub Actions** - Feedback automático en cada push
|
|
2134
|
+
3. **Aprendizaje Progresivo** - Cada tarea enseña conceptos cuando son relevantes
|
|
2135
|
+
|
|
2136
|
+
**El resultado**: Un desarrollador que no solo completa tareas, sino que **entiende** lo que está haciendo y **por qué**.
|