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.
Files changed (500) hide show
  1. package/.gitignore.template +105 -0
  2. package/.releaserc +44 -0
  3. package/README.md +45 -0
  4. package/ai-config/.skillignore +15 -0
  5. package/ai-config/AUTO_INVOKE.md +300 -0
  6. package/ai-config/agents/_TEMPLATE.md +93 -0
  7. package/ai-config/agents/business/api-designer.md +1657 -0
  8. package/ai-config/agents/business/business-analyst.md +1331 -0
  9. package/ai-config/agents/business/product-strategist.md +206 -0
  10. package/ai-config/agents/business/project-manager.md +178 -0
  11. package/ai-config/agents/business/requirements-analyst.md +1277 -0
  12. package/ai-config/agents/business/technical-writer.md +1679 -0
  13. package/ai-config/agents/creative/ux-designer.md +205 -0
  14. package/ai-config/agents/data-ai/ai-engineer.md +487 -0
  15. package/ai-config/agents/data-ai/analytics-engineer.md +953 -0
  16. package/ai-config/agents/data-ai/data-engineer.md +173 -0
  17. package/ai-config/agents/data-ai/data-scientist.md +672 -0
  18. package/ai-config/agents/data-ai/mlops-engineer.md +814 -0
  19. package/ai-config/agents/data-ai/prompt-engineer.md +772 -0
  20. package/ai-config/agents/development/angular-expert.md +620 -0
  21. package/ai-config/agents/development/backend-architect.md +795 -0
  22. package/ai-config/agents/development/database-specialist.md +212 -0
  23. package/ai-config/agents/development/frontend-specialist.md +686 -0
  24. package/ai-config/agents/development/fullstack-engineer.md +668 -0
  25. package/ai-config/agents/development/golang-pro.md +338 -0
  26. package/ai-config/agents/development/java-enterprise.md +400 -0
  27. package/ai-config/agents/development/javascript-pro.md +422 -0
  28. package/ai-config/agents/development/nextjs-pro.md +474 -0
  29. package/ai-config/agents/development/python-pro.md +570 -0
  30. package/ai-config/agents/development/react-pro.md +487 -0
  31. package/ai-config/agents/development/rust-pro.md +246 -0
  32. package/ai-config/agents/development/spring-boot-4-expert.md +326 -0
  33. package/ai-config/agents/development/typescript-pro.md +336 -0
  34. package/ai-config/agents/development/vue-specialist.md +605 -0
  35. package/ai-config/agents/infrastructure/cloud-architect.md +472 -0
  36. package/ai-config/agents/infrastructure/deployment-manager.md +358 -0
  37. package/ai-config/agents/infrastructure/devops-engineer.md +455 -0
  38. package/ai-config/agents/infrastructure/incident-responder.md +519 -0
  39. package/ai-config/agents/infrastructure/kubernetes-expert.md +705 -0
  40. package/ai-config/agents/infrastructure/monitoring-specialist.md +674 -0
  41. package/ai-config/agents/infrastructure/performance-engineer.md +658 -0
  42. package/ai-config/agents/orchestrator.md +241 -0
  43. package/ai-config/agents/quality/accessibility-auditor.md +1204 -0
  44. package/ai-config/agents/quality/code-reviewer-compact.md +123 -0
  45. package/ai-config/agents/quality/code-reviewer.md +363 -0
  46. package/ai-config/agents/quality/dependency-manager.md +743 -0
  47. package/ai-config/agents/quality/e2e-test-specialist.md +1005 -0
  48. package/ai-config/agents/quality/performance-tester.md +1086 -0
  49. package/ai-config/agents/quality/security-auditor.md +133 -0
  50. package/ai-config/agents/quality/test-engineer.md +453 -0
  51. package/ai-config/agents/specialists/api-designer.md +87 -0
  52. package/ai-config/agents/specialists/backend-architect.md +73 -0
  53. package/ai-config/agents/specialists/code-reviewer.md +77 -0
  54. package/ai-config/agents/specialists/db-optimizer.md +75 -0
  55. package/ai-config/agents/specialists/devops-engineer.md +83 -0
  56. package/ai-config/agents/specialists/documentation-writer.md +78 -0
  57. package/ai-config/agents/specialists/frontend-developer.md +75 -0
  58. package/ai-config/agents/specialists/performance-analyst.md +82 -0
  59. package/ai-config/agents/specialists/refactor-specialist.md +74 -0
  60. package/ai-config/agents/specialists/security-auditor.md +74 -0
  61. package/ai-config/agents/specialists/test-engineer.md +81 -0
  62. package/ai-config/agents/specialists/ux-consultant.md +76 -0
  63. package/ai-config/agents/specialized/agent-generator.md +1190 -0
  64. package/ai-config/agents/specialized/blockchain-developer.md +149 -0
  65. package/ai-config/agents/specialized/code-migrator.md +892 -0
  66. package/ai-config/agents/specialized/context-manager.md +978 -0
  67. package/ai-config/agents/specialized/documentation-writer.md +1078 -0
  68. package/ai-config/agents/specialized/ecommerce-expert.md +1756 -0
  69. package/ai-config/agents/specialized/embedded-engineer.md +1714 -0
  70. package/ai-config/agents/specialized/error-detective.md +1034 -0
  71. package/ai-config/agents/specialized/fintech-specialist.md +1659 -0
  72. package/ai-config/agents/specialized/freelance-project-planner-v2.md +1988 -0
  73. package/ai-config/agents/specialized/freelance-project-planner-v3.md +2136 -0
  74. package/ai-config/agents/specialized/freelance-project-planner-v4.md +4503 -0
  75. package/ai-config/agents/specialized/freelance-project-planner.md +722 -0
  76. package/ai-config/agents/specialized/game-developer.md +1963 -0
  77. package/ai-config/agents/specialized/healthcare-dev.md +1620 -0
  78. package/ai-config/agents/specialized/mobile-developer.md +188 -0
  79. package/ai-config/agents/specialized/parallel-plan-executor.md +506 -0
  80. package/ai-config/agents/specialized/plan-executor.md +485 -0
  81. package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +485 -0
  82. package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +3493 -0
  83. package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +778 -0
  84. package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +918 -0
  85. package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +1537 -0
  86. package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +2633 -0
  87. package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +5610 -0
  88. package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +335 -0
  89. package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +215 -0
  90. package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +260 -0
  91. package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +379 -0
  92. package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +355 -0
  93. package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +279 -0
  94. package/ai-config/agents/specialized/template-writer.md +347 -0
  95. package/ai-config/agents/specialized/test-runner.md +99 -0
  96. package/ai-config/agents/specialized/vibekanban-smart-worker.md +244 -0
  97. package/ai-config/agents/specialized/wave-executor.md +138 -0
  98. package/ai-config/agents/specialized/workflow-optimizer.md +1114 -0
  99. package/ai-config/commands/git/changelog.md +32 -0
  100. package/ai-config/commands/git/ci-local.md +70 -0
  101. package/ai-config/commands/git/commit.md +35 -0
  102. package/ai-config/commands/git/fix-issue.md +23 -0
  103. package/ai-config/commands/git/pr-create.md +42 -0
  104. package/ai-config/commands/git/pr-review.md +50 -0
  105. package/ai-config/commands/git/worktree.md +39 -0
  106. package/ai-config/commands/refactoring/cleanup.md +24 -0
  107. package/ai-config/commands/refactoring/dead-code.md +40 -0
  108. package/ai-config/commands/refactoring/extract.md +31 -0
  109. package/ai-config/commands/testing/e2e.md +30 -0
  110. package/ai-config/commands/testing/tdd.md +36 -0
  111. package/ai-config/commands/testing/test-coverage.md +30 -0
  112. package/ai-config/commands/testing/test-fix.md +24 -0
  113. package/ai-config/commands/workflow/generate-agents-md.md +85 -0
  114. package/ai-config/commands/workflow/planning.md +47 -0
  115. package/ai-config/commands/workflows/compound.md +89 -0
  116. package/ai-config/commands/workflows/plan.md +77 -0
  117. package/ai-config/commands/workflows/review.md +78 -0
  118. package/ai-config/commands/workflows/work.md +75 -0
  119. package/ai-config/config.yaml +18 -0
  120. package/ai-config/hooks/_TEMPLATE.md +96 -0
  121. package/ai-config/hooks/block-dangerous-commands.md +75 -0
  122. package/ai-config/hooks/commit-guard.md +90 -0
  123. package/ai-config/hooks/context-loader.md +73 -0
  124. package/ai-config/hooks/improve-prompt.md +91 -0
  125. package/ai-config/hooks/learning-log.md +72 -0
  126. package/ai-config/hooks/model-router.md +86 -0
  127. package/ai-config/hooks/secret-scanner.md +64 -0
  128. package/ai-config/hooks/skill-validator.md +102 -0
  129. package/ai-config/hooks/task-artifact.md +114 -0
  130. package/ai-config/hooks/validate-workflow.md +100 -0
  131. package/ai-config/prompts/base.md +71 -0
  132. package/ai-config/prompts/modes/debug.md +34 -0
  133. package/ai-config/prompts/modes/deploy.md +40 -0
  134. package/ai-config/prompts/modes/research.md +32 -0
  135. package/ai-config/prompts/modes/review.md +33 -0
  136. package/ai-config/prompts/review-policy.md +79 -0
  137. package/ai-config/skills/_TEMPLATE.md +157 -0
  138. package/ai-config/skills/backend/api-gateway/SKILL.md +254 -0
  139. package/ai-config/skills/backend/bff-concepts/SKILL.md +239 -0
  140. package/ai-config/skills/backend/bff-spring/SKILL.md +364 -0
  141. package/ai-config/skills/backend/chi-router/SKILL.md +396 -0
  142. package/ai-config/skills/backend/error-handling/SKILL.md +255 -0
  143. package/ai-config/skills/backend/exceptions-spring/SKILL.md +323 -0
  144. package/ai-config/skills/backend/fastapi/SKILL.md +302 -0
  145. package/ai-config/skills/backend/gateway-spring/SKILL.md +390 -0
  146. package/ai-config/skills/backend/go-backend/SKILL.md +457 -0
  147. package/ai-config/skills/backend/gradle-multimodule/SKILL.md +274 -0
  148. package/ai-config/skills/backend/graphql-concepts/SKILL.md +352 -0
  149. package/ai-config/skills/backend/graphql-spring/SKILL.md +398 -0
  150. package/ai-config/skills/backend/grpc-concepts/SKILL.md +283 -0
  151. package/ai-config/skills/backend/grpc-spring/SKILL.md +445 -0
  152. package/ai-config/skills/backend/jwt-auth/SKILL.md +412 -0
  153. package/ai-config/skills/backend/notifications-concepts/SKILL.md +259 -0
  154. package/ai-config/skills/backend/recommendations-concepts/SKILL.md +261 -0
  155. package/ai-config/skills/backend/search-concepts/SKILL.md +263 -0
  156. package/ai-config/skills/backend/search-spring/SKILL.md +375 -0
  157. package/ai-config/skills/backend/spring-boot-4/SKILL.md +172 -0
  158. package/ai-config/skills/backend/websockets/SKILL.md +532 -0
  159. package/ai-config/skills/data-ai/ai-ml/SKILL.md +423 -0
  160. package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +195 -0
  161. package/ai-config/skills/data-ai/analytics-spring/SKILL.md +340 -0
  162. package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +440 -0
  163. package/ai-config/skills/data-ai/langchain/SKILL.md +238 -0
  164. package/ai-config/skills/data-ai/mlflow/SKILL.md +302 -0
  165. package/ai-config/skills/data-ai/onnx-inference/SKILL.md +290 -0
  166. package/ai-config/skills/data-ai/powerbi/SKILL.md +352 -0
  167. package/ai-config/skills/data-ai/pytorch/SKILL.md +274 -0
  168. package/ai-config/skills/data-ai/scikit-learn/SKILL.md +321 -0
  169. package/ai-config/skills/data-ai/vector-db/SKILL.md +301 -0
  170. package/ai-config/skills/database/graph-databases/SKILL.md +218 -0
  171. package/ai-config/skills/database/graph-spring/SKILL.md +361 -0
  172. package/ai-config/skills/database/pgx-postgres/SKILL.md +512 -0
  173. package/ai-config/skills/database/redis-cache/SKILL.md +343 -0
  174. package/ai-config/skills/database/sqlite-embedded/SKILL.md +388 -0
  175. package/ai-config/skills/database/timescaledb/SKILL.md +320 -0
  176. package/ai-config/skills/docs/api-documentation/SKILL.md +293 -0
  177. package/ai-config/skills/docs/docs-spring/SKILL.md +377 -0
  178. package/ai-config/skills/docs/mustache-templates/SKILL.md +190 -0
  179. package/ai-config/skills/docs/technical-docs/SKILL.md +447 -0
  180. package/ai-config/skills/frontend/astro-ssr/SKILL.md +441 -0
  181. package/ai-config/skills/frontend/frontend-design/SKILL.md +54 -0
  182. package/ai-config/skills/frontend/frontend-web/SKILL.md +368 -0
  183. package/ai-config/skills/frontend/mantine-ui/SKILL.md +396 -0
  184. package/ai-config/skills/frontend/tanstack-query/SKILL.md +439 -0
  185. package/ai-config/skills/frontend/zod-validation/SKILL.md +417 -0
  186. package/ai-config/skills/frontend/zustand-state/SKILL.md +350 -0
  187. package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +244 -0
  188. package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +378 -0
  189. package/ai-config/skills/infrastructure/devops-infra/SKILL.md +435 -0
  190. package/ai-config/skills/infrastructure/docker-containers/SKILL.md +420 -0
  191. package/ai-config/skills/infrastructure/kubernetes/SKILL.md +456 -0
  192. package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +546 -0
  193. package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +474 -0
  194. package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +315 -0
  195. package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +504 -0
  196. package/ai-config/skills/mobile/mobile-ionic/SKILL.md +448 -0
  197. package/ai-config/skills/prompt-improver/SKILL.md +125 -0
  198. package/ai-config/skills/quality/ghagga-review/SKILL.md +216 -0
  199. package/ai-config/skills/references/hooks-patterns/SKILL.md +238 -0
  200. package/ai-config/skills/references/mcp-servers/SKILL.md +275 -0
  201. package/ai-config/skills/references/plugins-reference/SKILL.md +110 -0
  202. package/ai-config/skills/references/skills-reference/SKILL.md +420 -0
  203. package/ai-config/skills/references/subagent-templates/SKILL.md +193 -0
  204. package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +410 -0
  205. package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +408 -0
  206. package/ai-config/skills/systems-iot/rust-systems/SKILL.md +386 -0
  207. package/ai-config/skills/systems-iot/tokio-async/SKILL.md +324 -0
  208. package/ai-config/skills/testing/playwright-e2e/SKILL.md +289 -0
  209. package/ai-config/skills/testing/testcontainers/SKILL.md +299 -0
  210. package/ai-config/skills/testing/vitest-testing/SKILL.md +381 -0
  211. package/ai-config/skills/workflow/ci-local-guide/SKILL.md +118 -0
  212. package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +299 -0
  213. package/ai-config/skills/workflow/claude-md-improver/SKILL.md +158 -0
  214. package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +117 -0
  215. package/ai-config/skills/workflow/git-github/SKILL.md +334 -0
  216. package/ai-config/skills/workflow/git-github/references/examples.md +160 -0
  217. package/ai-config/skills/workflow/git-workflow/SKILL.md +214 -0
  218. package/ai-config/skills/workflow/ide-plugins/SKILL.md +277 -0
  219. package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +401 -0
  220. package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +199 -0
  221. package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +100 -0
  222. package/ai-config/skills/workflow/verification-before-completion/SKILL.md +73 -0
  223. package/ai-config/skills/workflow/wave-workflow/SKILL.md +178 -0
  224. package/ci-local/README.md +170 -0
  225. package/ci-local/ci-local.sh +297 -0
  226. package/ci-local/hooks/commit-msg +74 -0
  227. package/ci-local/hooks/pre-commit +162 -0
  228. package/ci-local/hooks/pre-push +41 -0
  229. package/ci-local/install.sh +49 -0
  230. package/ci-local/semgrep.yml +214 -0
  231. package/dist/commands/analyze.d.ts +9 -0
  232. package/dist/commands/analyze.d.ts.map +1 -0
  233. package/dist/commands/analyze.js +55 -0
  234. package/dist/commands/analyze.js.map +1 -0
  235. package/dist/commands/analyze.test.d.ts +2 -0
  236. package/dist/commands/analyze.test.d.ts.map +1 -0
  237. package/dist/commands/analyze.test.js +145 -0
  238. package/dist/commands/analyze.test.js.map +1 -0
  239. package/dist/commands/doctor.d.ts +7 -0
  240. package/dist/commands/doctor.d.ts.map +1 -0
  241. package/dist/commands/doctor.js +158 -0
  242. package/dist/commands/doctor.js.map +1 -0
  243. package/dist/commands/doctor.test.d.ts +2 -0
  244. package/dist/commands/doctor.test.d.ts.map +1 -0
  245. package/dist/commands/doctor.test.js +200 -0
  246. package/dist/commands/doctor.test.js.map +1 -0
  247. package/dist/commands/init.d.ts +9 -0
  248. package/dist/commands/init.d.ts.map +1 -0
  249. package/dist/commands/init.js +283 -0
  250. package/dist/commands/init.js.map +1 -0
  251. package/dist/commands/init.test.d.ts +2 -0
  252. package/dist/commands/init.test.d.ts.map +1 -0
  253. package/dist/commands/init.test.js +271 -0
  254. package/dist/commands/init.test.js.map +1 -0
  255. package/dist/commands/sync.d.ts +8 -0
  256. package/dist/commands/sync.d.ts.map +1 -0
  257. package/dist/commands/sync.js +201 -0
  258. package/dist/commands/sync.js.map +1 -0
  259. package/dist/constants.d.ts +21 -0
  260. package/dist/constants.d.ts.map +1 -0
  261. package/dist/constants.js +57 -0
  262. package/dist/constants.js.map +1 -0
  263. package/dist/e2e/aggressive.e2e.test.d.ts +2 -0
  264. package/dist/e2e/aggressive.e2e.test.d.ts.map +1 -0
  265. package/dist/e2e/aggressive.e2e.test.js +350 -0
  266. package/dist/e2e/aggressive.e2e.test.js.map +1 -0
  267. package/dist/e2e/commands.e2e.test.d.ts +2 -0
  268. package/dist/e2e/commands.e2e.test.d.ts.map +1 -0
  269. package/dist/e2e/commands.e2e.test.js +213 -0
  270. package/dist/e2e/commands.e2e.test.js.map +1 -0
  271. package/dist/index.d.ts +3 -0
  272. package/dist/index.d.ts.map +1 -0
  273. package/dist/index.js +82 -0
  274. package/dist/index.js.map +1 -0
  275. package/dist/lib/common.d.ts +17 -0
  276. package/dist/lib/common.d.ts.map +1 -0
  277. package/dist/lib/common.js +111 -0
  278. package/dist/lib/common.js.map +1 -0
  279. package/dist/lib/common.test.d.ts +2 -0
  280. package/dist/lib/common.test.d.ts.map +1 -0
  281. package/dist/lib/common.test.js +316 -0
  282. package/dist/lib/common.test.js.map +1 -0
  283. package/dist/lib/frontmatter.d.ts +18 -0
  284. package/dist/lib/frontmatter.d.ts.map +1 -0
  285. package/dist/lib/frontmatter.js +61 -0
  286. package/dist/lib/frontmatter.js.map +1 -0
  287. package/dist/lib/frontmatter.test.d.ts +2 -0
  288. package/dist/lib/frontmatter.test.d.ts.map +1 -0
  289. package/dist/lib/frontmatter.test.js +257 -0
  290. package/dist/lib/frontmatter.test.js.map +1 -0
  291. package/dist/lib/template.d.ts +24 -0
  292. package/dist/lib/template.d.ts.map +1 -0
  293. package/dist/lib/template.js +78 -0
  294. package/dist/lib/template.js.map +1 -0
  295. package/dist/lib/template.test.d.ts +2 -0
  296. package/dist/lib/template.test.d.ts.map +1 -0
  297. package/dist/lib/template.test.js +201 -0
  298. package/dist/lib/template.test.js.map +1 -0
  299. package/dist/types/index.d.ts +48 -0
  300. package/dist/types/index.d.ts.map +1 -0
  301. package/dist/types/index.js +2 -0
  302. package/dist/types/index.js.map +1 -0
  303. package/dist/ui/AnalyzeUI.d.ts +7 -0
  304. package/dist/ui/AnalyzeUI.d.ts.map +1 -0
  305. package/dist/ui/AnalyzeUI.js +100 -0
  306. package/dist/ui/AnalyzeUI.js.map +1 -0
  307. package/dist/ui/App.d.ts +13 -0
  308. package/dist/ui/App.d.ts.map +1 -0
  309. package/dist/ui/App.js +100 -0
  310. package/dist/ui/App.js.map +1 -0
  311. package/dist/ui/CIContext.d.ts +9 -0
  312. package/dist/ui/CIContext.d.ts.map +1 -0
  313. package/dist/ui/CIContext.js +9 -0
  314. package/dist/ui/CIContext.js.map +1 -0
  315. package/dist/ui/CISelector.d.ts +8 -0
  316. package/dist/ui/CISelector.d.ts.map +1 -0
  317. package/dist/ui/CISelector.js +45 -0
  318. package/dist/ui/CISelector.js.map +1 -0
  319. package/dist/ui/Doctor.d.ts +3 -0
  320. package/dist/ui/Doctor.d.ts.map +1 -0
  321. package/dist/ui/Doctor.js +89 -0
  322. package/dist/ui/Doctor.js.map +1 -0
  323. package/dist/ui/Header.d.ts +8 -0
  324. package/dist/ui/Header.d.ts.map +1 -0
  325. package/dist/ui/Header.js +30 -0
  326. package/dist/ui/Header.js.map +1 -0
  327. package/dist/ui/MemorySelector.d.ts +8 -0
  328. package/dist/ui/MemorySelector.d.ts.map +1 -0
  329. package/dist/ui/MemorySelector.js +46 -0
  330. package/dist/ui/MemorySelector.js.map +1 -0
  331. package/dist/ui/NameInput.d.ts +8 -0
  332. package/dist/ui/NameInput.d.ts.map +1 -0
  333. package/dist/ui/NameInput.js +69 -0
  334. package/dist/ui/NameInput.js.map +1 -0
  335. package/dist/ui/OptionSelector.d.ts +12 -0
  336. package/dist/ui/OptionSelector.d.ts.map +1 -0
  337. package/dist/ui/OptionSelector.js +69 -0
  338. package/dist/ui/OptionSelector.js.map +1 -0
  339. package/dist/ui/Progress.d.ts +11 -0
  340. package/dist/ui/Progress.d.ts.map +1 -0
  341. package/dist/ui/Progress.js +58 -0
  342. package/dist/ui/Progress.js.map +1 -0
  343. package/dist/ui/StackSelector.d.ts +9 -0
  344. package/dist/ui/StackSelector.d.ts.map +1 -0
  345. package/dist/ui/StackSelector.js +65 -0
  346. package/dist/ui/StackSelector.js.map +1 -0
  347. package/dist/ui/Summary.d.ts +12 -0
  348. package/dist/ui/Summary.d.ts.map +1 -0
  349. package/dist/ui/Summary.js +114 -0
  350. package/dist/ui/Summary.js.map +1 -0
  351. package/dist/ui/SyncUI.d.ts +10 -0
  352. package/dist/ui/SyncUI.d.ts.map +1 -0
  353. package/dist/ui/SyncUI.js +64 -0
  354. package/dist/ui/SyncUI.js.map +1 -0
  355. package/dist/ui/Welcome.d.ts +7 -0
  356. package/dist/ui/Welcome.d.ts.map +1 -0
  357. package/dist/ui/Welcome.js +45 -0
  358. package/dist/ui/Welcome.js.map +1 -0
  359. package/dist/ui/theme.d.ts +10 -0
  360. package/dist/ui/theme.d.ts.map +1 -0
  361. package/dist/ui/theme.js +9 -0
  362. package/dist/ui/theme.js.map +1 -0
  363. package/modules/engram/.gitignore-snippet.txt +6 -0
  364. package/modules/engram/.mcp-config-snippet.json +11 -0
  365. package/modules/engram/README.md +146 -0
  366. package/modules/engram/install-engram.sh +216 -0
  367. package/modules/ghagga/.env.example +43 -0
  368. package/modules/ghagga/README.md +153 -0
  369. package/modules/ghagga/docker-compose.yml +80 -0
  370. package/modules/ghagga/setup-ghagga.sh +139 -0
  371. package/modules/memory-simple/.project/NOTES.md +22 -0
  372. package/modules/memory-simple/README.md +23 -0
  373. package/modules/obsidian-brain/.obsidian/app.json +23 -0
  374. package/modules/obsidian-brain/.obsidian/appearance.json +5 -0
  375. package/modules/obsidian-brain/.obsidian/bookmarks.json +34 -0
  376. package/modules/obsidian-brain/.obsidian/community-plugins.json +1 -0
  377. package/modules/obsidian-brain/.obsidian/core-plugins-migration.json +21 -0
  378. package/modules/obsidian-brain/.obsidian/core-plugins.json +18 -0
  379. package/modules/obsidian-brain/.obsidian/daily-notes.json +5 -0
  380. package/modules/obsidian-brain/.obsidian/graph.json +37 -0
  381. package/modules/obsidian-brain/.obsidian/hotkeys.json +14 -0
  382. package/modules/obsidian-brain/.obsidian/plugins/dataview/data.json +25 -0
  383. package/modules/obsidian-brain/.obsidian/plugins/obsidian-kanban/data.json +29 -0
  384. package/modules/obsidian-brain/.obsidian/plugins/templater-obsidian/data.json +18 -0
  385. package/modules/obsidian-brain/.obsidian/snippets/project-memory.css +71 -0
  386. package/modules/obsidian-brain/.obsidian-gitignore-snippet.txt +8 -0
  387. package/modules/obsidian-brain/.project/Attachments/.gitkeep +0 -0
  388. package/modules/obsidian-brain/.project/Memory/BLOCKERS.md +78 -0
  389. package/modules/obsidian-brain/.project/Memory/CONTEXT.md +102 -0
  390. package/modules/obsidian-brain/.project/Memory/DASHBOARD.md +73 -0
  391. package/modules/obsidian-brain/.project/Memory/DECISIONS.md +87 -0
  392. package/modules/obsidian-brain/.project/Memory/KANBAN.md +15 -0
  393. package/modules/obsidian-brain/.project/Memory/README.md +61 -0
  394. package/modules/obsidian-brain/.project/Memory/WAVES.md +78 -0
  395. package/modules/obsidian-brain/.project/Sessions/TEMPLATE.md +99 -0
  396. package/modules/obsidian-brain/.project/Templates/ADR.md +33 -0
  397. package/modules/obsidian-brain/.project/Templates/Blocker.md +21 -0
  398. package/modules/obsidian-brain/.project/Templates/Session.md +88 -0
  399. package/modules/obsidian-brain/README.md +268 -0
  400. package/modules/obsidian-brain/new-wave.sh +182 -0
  401. package/package.json +51 -0
  402. package/schemas/agent.schema.json +34 -0
  403. package/schemas/ai-config.schema.json +28 -0
  404. package/schemas/skill.schema.json +44 -0
  405. package/src/commands/analyze.test.ts +145 -0
  406. package/src/commands/analyze.ts +69 -0
  407. package/src/commands/doctor.test.ts +208 -0
  408. package/src/commands/doctor.ts +163 -0
  409. package/src/commands/init.test.ts +298 -0
  410. package/src/commands/init.ts +285 -0
  411. package/src/constants.ts +69 -0
  412. package/src/e2e/aggressive.e2e.test.ts +557 -0
  413. package/src/e2e/commands.e2e.test.ts +298 -0
  414. package/src/index.tsx +106 -0
  415. package/src/lib/common.test.ts +318 -0
  416. package/src/lib/common.ts +127 -0
  417. package/src/lib/frontmatter.test.ts +291 -0
  418. package/src/lib/frontmatter.ts +77 -0
  419. package/src/lib/template.test.ts +226 -0
  420. package/src/lib/template.ts +99 -0
  421. package/src/types/index.ts +53 -0
  422. package/src/ui/AnalyzeUI.tsx +133 -0
  423. package/src/ui/App.tsx +175 -0
  424. package/src/ui/CIContext.tsx +25 -0
  425. package/src/ui/CISelector.tsx +72 -0
  426. package/src/ui/Doctor.tsx +122 -0
  427. package/src/ui/Header.tsx +48 -0
  428. package/src/ui/MemorySelector.tsx +73 -0
  429. package/src/ui/NameInput.tsx +82 -0
  430. package/src/ui/OptionSelector.tsx +100 -0
  431. package/src/ui/Progress.tsx +88 -0
  432. package/src/ui/StackSelector.tsx +101 -0
  433. package/src/ui/Summary.tsx +134 -0
  434. package/src/ui/Welcome.tsx +54 -0
  435. package/src/ui/theme.ts +10 -0
  436. package/stryker.config.json +19 -0
  437. package/tasks/_TEMPLATE/files-edited.md +3 -0
  438. package/tasks/_TEMPLATE/plan.md +3 -0
  439. package/tasks/_TEMPLATE/research.md +3 -0
  440. package/tasks/_TEMPLATE/verification.md +5 -0
  441. package/templates/common/dependabot/cargo.yml +11 -0
  442. package/templates/common/dependabot/github-actions.yml +16 -0
  443. package/templates/common/dependabot/gomod.yml +15 -0
  444. package/templates/common/dependabot/gradle.yml +15 -0
  445. package/templates/common/dependabot/header.yml +3 -0
  446. package/templates/common/dependabot/maven.yml +15 -0
  447. package/templates/common/dependabot/npm.yml +20 -0
  448. package/templates/common/dependabot/pip.yml +11 -0
  449. package/templates/dependabot.yml +162 -0
  450. package/templates/github/ci-go.yml +41 -0
  451. package/templates/github/ci-java.yml +45 -0
  452. package/templates/github/ci-monorepo.yml +150 -0
  453. package/templates/github/ci-node.yml +42 -0
  454. package/templates/github/ci-python.yml +42 -0
  455. package/templates/github/ci-rust.yml +42 -0
  456. package/templates/github/dependabot-automerge.yml +40 -0
  457. package/templates/gitlab/gitlab-ci-go.yml +88 -0
  458. package/templates/gitlab/gitlab-ci-java.yml +79 -0
  459. package/templates/gitlab/gitlab-ci-monorepo.yml +126 -0
  460. package/templates/gitlab/gitlab-ci-node.yml +63 -0
  461. package/templates/gitlab/gitlab-ci-python.yml +147 -0
  462. package/templates/gitlab/gitlab-ci-rust.yml +67 -0
  463. package/templates/global/claude-settings.json +98 -0
  464. package/templates/global/codex-config.toml +8 -0
  465. package/templates/global/copilot-instructions/base-rules.instructions.md +13 -0
  466. package/templates/global/copilot-instructions/sdd-orchestrator.instructions.md +37 -0
  467. package/templates/global/gemini-commands/cleanup.toml +20 -0
  468. package/templates/global/gemini-commands/commit.toml +15 -0
  469. package/templates/global/gemini-commands/dead-code.toml +22 -0
  470. package/templates/global/gemini-commands/plan.toml +30 -0
  471. package/templates/global/gemini-commands/review.toml +17 -0
  472. package/templates/global/gemini-commands/sdd-apply.toml +22 -0
  473. package/templates/global/gemini-commands/sdd-ff.toml +14 -0
  474. package/templates/global/gemini-commands/sdd-new.toml +21 -0
  475. package/templates/global/gemini-commands/sdd-verify.toml +21 -0
  476. package/templates/global/gemini-commands/tdd.toml +26 -0
  477. package/templates/global/gemini-settings.json +8 -0
  478. package/templates/global/opencode-config.json +44 -0
  479. package/templates/global/sdd-instructions.md +47 -0
  480. package/templates/global/sdd-orchestrator-claude.md +46 -0
  481. package/templates/global/sdd-orchestrator-copilot.md +34 -0
  482. package/templates/renovate.json +69 -0
  483. package/templates/woodpecker/monorepo/backend.yml +34 -0
  484. package/templates/woodpecker/monorepo/frontend.yml +34 -0
  485. package/templates/woodpecker/monorepo/summary.yml +25 -0
  486. package/templates/woodpecker/woodpecker-go.yml +51 -0
  487. package/templates/woodpecker/woodpecker-java.yml +67 -0
  488. package/templates/woodpecker/woodpecker-node.yml +47 -0
  489. package/templates/woodpecker/woodpecker-python.yml +108 -0
  490. package/templates/woodpecker/woodpecker-rust.yml +57 -0
  491. package/tsconfig.json +19 -0
  492. package/vitest.config.ts +16 -0
  493. package/workflows/reusable-build-go.yml +111 -0
  494. package/workflows/reusable-build-java.yml +120 -0
  495. package/workflows/reusable-build-node.yml +145 -0
  496. package/workflows/reusable-build-python.yml +159 -0
  497. package/workflows/reusable-build-rust.yml +135 -0
  498. package/workflows/reusable-docker.yml +120 -0
  499. package/workflows/reusable-ghagga-review.yml +165 -0
  500. package/workflows/reusable-release.yml +91 -0
@@ -0,0 +1,1086 @@
1
+ ---
2
+ name: performance-tester
3
+ description: Performance testing expert specializing in load testing, stress testing, benchmarking, and performance optimization
4
+ trigger: >
5
+ load testing, stress testing, performance testing, benchmarking, K6, JMeter, Gatling,
6
+ throughput, latency, response time, scalability, capacity planning, performance optimization
7
+ category: quality
8
+ color: orange
9
+ tools: Write, Read, MultiEdit, Bash, Grep, Glob
10
+ config:
11
+ model: sonnet
12
+ metadata:
13
+ version: "2.0"
14
+ updated: "2026-02"
15
+ ---
16
+
17
+ You are a performance testing expert with expertise in load testing, stress testing, performance monitoring, and optimization strategies.
18
+
19
+ ## Core Expertise
20
+ - Load and stress testing methodologies
21
+ - Performance monitoring and observability
22
+ - Capacity planning and scalability testing
23
+ - Database and application performance tuning
24
+ - Infrastructure performance optimization
25
+ - Performance testing automation and CI/CD
26
+ - Real user monitoring (RUM) and synthetic monitoring
27
+ - Performance budgets and SLA management
28
+
29
+ ## Technical Stack
30
+ - **Load Testing**: K6, JMeter, Artillery, Gatling, LoadRunner
31
+ - **APM Tools**: New Relic, Datadog, AppDynamics, Dynatrace
32
+ - **Monitoring**: Prometheus, Grafana, ELK Stack, Jaeger
33
+ - **Database Tools**: pgbench, sysbench, HammerDB
34
+ - **Cloud Load Testing**: AWS Load Testing, Azure Load Testing, GCP Load Testing
35
+ - **Browser Performance**: Lighthouse, WebPageTest, Chrome DevTools
36
+ - **Profiling**: Java Profiler, Python cProfile, Node.js Clinic
37
+
38
+ ## K6 Load Testing Framework
39
+ ```javascript
40
+ // k6/config/test-config.js
41
+ export const config = {
42
+ scenarios: {
43
+ smoke_test: {
44
+ executor: 'constant-vus',
45
+ vus: 1,
46
+ duration: '30s',
47
+ tags: { test_type: 'smoke' }
48
+ },
49
+ load_test: {
50
+ executor: 'ramping-vus',
51
+ startVUs: 0,
52
+ stages: [
53
+ { duration: '2m', target: 10 },
54
+ { duration: '5m', target: 10 },
55
+ { duration: '2m', target: 20 },
56
+ { duration: '5m', target: 20 },
57
+ { duration: '2m', target: 0 }
58
+ ],
59
+ tags: { test_type: 'load' }
60
+ },
61
+ stress_test: {
62
+ executor: 'ramping-vus',
63
+ startVUs: 0,
64
+ stages: [
65
+ { duration: '2m', target: 20 },
66
+ { duration: '5m', target: 20 },
67
+ { duration: '2m', target: 50 },
68
+ { duration: '5m', target: 50 },
69
+ { duration: '2m', target: 100 },
70
+ { duration: '5m', target: 100 },
71
+ { duration: '10m', target: 0 }
72
+ ],
73
+ tags: { test_type: 'stress' }
74
+ },
75
+ spike_test: {
76
+ executor: 'ramping-vus',
77
+ startVUs: 0,
78
+ stages: [
79
+ { duration: '10s', target: 100 },
80
+ { duration: '1m', target: 100 },
81
+ { duration: '10s', target: 1400 },
82
+ { duration: '3m', target: 1400 },
83
+ { duration: '10s', target: 100 },
84
+ { duration: '3m', target: 100 },
85
+ { duration: '10s', target: 0 }
86
+ ],
87
+ tags: { test_type: 'spike' }
88
+ }
89
+ },
90
+ thresholds: {
91
+ http_req_duration: ['p(95)<500'], // 95% of requests under 500ms
92
+ http_req_failed: ['rate<0.1'], // Error rate under 10%
93
+ http_reqs: ['rate>100'] // At least 100 RPS
94
+ }
95
+ };
96
+
97
+ // k6/utils/auth.js
98
+ import http from 'k6/http';
99
+ import { check } from 'k6';
100
+
101
+ export function authenticate(baseUrl, credentials) {
102
+ const loginResponse = http.post(`${baseUrl}/api/auth/login`, {
103
+ email: credentials.email,
104
+ password: credentials.password
105
+ }, {
106
+ headers: { 'Content-Type': 'application/json' }
107
+ });
108
+
109
+ check(loginResponse, {
110
+ 'login successful': (r) => r.status === 200,
111
+ 'token received': (r) => r.json('token') !== undefined
112
+ });
113
+
114
+ return loginResponse.json('token');
115
+ }
116
+
117
+ export function getAuthHeaders(token) {
118
+ return {
119
+ 'Authorization': `Bearer ${token}`,
120
+ 'Content-Type': 'application/json'
121
+ };
122
+ }
123
+
124
+ // k6/scenarios/user-journey.js
125
+ import http from 'k6/http';
126
+ import { check, sleep } from 'k6';
127
+ import { authenticate, getAuthHeaders } from '../utils/auth.js';
128
+ import { generateTestData } from '../utils/test-data.js';
129
+
130
+ const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000';
131
+ const TEST_USER_PASSWORD = __ENV.TEST_USER_PASSWORD || 'default-password';
132
+
133
+ export let options = {
134
+ scenarios: {
135
+ user_journey: {
136
+ executor: 'ramping-vus',
137
+ startVUs: 0,
138
+ stages: [
139
+ { duration: '1m', target: 5 },
140
+ { duration: '3m', target: 5 },
141
+ { duration: '1m', target: 10 },
142
+ { duration: '3m', target: 10 },
143
+ { duration: '1m', target: 0 }
144
+ ]
145
+ }
146
+ },
147
+ thresholds: {
148
+ 'http_req_duration{scenario:user_journey}': ['p(95)<1000'],
149
+ 'http_req_failed{scenario:user_journey}': ['rate<0.05'],
150
+ 'user_journey_duration': ['p(95)<30000'] // Complete journey under 30s
151
+ }
152
+ };
153
+
154
+ export default function() {
155
+ const startTime = new Date();
156
+
157
+ // 1. Login
158
+ const token = authenticate(BASE_URL, {
159
+ email: `user${__VU}@example.com`,
160
+ password: TEST_USER_PASSWORD
161
+ });
162
+
163
+ const headers = getAuthHeaders(token);
164
+ sleep(1);
165
+
166
+ // 2. Browse products
167
+ const productsResponse = http.get(`${BASE_URL}/api/products`, { headers });
168
+ check(productsResponse, {
169
+ 'products loaded': (r) => r.status === 200,
170
+ 'products count > 0': (r) => r.json('data').length > 0
171
+ });
172
+ sleep(2);
173
+
174
+ // 3. View product details
175
+ const products = productsResponse.json('data');
176
+ const randomProduct = products[Math.floor(Math.random() * products.length)];
177
+
178
+ const productResponse = http.get(`${BASE_URL}/api/products/${randomProduct.id}`, { headers });
179
+ check(productResponse, {
180
+ 'product details loaded': (r) => r.status === 200
181
+ });
182
+ sleep(3);
183
+
184
+ // 4. Add to cart
185
+ const cartResponse = http.post(`${BASE_URL}/api/cart/items`,
186
+ JSON.stringify({
187
+ productId: randomProduct.id,
188
+ quantity: Math.floor(Math.random() * 3) + 1
189
+ }),
190
+ { headers }
191
+ );
192
+ check(cartResponse, {
193
+ 'item added to cart': (r) => r.status === 201
194
+ });
195
+ sleep(1);
196
+
197
+ // 5. View cart
198
+ const cartViewResponse = http.get(`${BASE_URL}/api/cart`, { headers });
199
+ check(cartViewResponse, {
200
+ 'cart loaded': (r) => r.status === 200,
201
+ 'cart has items': (r) => r.json('items').length > 0
202
+ });
203
+ sleep(2);
204
+
205
+ // 6. Checkout process
206
+ const checkoutData = generateTestData.checkoutInfo();
207
+ const checkoutResponse = http.post(`${BASE_URL}/api/checkout`,
208
+ JSON.stringify(checkoutData),
209
+ { headers }
210
+ );
211
+ check(checkoutResponse, {
212
+ 'checkout successful': (r) => r.status === 200,
213
+ 'order created': (r) => r.json('orderId') !== undefined
214
+ });
215
+
216
+ // Record journey duration
217
+ const journeyDuration = new Date() - startTime;
218
+ console.log(`User journey completed in ${journeyDuration}ms`);
219
+
220
+ sleep(1);
221
+ }
222
+
223
+ // k6/utils/test-data.js
224
+ export const generateTestData = {
225
+ user() {
226
+ return {
227
+ email: `user${Math.random().toString(36).substr(2, 9)}@example.com`,
228
+ password: __ENV.TEST_USER_PASSWORD || 'default-password',
229
+ firstName: 'Test',
230
+ lastName: 'User'
231
+ };
232
+ },
233
+
234
+ product() {
235
+ return {
236
+ name: `Product ${Math.random().toString(36).substr(2, 9)}`,
237
+ description: 'Test product description',
238
+ price: Math.floor(Math.random() * 100) + 10,
239
+ category: 'electronics'
240
+ };
241
+ },
242
+
243
+ checkoutInfo() {
244
+ return {
245
+ shippingAddress: {
246
+ street: '123 Test St',
247
+ city: 'Test City',
248
+ state: 'TS',
249
+ zipCode: '12345',
250
+ country: 'US'
251
+ },
252
+ paymentMethod: {
253
+ type: 'credit_card',
254
+ cardNumber: '4111111111111111',
255
+ expiryDate: '12/25',
256
+ cvv: '123'
257
+ }
258
+ };
259
+ }
260
+ };
261
+ ```
262
+
263
+ ## JMeter Test Plan Configuration
264
+ ```xml
265
+ <?xml version="1.0" encoding="UTF-8"?>
266
+ <jmeterTestPlan version="1.2">
267
+ <hashTree>
268
+ <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="API Load Test">
269
+ <stringProp name="TestPlan.comments">Comprehensive API load testing</stringProp>
270
+ <boolProp name="TestPlan.functional_mode">false</boolProp>
271
+ <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
272
+ <elementProp name="TestPlan.arguments" elementType="Arguments" guiclass="ArgumentsPanel">
273
+ <collectionProp name="Arguments.arguments">
274
+ <elementProp name="base_url" elementType="Argument">
275
+ <stringProp name="Argument.name">base_url</stringProp>
276
+ <stringProp name="Argument.value">${__P(base_url,http://localhost:3000)}</stringProp>
277
+ </elementProp>
278
+ <elementProp name="users" elementType="Argument">
279
+ <stringProp name="Argument.name">users</stringProp>
280
+ <stringProp name="Argument.value">${__P(users,10)}</stringProp>
281
+ </elementProp>
282
+ <elementProp name="ramp_time" elementType="Argument">
283
+ <stringProp name="Argument.name">ramp_time</stringProp>
284
+ <stringProp name="Argument.value">${__P(ramp_time,60)}</stringProp>
285
+ </elementProp>
286
+ <elementProp name="duration" elementType="Argument">
287
+ <stringProp name="Argument.name">duration</stringProp>
288
+ <stringProp name="Argument.value">${__P(duration,300)}</stringProp>
289
+ </elementProp>
290
+ <elementProp name="test_password" elementType="Argument">
291
+ <stringProp name="Argument.name">test_password</stringProp>
292
+ <stringProp name="Argument.value">${__P(test_password,default-password)}</stringProp>
293
+ </elementProp>
294
+ </collectionProp>
295
+ </elementProp>
296
+ </TestPlan>
297
+
298
+ <hashTree>
299
+ <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Load Test Users">
300
+ <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
301
+ <elementProp name="ThreadGroup.main_controller" elementType="LoopController">
302
+ <boolProp name="LoopController.continue_forever">false</boolProp>
303
+ <stringProp name="LoopController.loops">-1</stringProp>
304
+ </elementProp>
305
+ <stringProp name="ThreadGroup.num_threads">${users}</stringProp>
306
+ <stringProp name="ThreadGroup.ramp_time">${ramp_time}</stringProp>
307
+ <longProp name="ThreadGroup.start_time">1640995200000</longProp>
308
+ <longProp name="ThreadGroup.end_time">1640995200000</longProp>
309
+ <boolProp name="ThreadGroup.scheduler">true</boolProp>
310
+ <stringProp name="ThreadGroup.duration">${duration}</stringProp>
311
+ <stringProp name="ThreadGroup.delay"></stringProp>
312
+ </ThreadGroup>
313
+
314
+ <hashTree>
315
+ <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults">
316
+ <elementProp name="HTTPsampler.Arguments" elementType="Arguments">
317
+ <collectionProp name="Arguments.arguments"></collectionProp>
318
+ </elementProp>
319
+ <stringProp name="HTTPSampler.domain">${__javaScript(${base_url}.replace(/https?:\/\//, '').split('/')[0])}</stringProp>
320
+ <stringProp name="HTTPSampler.port"></stringProp>
321
+ <stringProp name="HTTPSampler.protocol">${__javaScript(${base_url}.startsWith('https') ? 'https' : 'http')}</stringProp>
322
+ <stringProp name="HTTPSampler.contentEncoding"></stringProp>
323
+ <stringProp name="HTTPSampler.path"></stringProp>
324
+ </ConfigTestElement>
325
+
326
+ <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager">
327
+ <collectionProp name="CookieManager.cookies"></collectionProp>
328
+ <boolProp name="CookieManager.clearEachIteration">false</boolProp>
329
+ </CookieManager>
330
+
331
+ <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Login">
332
+ <elementProp name="HTTPsampler.Arguments" elementType="Arguments">
333
+ <collectionProp name="Arguments.arguments">
334
+ <elementProp name="" elementType="HTTPArgument">
335
+ <boolProp name="HTTPArgument.always_encode">false</boolProp>
336
+ <stringProp name="Argument.value">{"email":"user${__threadNum}@example.com","password":"${test_password}"}</stringProp>
337
+ <stringProp name="Argument.metadata">=</stringProp>
338
+ </elementProp>
339
+ </collectionProp>
340
+ </elementProp>
341
+ <stringProp name="HTTPSampler.domain"></stringProp>
342
+ <stringProp name="HTTPSampler.port"></stringProp>
343
+ <stringProp name="HTTPSampler.protocol"></stringProp>
344
+ <stringProp name="HTTPSampler.contentEncoding"></stringProp>
345
+ <stringProp name="HTTPSampler.path">/api/auth/login</stringProp>
346
+ <stringProp name="HTTPSampler.method">POST</stringProp>
347
+ <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
348
+ <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
349
+ <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
350
+ <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
351
+ <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
352
+ <stringProp name="HTTPSampler.connect_timeout"></stringProp>
353
+ <stringProp name="HTTPSampler.response_timeout"></stringProp>
354
+ </HTTPSamplerProxy>
355
+
356
+ <hashTree>
357
+ <JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="Extract Auth Token">
358
+ <stringProp name="JSONPostProcessor.referenceNames">auth_token</stringProp>
359
+ <stringProp name="JSONPostProcessor.jsonPathExprs">$.token</stringProp>
360
+ <stringProp name="JSONPostProcessor.match_numbers"></stringProp>
361
+ <stringProp name="JSONPostProcessor.defaultValues">NOTFOUND</stringProp>
362
+ </JSONPostProcessor>
363
+ </hashTree>
364
+ </hashTree>
365
+ </hashTree>
366
+ </hashTree>
367
+ </jmeterTestPlan>
368
+ ```
369
+
370
+ ## Database Performance Testing
371
+ ```sql
372
+ -- postgres/performance-test-setup.sql
373
+ -- Create test tables with realistic data volumes
374
+ CREATE TABLE IF NOT EXISTS users_perf_test (
375
+ id SERIAL PRIMARY KEY,
376
+ email VARCHAR(255) UNIQUE NOT NULL,
377
+ first_name VARCHAR(100),
378
+ last_name VARCHAR(100),
379
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
380
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
381
+ );
382
+
383
+ CREATE TABLE IF NOT EXISTS orders_perf_test (
384
+ id SERIAL PRIMARY KEY,
385
+ user_id INTEGER REFERENCES users_perf_test(id),
386
+ order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
387
+ total_amount DECIMAL(10,2),
388
+ status VARCHAR(50),
389
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
390
+ );
391
+
392
+ CREATE TABLE IF NOT EXISTS order_items_perf_test (
393
+ id SERIAL PRIMARY KEY,
394
+ order_id INTEGER REFERENCES orders_perf_test(id),
395
+ product_id INTEGER,
396
+ quantity INTEGER,
397
+ unit_price DECIMAL(10,2),
398
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
399
+ );
400
+
401
+ -- Generate test data
402
+ INSERT INTO users_perf_test (email, first_name, last_name)
403
+ SELECT
404
+ 'user' || generate_series || '@example.com',
405
+ 'FirstName' || generate_series,
406
+ 'LastName' || generate_series
407
+ FROM generate_series(1, 100000);
408
+
409
+ -- Insert orders (average 5 orders per user)
410
+ INSERT INTO orders_perf_test (user_id, order_date, total_amount, status)
411
+ SELECT
412
+ (random() * 99999 + 1)::INTEGER,
413
+ CURRENT_TIMESTAMP - (random() * INTERVAL '365 days'),
414
+ (random() * 1000 + 10)::DECIMAL(10,2),
415
+ CASE
416
+ WHEN random() < 0.8 THEN 'completed'
417
+ WHEN random() < 0.9 THEN 'pending'
418
+ ELSE 'cancelled'
419
+ END
420
+ FROM generate_series(1, 500000);
421
+
422
+ -- Insert order items (average 3 items per order)
423
+ INSERT INTO order_items_perf_test (order_id, product_id, quantity, unit_price)
424
+ SELECT
425
+ (random() * 499999 + 1)::INTEGER,
426
+ (random() * 10000 + 1)::INTEGER,
427
+ (random() * 5 + 1)::INTEGER,
428
+ (random() * 100 + 5)::DECIMAL(10,2)
429
+ FROM generate_series(1, 1500000);
430
+
431
+ -- Create indexes for performance testing
432
+ CREATE INDEX idx_users_email ON users_perf_test(email);
433
+ CREATE INDEX idx_orders_user_id ON orders_perf_test(user_id);
434
+ CREATE INDEX idx_orders_date ON orders_perf_test(order_date);
435
+ CREATE INDEX idx_orders_status ON orders_perf_test(status);
436
+ CREATE INDEX idx_order_items_order_id ON order_items_perf_test(order_id);
437
+ CREATE INDEX idx_order_items_product_id ON order_items_perf_test(product_id);
438
+
439
+ -- Update table statistics
440
+ ANALYZE users_perf_test;
441
+ ANALYZE orders_perf_test;
442
+ ANALYZE order_items_perf_test;
443
+ ```
444
+
445
+ ```bash
446
+ #!/bin/bash
447
+ # scripts/database-performance-test.sh
448
+
449
+ # Database performance testing script using pgbench
450
+
451
+ # Load credentials securely from environment variables
452
+ DB_HOST=${DB_HOST:-localhost}
453
+ DB_PORT=${DB_PORT:-5432}
454
+ DB_NAME=${DB_NAME:-testdb}
455
+ DB_USER=${DB_USER:-testuser}
456
+ DB_PASSWORD=${DB_PASSWORD} # Should be set in the environment
457
+
458
+ if [[ -z "$DB_PASSWORD" ]]; then
459
+ echo "Error: DB_PASSWORD environment variable is not set."
460
+ exit 1
461
+ fi
462
+
463
+ export PGPASSWORD=$DB_PASSWORD
464
+
465
+ # Performance test configurations
466
+ CLIENTS=(1 5 10 25 50 100)
467
+ DURATION=300 # 5 minutes per test
468
+ SCALE_FACTOR=100
469
+
470
+ echo "Starting database performance tests..."
471
+
472
+ # Initialize pgbench
473
+ echo "Initializing pgbench with scale factor $SCALE_FACTOR..."
474
+ pgbench -i -s $SCALE_FACTOR -h $DB_HOST -p $DB_PORT -U $DB_USER $DB_NAME
475
+
476
+ # Custom test scripts
477
+ cat > custom_readonly.sql << EOF
478
+ \set aid random(1, 100000 * :scale)
479
+ SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
480
+ EOF
481
+
482
+ cat > custom_writeonly.sql << EOF
483
+ \set aid random(1, 100000 * :scale)
484
+ \set delta random(-5000, 5000)
485
+ UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
486
+ EOF
487
+
488
+ cat > custom_mixed.sql << EOF
489
+ \set aid random(1, 100000 * :scale)
490
+ \set delta random(-5000, 5000)
491
+ BEGIN;
492
+ SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
493
+ UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
494
+ COMMIT;
495
+ EOF
496
+
497
+ # Run performance tests
498
+ for clients in "${CLIENTS[@]}"; do
499
+ echo "Running tests with $clients concurrent clients..."
500
+
501
+ # Read-only test
502
+ echo " Read-only test..."
503
+ pgbench -c $clients -j $(nproc) -T $DURATION -S -h $DB_HOST -p $DB_PORT -U $DB_USER $DB_NAME \
504
+ > results/readonly_${clients}_clients.log 2>&1
505
+
506
+ # Write-only test
507
+ echo " Write-only test..."
508
+ pgbench -c $clients -j $(nproc) -T $DURATION -f custom_writeonly.sql -h $DB_HOST -p $DB_PORT -U $DB_USER $DB_NAME \
509
+ > results/writeonly_${clients}_clients.log 2>&1
510
+
511
+ # Mixed workload test
512
+ echo " Mixed workload test..."
513
+ pgbench -c $clients -j $(nproc) -T $DURATION -f custom_mixed.sql -h $DB_HOST -p $DB_PORT -U $DB_USER $DB_NAME \
514
+ > results/mixed_${clients}_clients.log 2>&1
515
+
516
+ # Standard TPC-B test
517
+ echo " Standard TPC-B test..."
518
+ pgbench -c $clients -j $(nproc) -T $DURATION -h $DB_HOST -p $DB_PORT -U $DB_USER $DB_NAME \
519
+ > results/tpcb_${clients}_clients.log 2>&1
520
+
521
+ echo " Completed tests for $clients clients"
522
+ done
523
+
524
+ # Generate performance report
525
+ python3 scripts/analyze_pgbench_results.py results/
526
+ ```
527
+
528
+ ## Performance Monitoring and Analysis
529
+ ```python
530
+ # scripts/performance-monitor.py
531
+ import psutil
532
+ import time
533
+ import json
534
+ import requests
535
+ import logging
536
+ from datetime import datetime
537
+ import threading
538
+ import queue
539
+
540
+ class PerformanceMonitor:
541
+ def __init__(self, interval=5):
542
+ self.interval = interval
543
+ self.running = False
544
+ self.metrics_queue = queue.Queue()
545
+
546
+ def start_monitoring(self):
547
+ """Start performance monitoring in background"""
548
+ self.running = True
549
+
550
+ # Start system metrics collection
551
+ system_thread = threading.Thread(target=self._collect_system_metrics)
552
+ system_thread.daemon = True
553
+ system_thread.start()
554
+
555
+ # Start application metrics collection
556
+ app_thread = threading.Thread(target=self._collect_app_metrics)
557
+ app_thread.daemon = True
558
+ app_thread.start()
559
+
560
+ return system_thread, app_thread
561
+
562
+ def stop_monitoring(self):
563
+ """Stop performance monitoring"""
564
+ self.running = False
565
+
566
+ def _collect_system_metrics(self):
567
+ """Collect system-level performance metrics"""
568
+ while self.running:
569
+ try:
570
+ # CPU metrics
571
+ cpu_percent = psutil.cpu_percent(interval=1)
572
+ cpu_count = psutil.cpu_count()
573
+ cpu_freq = psutil.cpu_freq()
574
+
575
+ # Memory metrics
576
+ memory = psutil.virtual_memory()
577
+ swap = psutil.swap_memory()
578
+
579
+ # Disk metrics
580
+ disk_usage = psutil.disk_usage('/')
581
+ disk_io = psutil.disk_io_counters()
582
+
583
+ # Network metrics
584
+ network_io = psutil.net_io_counters()
585
+
586
+ metrics = {
587
+ 'timestamp': datetime.utcnow().isoformat(),
588
+ 'type': 'system',
589
+ 'cpu': {
590
+ 'percent': cpu_percent,
591
+ 'count': cpu_count,
592
+ 'frequency': cpu_freq.current if cpu_freq else None
593
+ },
594
+ 'memory': {
595
+ 'total': memory.total,
596
+ 'available': memory.available,
597
+ 'percent': memory.percent,
598
+ 'used': memory.used,
599
+ 'free': memory.free
600
+ },
601
+ 'swap': {
602
+ 'total': swap.total,
603
+ 'used': swap.used,
604
+ 'free': swap.free,
605
+ 'percent': swap.percent
606
+ },
607
+ 'disk': {
608
+ 'total': disk_usage.total,
609
+ 'used': disk_usage.used,
610
+ 'free': disk_usage.free,
611
+ 'percent': disk_usage.percent,
612
+ 'read_bytes': disk_io.read_bytes if disk_io else 0,
613
+ 'write_bytes': disk_io.write_bytes if disk_io else 0
614
+ },
615
+ 'network': {
616
+ 'bytes_sent': network_io.bytes_sent,
617
+ 'bytes_recv': network_io.bytes_recv,
618
+ 'packets_sent': network_io.packets_sent,
619
+ 'packets_recv': network_io.packets_recv
620
+ }
621
+ }
622
+
623
+ self.metrics_queue.put(metrics)
624
+
625
+ except Exception as e:
626
+ logging.error(f"Error collecting system metrics: {e}")
627
+
628
+ time.sleep(self.interval)
629
+
630
+ def _collect_app_metrics(self):
631
+ """Collect application-specific metrics"""
632
+ while self.running:
633
+ try:
634
+ # Application metrics endpoint
635
+ response = requests.get('http://localhost:3000/metrics', timeout=5)
636
+
637
+ if response.status_code == 200:
638
+ app_metrics = response.json()
639
+
640
+ metrics = {
641
+ 'timestamp': datetime.utcnow().isoformat(),
642
+ 'type': 'application',
643
+ 'metrics': app_metrics
644
+ }
645
+
646
+ self.metrics_queue.put(metrics)
647
+
648
+ except Exception as e:
649
+ logging.error(f"Error collecting application metrics: {e}")
650
+
651
+ time.sleep(self.interval)
652
+
653
+ def get_metrics(self):
654
+ """Get collected metrics"""
655
+ metrics = []
656
+ while not self.metrics_queue.empty():
657
+ metrics.append(self.metrics_queue.get())
658
+ return metrics
659
+
660
+ def save_metrics_to_file(self, filename):
661
+ """Save metrics to file"""
662
+ metrics = self.get_metrics()
663
+ with open(filename, 'w') as f:
664
+ json.dump(metrics, f, indent=2)
665
+ return len(metrics)
666
+
667
+ # Performance test execution with monitoring
668
+ class PerformanceTestExecutor:
669
+ def __init__(self):
670
+ self.monitor = PerformanceMonitor()
671
+ self.results = {}
672
+
673
+ def run_load_test(self, test_config):
674
+ """Run load test with performance monitoring"""
675
+ print(f"Starting load test: {test_config['name']}")
676
+
677
+ # Start monitoring
678
+ self.monitor.start_monitoring()
679
+
680
+ try:
681
+ # Execute K6 test
682
+ import subprocess
683
+
684
+ cmd = [
685
+ 'k6', 'run',
686
+ '--out', 'json=results.json',
687
+ '--env', f"BASE_URL={test_config['base_url']}",
688
+ test_config['script']
689
+ ]
690
+
691
+ result = subprocess.run(cmd, capture_output=True, text=True)
692
+
693
+ if result.returncode == 0:
694
+ print("Load test completed successfully")
695
+ self.results['load_test'] = {
696
+ 'status': 'success',
697
+ 'stdout': result.stdout,
698
+ 'stderr': result.stderr
699
+ }
700
+ else:
701
+ print(f"Load test failed: {result.stderr}")
702
+ self.results['load_test'] = {
703
+ 'status': 'failed',
704
+ 'stdout': result.stdout,
705
+ 'stderr': result.stderr
706
+ }
707
+
708
+ finally:
709
+ # Stop monitoring and save metrics
710
+ self.monitor.stop_monitoring()
711
+ time.sleep(2) # Allow time for final metrics collection
712
+
713
+ metrics_count = self.monitor.save_metrics_to_file('performance_metrics.json')
714
+ print(f"Saved {metrics_count} performance metrics")
715
+
716
+ def analyze_results(self):
717
+ """Analyze performance test results"""
718
+ # Load K6 results
719
+ try:
720
+ with open('results.json', 'r') as f:
721
+ k6_results = [json.loads(line) for line in f if line.strip()]
722
+ except FileNotFoundError:
723
+ k6_results = []
724
+
725
+ # Load performance metrics
726
+ try:
727
+ with open('performance_metrics.json', 'r') as f:
728
+ perf_metrics = json.load(f)
729
+ except FileNotFoundError:
730
+ perf_metrics = []
731
+
732
+ # Analyze metrics
733
+ analysis = self._analyze_metrics(k6_results, perf_metrics)
734
+
735
+ # Generate report
736
+ self._generate_report(analysis)
737
+
738
+ return analysis
739
+
740
+ def _analyze_metrics(self, k6_results, perf_metrics):
741
+ """Analyze collected metrics"""
742
+ analysis = {
743
+ 'summary': {},
744
+ 'performance_issues': [],
745
+ 'recommendations': []
746
+ }
747
+
748
+ # Analyze K6 metrics
749
+ if k6_results:
750
+ http_reqs = [r for r in k6_results if r.get('type') == 'Point' and r.get('metric') == 'http_reqs']
751
+ http_req_duration = [r for r in k6_results if r.get('type') == 'Point' and r.get('metric') == 'http_req_duration']
752
+
753
+ if http_req_duration:
754
+ durations = [r['data']['value'] for r in http_req_duration]
755
+ analysis['summary']['avg_response_time'] = sum(durations) / len(durations)
756
+ analysis['summary']['max_response_time'] = max(durations)
757
+ analysis['summary']['min_response_time'] = min(durations)
758
+ analysis['summary']['total_requests'] = len(http_reqs)
759
+
760
+ # Analyze system metrics
761
+ if perf_metrics:
762
+ system_metrics = [m for m in perf_metrics if m.get('type') == 'system']
763
+
764
+ if system_metrics:
765
+ cpu_usage = [m['cpu']['percent'] for m in system_metrics]
766
+ memory_usage = [m['memory']['percent'] for m in system_metrics]
767
+
768
+ analysis['summary']['avg_cpu_usage'] = sum(cpu_usage) / len(cpu_usage)
769
+ analysis['summary']['max_cpu_usage'] = max(cpu_usage)
770
+ analysis['summary']['avg_memory_usage'] = sum(memory_usage) / len(memory_usage)
771
+ analysis['summary']['max_memory_usage'] = max(memory_usage)
772
+
773
+ # Identify performance issues
774
+ if max(cpu_usage) > 80:
775
+ analysis['performance_issues'].append('High CPU usage detected')
776
+ analysis['recommendations'].append('Consider CPU optimization or scaling')
777
+
778
+ if max(memory_usage) > 85:
779
+ analysis['performance_issues'].append('High memory usage detected')
780
+ analysis['recommendations'].append('Consider memory optimization or scaling')
781
+
782
+ return analysis
783
+
784
+ def _generate_report(self, analysis):
785
+ """Generate performance test report"""
786
+ report = f"""
787
+ Performance Test Report
788
+ ======================
789
+ Generated: {datetime.utcnow().isoformat()}
790
+
791
+ Summary:
792
+ --------
793
+ Average Response Time: {analysis['summary'].get('avg_response_time', 'N/A')} ms
794
+ Max Response Time: {analysis['summary'].get('max_response_time', 'N/A')} ms
795
+ Total Requests: {analysis['summary'].get('total_requests', 'N/A')}
796
+ Average CPU Usage: {analysis['summary'].get('avg_cpu_usage', 'N/A'):.2f}%
797
+ Max CPU Usage: {analysis['summary'].get('max_cpu_usage', 'N/A'):.2f}%
798
+ Average Memory Usage: {analysis['summary'].get('avg_memory_usage', 'N/A'):.2f}%
799
+ Max Memory Usage: {analysis['summary'].get('max_memory_usage', 'N/A'):.2f}%
800
+
801
+ Performance Issues:
802
+ ------------------
803
+ """
804
+
805
+ for issue in analysis['performance_issues']:
806
+ report += f"- {issue}\n"
807
+
808
+ report += "\nRecommendations:\n----------------\n"
809
+
810
+ for rec in analysis['recommendations']:
811
+ report += f"- {rec}\n"
812
+
813
+ with open('performance_report.txt', 'w') as f:
814
+ f.write(report)
815
+
816
+ print(report)
817
+
818
+ # Usage example
819
+ if __name__ == "__main__":
820
+ executor = PerformanceTestExecutor()
821
+
822
+ test_config = {
823
+ 'name': 'API Load Test',
824
+ 'script': 'k6/scenarios/user-journey.js',
825
+ 'base_url': 'http://localhost:3000'
826
+ }
827
+
828
+ executor.run_load_test(test_config)
829
+ analysis = executor.analyze_results()
830
+ ```
831
+
832
+ ## CI/CD Integration for Performance Testing
833
+ ```yaml
834
+ # .github/workflows/performance-tests.yml
835
+ name: Performance Tests
836
+
837
+ on:
838
+ schedule:
839
+ - cron: '0 2 * * *' # Daily at 2 AM
840
+ workflow_dispatch:
841
+ inputs:
842
+ test_environment:
843
+ description: 'Environment to test'
844
+ required: true
845
+ default: 'staging'
846
+ type: choice
847
+ options:
848
+ - staging
849
+ - production
850
+ test_duration:
851
+ description: 'Test duration in seconds'
852
+ required: true
853
+ default: '300'
854
+ concurrent_users:
855
+ description: 'Number of concurrent users'
856
+ required: true
857
+ default: '50'
858
+
859
+ jobs:
860
+ load-test:
861
+ runs-on: ubuntu-latest
862
+ environment: ${{ github.event.inputs.test_environment || 'staging' }}
863
+
864
+ steps:
865
+ - uses: actions/checkout@v3
866
+
867
+ - name: Setup Node.js
868
+ uses: actions/setup-node@v3
869
+ with:
870
+ node-version: 18
871
+
872
+ - name: Install K6
873
+ run: |
874
+ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
875
+ echo "deb [https://dl.k6.io/deb](https://dl.k6.io/deb) stable main" | sudo tee /etc/apt/sources.list.d/k6.list
876
+ sudo apt-get update
877
+ sudo apt-get install k6
878
+
879
+ - name: Setup performance monitoring
880
+ run: |
881
+ pip install psutil requests
882
+ sudo apt-get install postgresql-client
883
+
884
+ - name: Run smoke test
885
+ run: |
886
+ k6 run --vus 1 --duration 30s \
887
+ --env BASE_URL=${{ vars.BASE_URL }} \
888
+ k6/scenarios/smoke-test.js
889
+
890
+ - name: Run load test
891
+ run: |
892
+ python3 scripts/performance-monitor.py &
893
+ MONITOR_PID=$!
894
+
895
+ k6 run --vus ${{ github.event.inputs.concurrent_users || '50' }} \
896
+ --duration ${{ github.event.inputs.test_duration || '300' }}s \
897
+ --env BASE_URL=${{ vars.BASE_URL }} \
898
+ --out json=results.json \
899
+ k6/scenarios/user-journey.js
900
+
901
+ kill $MONITOR_PID || true
902
+
903
+ - name: Database performance test
904
+ run: |
905
+ ./scripts/database-performance-test.sh
906
+ env:
907
+ DB_HOST: ${{ secrets.DB_HOST }}
908
+ DB_USER: ${{ secrets.DB_USER }}
909
+ DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
910
+ DB_NAME: ${{ secrets.DB_NAME }}
911
+
912
+ - name: Analyze results
913
+ run: |
914
+ python3 scripts/analyze-performance-results.py
915
+
916
+ - name: Upload test results
917
+ uses: actions/upload-artifact@v3
918
+ with:
919
+ name: performance-test-results
920
+ path: |
921
+ results.json
922
+ performance_metrics.json
923
+ performance_report.txt
924
+ results/
925
+ retention-days: 30
926
+
927
+ - name: Performance regression check
928
+ run: |
929
+ python3 scripts/performance-regression-check.py \
930
+ --current-results results.json \
931
+ --baseline-results baseline/results.json \
932
+ --threshold 10
933
+
934
+ - name: Send Slack notification
935
+ if: failure()
936
+ uses: 8398a7/action-slack@v3
937
+ with:
938
+ status: failure
939
+ channel: '#performance-alerts'
940
+ text: 'Performance test failed on ${{ github.event.inputs.test_environment || "staging" }}'
941
+ env:
942
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
943
+
944
+ stress-test:
945
+ runs-on: ubuntu-latest
946
+ needs: load-test
947
+ if: github.event.inputs.test_environment == 'staging'
948
+
949
+ steps:
950
+ - uses: actions/checkout@v3
951
+
952
+ - name: Install K6
953
+ run: |
954
+ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
955
+ echo "deb [https://dl.k6.io/deb](https://dl.k6.io/deb) stable main" | sudo tee /etc/apt/sources.list.d/k6.list
956
+ sudo apt-get update
957
+ sudo apt-get install k6
958
+
959
+ - name: Run stress test
960
+ run: |
961
+ k6 run --env BASE_URL=${{ vars.BASE_URL }} \
962
+ --out json=stress-results.json \
963
+ k6/scenarios/stress-test.js
964
+
965
+ - name: Analyze stress test results
966
+ run: |
967
+ python3 scripts/analyze-stress-test.py stress-results.json
968
+
969
+ - name: Upload stress test results
970
+ uses: actions/upload-artifact@v3
971
+ with:
972
+ name: stress-test-results
973
+ path: stress-results.json
974
+ retention-days: 30
975
+ ```
976
+
977
+ ## Performance Budget and Monitoring
978
+ ```javascript
979
+ // scripts/performance-budget.js
980
+ const performanceBudget = {
981
+ // Response time budgets (in milliseconds)
982
+ responseTime: {
983
+ homepage: { p95: 1000, p99: 2000 },
984
+ api_endpoints: { p95: 500, p99: 1000 },
985
+ database_queries: { p95: 100, p99: 500 }
986
+ },
987
+
988
+ // Throughput budgets (requests per second)
989
+ throughput: {
990
+ api_endpoints: { min: 1000 },
991
+ homepage: { min: 500 }
992
+ },
993
+
994
+ // Error rate budgets (percentage)
995
+ errorRate: {
996
+ max: 0.1 // 0.1% maximum error rate
997
+ },
998
+
999
+ // Resource utilization budgets
1000
+ resources: {
1001
+ cpu: { max: 70 }, // 70% maximum CPU usage
1002
+ memory: { max: 80 }, // 80% maximum memory usage
1003
+ disk: { max: 85 } // 85% maximum disk usage
1004
+ }
1005
+ };
1006
+
1007
+ class PerformanceBudgetValidator {
1008
+ constructor(budget) {
1009
+ this.budget = budget;
1010
+ }
1011
+
1012
+ validateResults(testResults) {
1013
+ const violations = [];
1014
+
1015
+ // Validate response times
1016
+ if (testResults.responseTime) {
1017
+ for (const [endpoint, metrics] of Object.entries(testResults.responseTime)) {
1018
+ const budget = this.budget.responseTime[endpoint];
1019
+ if (budget) {
1020
+ if (metrics.p95 > budget.p95) {
1021
+ violations.push(`${endpoint} P95 response time (${metrics.p95}ms) exceeds budget (${budget.p95}ms)`);
1022
+ }
1023
+ if (metrics.p99 > budget.p99) {
1024
+ violations.push(`${endpoint} P99 response time (${metrics.p99}ms) exceeds budget (${budget.p99}ms)`);
1025
+ }
1026
+ }
1027
+ }
1028
+ }
1029
+
1030
+ // Validate throughput
1031
+ if (testResults.throughput) {
1032
+ for (const [endpoint, metrics] of Object.entries(testResults.throughput)) {
1033
+ const budget = this.budget.throughput[endpoint];
1034
+ if (budget && metrics.rps < budget.min) {
1035
+ violations.push(`${endpoint} throughput (${metrics.rps} RPS) below budget (${budget.min} RPS)`);
1036
+ }
1037
+ }
1038
+ }
1039
+
1040
+ // Validate error rates
1041
+ if (testResults.errorRate && testResults.errorRate > this.budget.errorRate.max) {
1042
+ violations.push(`Error rate (${testResults.errorRate}%) exceeds budget (${this.budget.errorRate.max}%)`);
1043
+ }
1044
+
1045
+ return {
1046
+ passed: violations.length === 0,
1047
+ violations: violations
1048
+ };
1049
+ }
1050
+ }
1051
+
1052
+ module.exports = { performanceBudget, PerformanceBudgetValidator };
1053
+ ```
1054
+
1055
+ ## Best Practices
1056
+ 1. **Test Environment Consistency**: Use production-like environments for testing
1057
+ 2. **Baseline Establishment**: Establish performance baselines and track trends
1058
+ 3. **Progressive Testing**: Start with smoke tests, then load, stress, and spike tests
1059
+ 4. **Monitoring Integration**: Monitor system resources during tests
1060
+ 5. **Automated Analysis**: Implement automated performance regression detection
1061
+ 6. **Performance Budgets**: Define and enforce performance budgets
1062
+ 7. **Continuous Testing**: Integrate performance tests into CI/CD pipelines
1063
+
1064
+ ## Performance Testing Strategy
1065
+ - Define clear performance objectives and acceptance criteria
1066
+ - Identify critical user journeys and peak usage scenarios
1067
+ - Establish realistic test data and environment setup
1068
+ - Implement comprehensive monitoring and alerting
1069
+ - Create actionable performance reports and recommendations
1070
+ - Regular performance reviews and optimization cycles
1071
+
1072
+ ## Approach
1073
+ - Start with application profiling to identify bottlenecks
1074
+ - Design realistic test scenarios based on production usage
1075
+ - Implement comprehensive monitoring during tests
1076
+ - Analyze results and provide actionable recommendations
1077
+ - Establish performance baselines and regression detection
1078
+ - Create automated performance testing pipelines
1079
+
1080
+ ## Output Format
1081
+ - Provide complete performance testing frameworks
1082
+ - Include monitoring and analysis configurations
1083
+ - Document performance budgets and SLAs
1084
+ - Add CI/CD integration examples
1085
+ - Include performance optimization recommendations
1086
+ - Provide comprehensive reporting and alerting setups