@ngocsangairvds/vsaf 3.1.27 → 3.2.2

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 (303) hide show
  1. package/package.json +2 -2
  2. package/src/global.js +65 -39
  3. package/tools/skills/vds-scripts-skill/.openskills.json +6 -0
  4. package/tools/skills/vds-scripts-skill/QUALITY.md +44 -0
  5. package/tools/skills/vds-scripts-skill/SKILL.md +135 -0
  6. package/tools/skills/vds-scripts-skill/references/audit-commands.md +171 -0
  7. package/tools/skills/vds-scripts-skill/references/capability-index.md +34 -0
  8. package/tools/skills/vds-scripts-skill/references/development-commands.md +12 -0
  9. package/tools/skills/vds-scripts-skill/references/google-sheets.md +73 -0
  10. package/tools/skills/vds-scripts-skill/references/integration-commands.md +17 -0
  11. package/tools/skills/vds-scripts-skill/references/platform-bootstrap.md +31 -0
  12. package/tools/skills/vds-scripts-skill/references/specialist-routing.md +14 -0
  13. package/tools/skills/vds-scripts-skill/references/validation-commands.md +15 -0
  14. package/tools/skills/vsaf-build/SKILL.md +32 -2
  15. package/tools/skills/vsaf-ship/SKILL.md +41 -10
  16. package/tools/skills/vsaf-test/SKILL.md +8 -0
  17. package/tools/vds-scripts/.mcp.json +11 -0
  18. package/tools/vds-scripts/.secrets.baseline +133 -0
  19. package/tools/vds-scripts/AGENTS.md +152 -0
  20. package/tools/vds-scripts/CLAUDE.md +101 -0
  21. package/tools/vds-scripts/CLI_COMMAND_OPTIMIZATION.md +156 -0
  22. package/tools/vds-scripts/PACKAGE_P125B_IMPLEMENTATION_SUMMARY.md +131 -0
  23. package/tools/vds-scripts/PROJECT_COMPLETION_SUMMARY.md +45 -0
  24. package/tools/vds-scripts/README.md +97 -0
  25. package/tools/vds-scripts/bitbucket_manifest_mapping.toml +34 -0
  26. package/tools/vds-scripts/bitbucket_orchestrator/ARCHITECTURE_ANALYSIS.md +258 -0
  27. package/tools/vds-scripts/bitbucket_orchestrator/BITBUCKET_API_PRACTICES.md +393 -0
  28. package/tools/vds-scripts/bitbucket_orchestrator/EVALUATION_REPORT.md +61 -0
  29. package/tools/vds-scripts/bitbucket_orchestrator/FEATURES.md +908 -0
  30. package/tools/vds-scripts/bitbucket_orchestrator/README.md +687 -0
  31. package/tools/vds-scripts/bitbucket_orchestrator/pyproject.toml +40 -0
  32. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/__init__.py +20 -0
  33. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/async_client.py +657 -0
  34. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/cli.py +2108 -0
  35. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/client.py +2534 -0
  36. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/config.py +171 -0
  37. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/errors.py +67 -0
  38. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/factory.py +185 -0
  39. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/protocols.py +244 -0
  40. package/tools/vds-scripts/bitbucket_orchestrator/tests/__init__.py +8 -0
  41. package/tools/vds-scripts/bitbucket_orchestrator/tests/conftest.py +65 -0
  42. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_advanced_search.py +151 -0
  43. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_async_client.py +546 -0
  44. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_branch_permissions.py +145 -0
  45. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_cli.py +115 -0
  46. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client.py +157 -0
  47. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_branch_conditions.py +79 -0
  48. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_code_advanced.py +163 -0
  49. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_code_file.py +32 -0
  50. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_deployment_environments.py +194 -0
  51. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_issues.py +164 -0
  52. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_pipelines_advanced.py +179 -0
  53. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_pr_blockers.py +119 -0
  54. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_repository_variables.py +156 -0
  55. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code.py +98 -0
  56. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code_advanced.py +282 -0
  57. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code_insights.py +335 -0
  58. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_conditions.py +147 -0
  59. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_config.py +131 -0
  60. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_deployment_env.py +352 -0
  61. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_factory.py +371 -0
  62. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_fork_operations.py +204 -0
  63. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_issue_cli.py +261 -0
  64. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_pipeline_advanced.py +270 -0
  65. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_pr_blocker.py +204 -0
  66. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_protocols.py +334 -0
  67. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_repo_settings.py +343 -0
  68. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_repo_variables.py +270 -0
  69. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_webhooks.py +189 -0
  70. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_workspace.py +233 -0
  71. package/tools/vds-scripts/bitbucket_orchestrator/uv.lock +742 -0
  72. package/tools/vds-scripts/confluence_orchestrator/Dockerfile +19 -0
  73. package/tools/vds-scripts/confluence_orchestrator/README.md +412 -0
  74. package/tools/vds-scripts/confluence_orchestrator/SYNC_SCRIPTS.md +127 -0
  75. package/tools/vds-scripts/confluence_orchestrator/SYNC_STANDARDIZATION.md +108 -0
  76. package/tools/vds-scripts/confluence_orchestrator/pyproject.toml +48 -0
  77. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/__init__.py +20 -0
  78. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/cli.py +2532 -0
  79. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/config.py +175 -0
  80. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content.py +290 -0
  81. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content_v2.py +94 -0
  82. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/crawl_tree.py +1835 -0
  83. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/errors.py +80 -0
  84. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/eventing.py +109 -0
  85. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/http.py +1114 -0
  86. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/orchestration.py +165 -0
  87. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/reporting.py +78 -0
  88. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/tree.py +121 -0
  89. package/tools/vds-scripts/confluence_orchestrator/sync_pdfs_from_markdown.py +213 -0
  90. package/tools/vds-scripts/confluence_orchestrator/sync_pdfs_to_confluence.py +305 -0
  91. package/tools/vds-scripts/confluence_orchestrator/sync_png_attachments.py +305 -0
  92. package/tools/vds-scripts/confluence_orchestrator/tests/__init__.py +0 -0
  93. package/tools/vds-scripts/confluence_orchestrator/tests/conftest.py +8 -0
  94. package/tools/vds-scripts/confluence_orchestrator/tests/test_advanced_content.py +224 -0
  95. package/tools/vds-scripts/confluence_orchestrator/tests/test_advanced_search.py +188 -0
  96. package/tools/vds-scripts/confluence_orchestrator/tests/test_cache_management.py +247 -0
  97. package/tools/vds-scripts/confluence_orchestrator/tests/test_cli.py +499 -0
  98. package/tools/vds-scripts/confluence_orchestrator/tests/test_config.py +83 -0
  99. package/tools/vds-scripts/confluence_orchestrator/tests/test_content.py +186 -0
  100. package/tools/vds-scripts/confluence_orchestrator/tests/test_content_flags.py +27 -0
  101. package/tools/vds-scripts/confluence_orchestrator/tests/test_crawl_tree.py +2250 -0
  102. package/tools/vds-scripts/confluence_orchestrator/tests/test_draft_management.py +223 -0
  103. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing.py +71 -0
  104. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_chaos.py +37 -0
  105. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_rate_limit.py +44 -0
  106. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_timeout.py +49 -0
  107. package/tools/vds-scripts/confluence_orchestrator/tests/test_export.py +230 -0
  108. package/tools/vds-scripts/confluence_orchestrator/tests/test_history.py +204 -0
  109. package/tools/vds-scripts/confluence_orchestrator/tests/test_http.py +117 -0
  110. package/tools/vds-scripts/confluence_orchestrator/tests/test_orchestration.py +91 -0
  111. package/tools/vds-scripts/confluence_orchestrator/tests/test_reporting.py +24 -0
  112. package/tools/vds-scripts/confluence_orchestrator/tests/test_search_cql.py +34 -0
  113. package/tools/vds-scripts/confluence_orchestrator/tests/test_space_management.py +237 -0
  114. package/tools/vds-scripts/confluence_orchestrator/tests/test_space_permissions.py +332 -0
  115. package/tools/vds-scripts/confluence_orchestrator/tests/test_user_group_management.py +388 -0
  116. package/tools/vds-scripts/confluence_orchestrator/uv.lock +1023 -0
  117. package/tools/vds-scripts/git_orchestrator/ENHANCEMENT_SUMMARY.md +119 -0
  118. package/tools/vds-scripts/git_orchestrator/README.md +280 -0
  119. package/tools/vds-scripts/git_orchestrator/VERIFICATION_REPORT.md +152 -0
  120. package/tools/vds-scripts/git_orchestrator/pyproject.toml +35 -0
  121. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__init__.py +7 -0
  122. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__main__.py +4 -0
  123. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/cli.py +847 -0
  124. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/logging_config.py +63 -0
  125. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/manifest.py +129 -0
  126. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/orchestrator.py +819 -0
  127. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/reporting.py +53 -0
  128. package/tools/vds-scripts/git_orchestrator/tests/__init__.py +0 -0
  129. package/tools/vds-scripts/git_orchestrator/tests/test_cli_settings.py +21 -0
  130. package/tools/vds-scripts/git_orchestrator/tests/test_integration.py +74 -0
  131. package/tools/vds-scripts/git_orchestrator/tests/test_manifest.py +79 -0
  132. package/tools/vds-scripts/git_orchestrator/tests/test_orchestrator.py +204 -0
  133. package/tools/vds-scripts/git_orchestrator/tests/test_public_api.py +236 -0
  134. package/tools/vds-scripts/git_orchestrator/tests/test_resilience.py +345 -0
  135. package/tools/vds-scripts/git_orchestrator/uv.lock +271 -0
  136. package/tools/vds-scripts/jira_orchestrator/README.md +770 -0
  137. package/tools/vds-scripts/jira_orchestrator/pyproject.toml +39 -0
  138. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/__init__.py +1 -0
  139. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/adapter.py +1320 -0
  140. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/cli.py +2271 -0
  141. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/config.py +138 -0
  142. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/errors.py +67 -0
  143. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/reporting.py +65 -0
  144. package/tools/vds-scripts/jira_orchestrator/tests/__init__.py +1 -0
  145. package/tools/vds-scripts/jira_orchestrator/tests/conftest.py +86 -0
  146. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_agile_list_payloads.py +54 -0
  147. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_bulk_operations.py +69 -0
  148. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_components.py +57 -0
  149. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_createmeta.py +45 -0
  150. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_dashboard.py +117 -0
  151. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_issue_properties.py +54 -0
  152. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_permissions_compat.py +42 -0
  153. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_reindex.py +42 -0
  154. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_remote_links.py +76 -0
  155. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_transitions.py +91 -0
  156. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_user_management.py +110 -0
  157. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_version_management.py +133 -0
  158. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_watchers.py +41 -0
  159. package/tools/vds-scripts/jira_orchestrator/tests/test_advanced_search.py +164 -0
  160. package/tools/vds-scripts/jira_orchestrator/tests/test_agile.py +256 -0
  161. package/tools/vds-scripts/jira_orchestrator/tests/test_application_properties.py +193 -0
  162. package/tools/vds-scripts/jira_orchestrator/tests/test_backlog.py +91 -0
  163. package/tools/vds-scripts/jira_orchestrator/tests/test_bulk_operations.py +277 -0
  164. package/tools/vds-scripts/jira_orchestrator/tests/test_cli.py +106 -0
  165. package/tools/vds-scripts/jira_orchestrator/tests/test_components.py +106 -0
  166. package/tools/vds-scripts/jira_orchestrator/tests/test_config.py +164 -0
  167. package/tools/vds-scripts/jira_orchestrator/tests/test_dashboard.py +122 -0
  168. package/tools/vds-scripts/jira_orchestrator/tests/test_discover_fields.py +207 -0
  169. package/tools/vds-scripts/jira_orchestrator/tests/test_filter_management.py +333 -0
  170. package/tools/vds-scripts/jira_orchestrator/tests/test_issue_archiving.py +164 -0
  171. package/tools/vds-scripts/jira_orchestrator/tests/test_issue_links.py +257 -0
  172. package/tools/vds-scripts/jira_orchestrator/tests/test_issue_properties.py +171 -0
  173. package/tools/vds-scripts/jira_orchestrator/tests/test_link_types.py +314 -0
  174. package/tools/vds-scripts/jira_orchestrator/tests/test_parse_set.py +37 -0
  175. package/tools/vds-scripts/jira_orchestrator/tests/test_permissions.py +273 -0
  176. package/tools/vds-scripts/jira_orchestrator/tests/test_reindex.py +81 -0
  177. package/tools/vds-scripts/jira_orchestrator/tests/test_remote_links.py +254 -0
  178. package/tools/vds-scripts/jira_orchestrator/tests/test_security_schemes.py +170 -0
  179. package/tools/vds-scripts/jira_orchestrator/tests/test_transitions_changelog.py +114 -0
  180. package/tools/vds-scripts/jira_orchestrator/tests/test_user_management.py +226 -0
  181. package/tools/vds-scripts/jira_orchestrator/tests/test_version_management.py +339 -0
  182. package/tools/vds-scripts/jira_orchestrator/tests/test_watchers.py +101 -0
  183. package/tools/vds-scripts/jira_orchestrator/tests/test_worklog.py +223 -0
  184. package/tools/vds-scripts/jira_orchestrator/uv.lock +738 -0
  185. package/tools/vds-scripts/mcp_server/Dockerfile +34 -0
  186. package/tools/vds-scripts/mcp_server/README.md +140 -0
  187. package/tools/vds-scripts/mcp_server/pyproject.toml +42 -0
  188. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/__init__.py +4 -0
  189. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/config.py +36 -0
  190. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/server.py +66 -0
  191. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/__init__.py +14 -0
  192. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/bitbucket_tools.py +47 -0
  193. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/confluence_tools.py +59 -0
  194. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/git_tools.py +71 -0
  195. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/jira_tools.py +63 -0
  196. package/tools/vds-scripts/mcp_server/tests/__init__.py +2 -0
  197. package/tools/vds-scripts/mcp_server/tests/conftest.py +29 -0
  198. package/tools/vds-scripts/mcp_server/tests/unit/__init__.py +2 -0
  199. package/tools/vds-scripts/mcp_server/tests/unit/test_bitbucket_tools.py +25 -0
  200. package/tools/vds-scripts/mcp_server/tests/unit/test_confluence_tools.py +25 -0
  201. package/tools/vds-scripts/mcp_server/tests/unit/test_git_tools.py +32 -0
  202. package/tools/vds-scripts/mcp_server/tests/unit/test_jira_tools.py +32 -0
  203. package/tools/vds-scripts/mcp_server/tests/verification/__init__.py +2 -0
  204. package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_confluence_tools.py +40 -0
  205. package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_jira_tools.py +37 -0
  206. package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_tool_registration.py +47 -0
  207. package/tools/vds-scripts/mcp_server/uv.lock +1032 -0
  208. package/tools/vds-scripts/mypy.ini +5 -0
  209. package/tools/vds-scripts/pyproject.toml +29 -0
  210. package/tools/vds-scripts/repo-manifest.yaml +273 -0
  211. package/tools/vds-scripts/repo-manifest.yaml.example +25 -0
  212. package/tools/vds-scripts/scripts/BRD-Validation-API.postman_collection.json +706 -0
  213. package/tools/vds-scripts/scripts/BRD-Validation-README.md +308 -0
  214. package/tools/vds-scripts/scripts/README.md +162 -0
  215. package/tools/vds-scripts/scripts/bootstrap_uv.sh +30 -0
  216. package/tools/vds-scripts/scripts/brd-validation-environment.json +51 -0
  217. package/tools/vds-scripts/scripts/brd-validation-test-results.json +13023 -0
  218. package/tools/vds-scripts/scripts/brd_coverage_report.json +276 -0
  219. package/tools/vds-scripts/scripts/create_memory_session.py +35 -0
  220. package/tools/vds-scripts/scripts/deployment/load_docker_images_offline.sh +90 -0
  221. package/tools/vds-scripts/scripts/final_completion_report.md +139 -0
  222. package/tools/vds-scripts/scripts/folder_structure_report.json +321 -0
  223. package/tools/vds-scripts/scripts/generate_completion_report.py +125 -0
  224. package/tools/vds-scripts/scripts/generate_intellij_modules.py +150 -0
  225. package/tools/vds-scripts/scripts/link_integrity_report.json +807 -0
  226. package/tools/vds-scripts/scripts/move_audit_artifact_pages.py +255 -0
  227. package/tools/vds-scripts/scripts/move_audit_artifact_pages_rest.py +165 -0
  228. package/tools/vds-scripts/scripts/move_wrong_dept_pages.py +216 -0
  229. package/tools/vds-scripts/scripts/save_intellij_memories.py +120 -0
  230. package/tools/vds-scripts/scripts/save_memories_to_vds_ai.py +83 -0
  231. package/tools/vds-scripts/scripts/save_memories_vds_style.py +129 -0
  232. package/tools/vds-scripts/scripts/search_intellij_memories.py +50 -0
  233. package/tools/vds-scripts/scripts/setup_intellij_workspace.py +65 -0
  234. package/tools/vds-scripts/scripts/target-state-automation/README.md +89 -0
  235. package/tools/vds-scripts/scripts/target-state-automation/confluence_sync_coordinator.sh +27 -0
  236. package/tools/vds-scripts/scripts/target-state-automation/coordination.sh +114 -0
  237. package/tools/vds-scripts/scripts/target-state-automation/diagram_coordinator.sh +25 -0
  238. package/tools/vds-scripts/scripts/target-state-automation/docs_root.sh +22 -0
  239. package/tools/vds-scripts/scripts/target-state-automation/generate_diagrams.sh +22 -0
  240. package/tools/vds-scripts/scripts/target-state-automation/markdown_coordinator.sh +25 -0
  241. package/tools/vds-scripts/scripts/target-state-automation/progress_dashboard.sh +17 -0
  242. package/tools/vds-scripts/scripts/target-state-automation/schema_coordinator.sh +25 -0
  243. package/tools/vds-scripts/scripts/target-state-automation/sync_confluence.sh +30 -0
  244. package/tools/vds-scripts/scripts/target-state-automation/update_dependencies.sh +19 -0
  245. package/tools/vds-scripts/scripts/target-state-automation/validate_links.sh +86 -0
  246. package/tools/vds-scripts/scripts/target-state-automation/validate_markdown.sh +52 -0
  247. package/tools/vds-scripts/scripts/target-state-automation/validate_schemas.sh +26 -0
  248. package/tools/vds-scripts/scripts/target-state-automation/validate_structure.sh +98 -0
  249. package/tools/vds-scripts/scripts/update_modules_xml.py +190 -0
  250. package/tools/vds-scripts/scripts/uv-workspace-alignment-verification-2026-03-25.md +128 -0
  251. package/tools/vds-scripts/scripts/validate_brd_coverage.py +179 -0
  252. package/tools/vds-scripts/scripts/validate_folder_structure.py +240 -0
  253. package/tools/vds-scripts/scripts/validate_link_integrity.py +272 -0
  254. package/tools/vds-scripts/scripts/vds_sh_helpers.sh +180 -0
  255. package/tools/vds-scripts/scripts/verification/phase2_portable_paths_ubuntu_docker.sh +26 -0
  256. package/tools/vds-scripts/scripts/worktree_uv.sh +48 -0
  257. package/tools/vds-scripts/uv.lock +8 -0
  258. package/tools/vds-scripts/vds_cli/README.md +126 -0
  259. package/tools/vds-scripts/vds_cli/VERIFICATION_REPORT.md +41 -0
  260. package/tools/vds-scripts/vds_cli/pyproject.toml +38 -0
  261. package/tools/vds-scripts/vds_cli/src/vds_cli/__init__.py +3 -0
  262. package/tools/vds-scripts/vds_cli/src/vds_cli/cli.py +173 -0
  263. package/tools/vds-scripts/vds_cli/src/vds_cli/docs_sync.py +1203 -0
  264. package/tools/vds-scripts/vds_cli/src/vds_cli/env.py +41 -0
  265. package/tools/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/__init__.py +3 -0
  266. package/tools/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/google_sheets_orchestrator.py +198 -0
  267. package/tools/vds-scripts/vds_cli/src/vds_cli/router.py +93 -0
  268. package/tools/vds-scripts/vds_cli/src/vds_cli/sync_api.py +647 -0
  269. package/tools/vds-scripts/vds_cli/src/vds_cli/sync_service.py +266 -0
  270. package/tools/vds-scripts/vds_cli/tests/__init__.py +2 -0
  271. package/tools/vds-scripts/vds_cli/tests/conftest.py +49 -0
  272. package/tools/vds-scripts/vds_cli/tests/unit/__init__.py +2 -0
  273. package/tools/vds-scripts/vds_cli/tests/unit/test_cli.py +143 -0
  274. package/tools/vds-scripts/vds_cli/tests/unit/test_docs_sync.py +422 -0
  275. package/tools/vds-scripts/vds_cli/tests/unit/test_env.py +51 -0
  276. package/tools/vds-scripts/vds_cli/tests/unit/test_router.py +72 -0
  277. package/tools/vds-scripts/vds_cli/tests/unit/test_sync_api.py +357 -0
  278. package/tools/vds-scripts/vds_cli/tests/unit/test_sync_service.py +160 -0
  279. package/tools/vds-scripts/vds_cli/tests/verification/__init__.py +2 -0
  280. package/tools/vds-scripts/vds_cli/tests/verification/test_bitbucket_real.py +33 -0
  281. package/tools/vds-scripts/vds_cli/tests/verification/test_confluence_real.py +35 -0
  282. package/tools/vds-scripts/vds_cli/tests/verification/test_jira_real.py +41 -0
  283. package/tools/vds-scripts/vds_cli/uv.lock +524 -0
  284. package/tools/vds-scripts/vds_cli_common/README.md +190 -0
  285. package/tools/vds-scripts/vds_cli_common/pyproject.toml +92 -0
  286. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/__init__.py +34 -0
  287. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/completers.py +139 -0
  288. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/context.py +201 -0
  289. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/env.py +119 -0
  290. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/errors.py +318 -0
  291. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/output.py +284 -0
  292. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/paths.py +78 -0
  293. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/testing.py +213 -0
  294. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/version.py +85 -0
  295. package/tools/vds-scripts/vds_cli_common/tests/__init__.py +1 -0
  296. package/tools/vds-scripts/vds_cli_common/tests/test_completers.py +148 -0
  297. package/tools/vds-scripts/vds_cli_common/tests/test_context.py +192 -0
  298. package/tools/vds-scripts/vds_cli_common/tests/test_env.py +102 -0
  299. package/tools/vds-scripts/vds_cli_common/tests/test_errors.py +186 -0
  300. package/tools/vds-scripts/vds_cli_common/tests/test_output.py +229 -0
  301. package/tools/vds-scripts/vds_cli_common/tests/test_paths.py +61 -0
  302. package/tools/vds-scripts/vds_cli_common/tests/test_testing.py +138 -0
  303. package/tools/vds-scripts/vds_cli_common/tests/test_version.py +64 -0
@@ -0,0 +1,115 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+ from unittest.mock import MagicMock, Mock, patch
5
+
6
+ import pytest
7
+ from typer.testing import CliRunner
8
+ from vds_bitbucket_orchestrator.cli import app
9
+ from vds_bitbucket_orchestrator.config import BitbucketSettings
10
+
11
+
12
+ @pytest.fixture
13
+ def runner() -> CliRunner:
14
+ """Create a CLI runner for testing."""
15
+ return CliRunner()
16
+
17
+
18
+ @pytest.fixture
19
+ def mock_settings() -> BitbucketSettings:
20
+ """Create mock settings for testing."""
21
+ return BitbucketSettings(
22
+ VDS_USERNAME="test_user",
23
+ VDS_PASSWORD="test_pass",
24
+ BITBUCKET_TOKEN="test_token",
25
+ BITBUCKET_BASE_URL="https://bitbucket.test.com",
26
+ BITBUCKET_MODE="server",
27
+ )
28
+
29
+
30
+ class TestBitbucketCLI:
31
+ """Regression coverage for top-level Bitbucket CLI commands."""
32
+
33
+ def test_version_option(self, runner: CliRunner) -> None:
34
+ """`--version` should print the CLI version and exit cleanly."""
35
+ result = runner.invoke(app, ["--version"])
36
+ assert result.exit_code == 0
37
+ assert "vds-bitbucket-orchestrator" in result.stdout
38
+
39
+ @patch("vds_bitbucket_orchestrator.cli.BitbucketClient")
40
+ @patch("vds_bitbucket_orchestrator.cli.load_settings")
41
+ def test_projects_command_success(
42
+ self,
43
+ mock_load: Mock,
44
+ mock_client_class: Mock,
45
+ runner: CliRunner,
46
+ mock_settings: BitbucketSettings,
47
+ sample_project_response: dict,
48
+ ) -> None:
49
+ """`projects` should call list_projects and emit JSON when --no-markdown is provided."""
50
+ mock_load.return_value = mock_settings
51
+
52
+ client_manager = MagicMock()
53
+ client_instance = client_manager.__enter__.return_value
54
+ client_instance.list_projects.return_value = [sample_project_response]
55
+ mock_client_class.return_value = client_manager
56
+
57
+ with runner.isolated_filesystem():
58
+ result = runner.invoke(app, ["--report-dir", ".", "projects", "--limit", "5"])
59
+ assert result.exit_code == 0
60
+ assert "Test Project" in result.stdout
61
+ client_instance.list_projects.assert_called_once_with(limit=5)
62
+ assert Path("projects.md").exists()
63
+
64
+ @patch("vds_bitbucket_orchestrator.cli.BitbucketClient")
65
+ @patch("vds_bitbucket_orchestrator.cli.load_settings")
66
+ def test_projects_command_handles_error(
67
+ self,
68
+ mock_load: Mock,
69
+ mock_client_class: Mock,
70
+ runner: CliRunner,
71
+ mock_settings: BitbucketSettings,
72
+ ) -> None:
73
+ """`projects` should exit non-zero when the client raises."""
74
+ mock_load.return_value = mock_settings
75
+
76
+ client_manager = MagicMock()
77
+ client_instance = client_manager.__enter__.return_value
78
+ client_instance.list_projects.side_effect = RuntimeError("boom")
79
+ mock_client_class.return_value = client_manager
80
+
81
+ with runner.isolated_filesystem():
82
+ result = runner.invoke(app, ["projects"])
83
+
84
+ assert result.exit_code != 0
85
+
86
+ @patch("vds_bitbucket_orchestrator.cli.BitbucketClient")
87
+ @patch("vds_bitbucket_orchestrator.cli.load_settings")
88
+ def test_repositories_command_success(
89
+ self,
90
+ mock_load: Mock,
91
+ mock_client_class: Mock,
92
+ runner: CliRunner,
93
+ mock_settings: BitbucketSettings,
94
+ sample_repository_response: dict,
95
+ ) -> None:
96
+ """`repositories` should call list_repositories with the provided project key."""
97
+ mock_load.return_value = mock_settings
98
+
99
+ client_manager = MagicMock()
100
+ client_instance = client_manager.__enter__.return_value
101
+ client_instance.list_repositories.return_value = [sample_repository_response]
102
+ mock_client_class.return_value = client_manager
103
+
104
+ with runner.isolated_filesystem():
105
+ result = runner.invoke(app, ["--report-dir", ".", "repositories", "TEST", "--limit", "7"])
106
+ assert result.exit_code == 0
107
+ assert "test-repo" in result.stdout
108
+ client_instance.list_repositories.assert_called_once_with("TEST", limit=7)
109
+ assert Path("TEST_repositories.md").exists()
110
+
111
+ def test_repositories_missing_project_argument(self, runner: CliRunner) -> None:
112
+ """`repositories` without the required project key should exit with usage error."""
113
+ result = runner.invoke(app, ["repositories"])
114
+ assert result.exit_code == 2
115
+ assert "Missing argument 'PROJECT_KEY'" in (result.stdout or result.stderr)
@@ -0,0 +1,157 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from unittest.mock import Mock, patch
5
+
6
+ import pytest
7
+ from vds_bitbucket_orchestrator.client import BitbucketClient
8
+ from vds_bitbucket_orchestrator.config import BitbucketSettings
9
+
10
+
11
+ @pytest.fixture
12
+ def mock_settings() -> BitbucketSettings:
13
+ """Create server-mode settings for testing."""
14
+ return BitbucketSettings(
15
+ VDS_USERNAME="test_user",
16
+ VDS_PASSWORD="test_pass",
17
+ BITBUCKET_TOKEN="test_token",
18
+ BITBUCKET_BASE_URL="https://bitbucket.test.com",
19
+ BITBUCKET_MODE="server",
20
+ )
21
+
22
+
23
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
24
+ def test_client_initialization_server_mode(mock_bitbucket_class: Mock, mock_settings: BitbucketSettings) -> None:
25
+ """Client should initialize correctly in server mode."""
26
+ client = BitbucketClient(mock_settings)
27
+ assert client._settings == mock_settings
28
+ assert client._settings.is_server_mode
29
+ assert not client._settings.is_cloud_mode
30
+ mock_bitbucket_class.assert_called_once()
31
+
32
+
33
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
34
+ def test_client_initialization_cloud_mode(mock_bitbucket_class: Mock) -> None:
35
+ """Client should initialize correctly in cloud mode."""
36
+ settings = BitbucketSettings(
37
+ BITBUCKET_TOKEN="test_token",
38
+ BITBUCKET_MODE="cloud",
39
+ BITBUCKET_CLOUD_WORKSPACE="test_workspace",
40
+ )
41
+ client = BitbucketClient(settings)
42
+ assert client._settings == settings
43
+ assert client._settings.is_cloud_mode
44
+ assert not client._settings.is_server_mode
45
+ mock_bitbucket_class.assert_called_once()
46
+
47
+
48
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
49
+ def test_list_projects_server_mode(mock_bitbucket_class: Mock, mock_settings: BitbucketSettings) -> None:
50
+ client = BitbucketClient(mock_settings)
51
+ mock_bitbucket = Mock()
52
+ mock_bitbucket.project_list.return_value = [{"key": "TEST", "name": "Test Project"}]
53
+ client._client = mock_bitbucket
54
+
55
+ result = client.list_projects()
56
+
57
+ assert result == [{"key": "TEST", "name": "Test Project"}]
58
+ mock_bitbucket.project_list.assert_called_once_with(limit=25)
59
+
60
+
61
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
62
+ def test_list_repositories_server_mode(mock_bitbucket_class: Mock, mock_settings: BitbucketSettings) -> None:
63
+ client = BitbucketClient(mock_settings)
64
+ mock_bitbucket = Mock()
65
+ mock_bitbucket.repo_list.return_value = [{"slug": "test-repo", "name": "Test Repository"}]
66
+ client._client = mock_bitbucket
67
+
68
+ result = client.list_repositories("TEST")
69
+
70
+ assert result == [{"slug": "test-repo", "name": "Test Repository"}]
71
+ mock_bitbucket.repo_list.assert_called_once_with("TEST", limit=25)
72
+
73
+
74
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
75
+ def test_get_project_server_mode(mock_bitbucket_class: Mock, mock_settings: BitbucketSettings) -> None:
76
+ client = BitbucketClient(mock_settings)
77
+ mock_bitbucket = Mock()
78
+ mock_bitbucket.project.return_value = {"key": "TEST", "name": "Test Project"}
79
+ client._client = mock_bitbucket
80
+
81
+ result = client.get_project("TEST")
82
+
83
+ assert result == {"key": "TEST", "name": "Test Project"}
84
+ mock_bitbucket.project.assert_called_once_with("TEST")
85
+
86
+
87
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
88
+ def test_get_repository_server_mode(mock_bitbucket_class: Mock, mock_settings: BitbucketSettings) -> None:
89
+ client = BitbucketClient(mock_settings)
90
+ mock_bitbucket = Mock()
91
+ mock_bitbucket.get_repo.return_value = {"slug": "test-repo", "name": "Test Repository"}
92
+ client._client = mock_bitbucket
93
+
94
+ result = client.get_repository("TEST", "test-repo")
95
+
96
+ assert result == {"slug": "test-repo", "name": "Test Repository"}
97
+ mock_bitbucket.get_repo.assert_called_once_with("TEST", "test-repo")
98
+
99
+
100
+ def test_get_url_server_mode(mock_settings: BitbucketSettings) -> None:
101
+ url = mock_settings.get_url()
102
+ assert url == "https://bitbucket.test.com"
103
+
104
+
105
+ def test_get_url_cloud_mode() -> None:
106
+ settings = BitbucketSettings(
107
+ BITBUCKET_TOKEN="test_token",
108
+ BITBUCKET_MODE="cloud",
109
+ BITBUCKET_CLOUD_WORKSPACE="test_workspace",
110
+ )
111
+ url = settings.get_url()
112
+ assert url == "https://api.bitbucket.org/workspace/test_workspace"
113
+
114
+
115
+ def test_get_url_cloud_mode_missing_workspace() -> None:
116
+ settings = BitbucketSettings(BITBUCKET_TOKEN="test_token", BITBUCKET_MODE="cloud")
117
+ with pytest.raises(ValueError, match="BITBUCKET_CLOUD_WORKSPACE is required"):
118
+ settings.get_url()
119
+
120
+
121
+ def test_get_auth_kwargs_with_token() -> None:
122
+ settings = BitbucketSettings(BITBUCKET_TOKEN="test_token")
123
+ auth_kwargs = settings.get_auth_kwargs()
124
+ assert auth_kwargs == {"token": "test_token"}
125
+
126
+
127
+ def test_get_auth_kwargs_with_username_password() -> None:
128
+ settings = BitbucketSettings(VDS_USERNAME="test_user", VDS_PASSWORD="test_pass")
129
+ auth_kwargs = settings.get_auth_kwargs()
130
+ assert auth_kwargs == {"username": "test_user", "password": "test_pass"}
131
+
132
+
133
+ @patch.dict(os.environ, {}, clear=True)
134
+ def test_get_auth_kwargs_no_credentials() -> None:
135
+ settings = BitbucketSettings(
136
+ VDS_USERNAME=None,
137
+ VDS_PASSWORD=None,
138
+ BITBUCKET_TOKEN=None,
139
+ )
140
+ with pytest.raises(ValueError, match="No valid authentication credentials"):
141
+ settings.get_auth_kwargs()
142
+
143
+
144
+ def test_require_basic_or_token_success() -> None:
145
+ settings = BitbucketSettings(BITBUCKET_TOKEN="test_token")
146
+ settings.require_basic_or_token()
147
+
148
+
149
+ @patch.dict(os.environ, {}, clear=True)
150
+ def test_require_basic_or_token_failure() -> None:
151
+ settings = BitbucketSettings(
152
+ VDS_USERNAME=None,
153
+ VDS_PASSWORD=None,
154
+ BITBUCKET_TOKEN=None,
155
+ )
156
+ with pytest.raises(ValueError, match="Missing credentials"):
157
+ settings.require_basic_or_token()
@@ -0,0 +1,79 @@
1
+ from __future__ import annotations
2
+
3
+ from unittest.mock import MagicMock, patch
4
+
5
+ import pytest
6
+ from vds_bitbucket_orchestrator.client import BitbucketClient, BitbucketClientError
7
+ from vds_bitbucket_orchestrator.config import BitbucketSettings
8
+
9
+
10
+ @pytest.fixture
11
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
12
+ def client(mock_bb: MagicMock) -> BitbucketClient:
13
+ mock_instance = MagicMock()
14
+ mock_bb.return_value = mock_instance
15
+ settings = BitbucketSettings(BITBUCKET_TOKEN="token")
16
+ return BitbucketClient(settings)
17
+
18
+
19
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
20
+ def test_set_branches_permissions_defaults(mock_bb: MagicMock) -> None:
21
+ stub = MagicMock()
22
+ stub.set_branches_permissions.return_value = {"ok": True}
23
+ mock_bb.return_value = stub
24
+ client = BitbucketClient(BitbucketSettings(BITBUCKET_TOKEN="token"))
25
+
26
+ result = client.set_branches_permissions(
27
+ "PRJ",
28
+ matcher_type="BRANCH",
29
+ matcher_value="refs/heads/main",
30
+ permission_type="READ_ONLY",
31
+ )
32
+
33
+ assert result == {"ok": True}
34
+ stub.set_branches_permissions.assert_called_once_with(
35
+ "PRJ",
36
+ multiple_permissions=False,
37
+ matcher_type="BRANCH",
38
+ matcher_value="refs/heads/main",
39
+ permission_type="READ_ONLY",
40
+ repository_slug=None,
41
+ except_users=[],
42
+ except_groups=[],
43
+ except_access_keys=[],
44
+ start=0,
45
+ limit=25,
46
+ )
47
+
48
+
49
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
50
+ def test_set_branches_permissions_error(mock_bb: MagicMock) -> None:
51
+ stub = MagicMock()
52
+ stub.set_branches_permissions.side_effect = RuntimeError("boom")
53
+ mock_bb.return_value = stub
54
+ client = BitbucketClient(BitbucketSettings(BITBUCKET_TOKEN="token"))
55
+
56
+ with pytest.raises(BitbucketClientError):
57
+ client.set_branches_permissions("PRJ")
58
+
59
+
60
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
61
+ def test_get_project_conditions_coerces_list(mock_bb: MagicMock) -> None:
62
+ stub = MagicMock()
63
+ stub.get_project_conditions.return_value = {"id": 1}
64
+ mock_bb.return_value = stub
65
+ client = BitbucketClient(BitbucketSettings(BITBUCKET_TOKEN="token"))
66
+
67
+ result = client.get_project_conditions("PRJ")
68
+ assert result == [{"id": 1}]
69
+
70
+
71
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
72
+ def test_get_project_conditions_handles_none(mock_bb: MagicMock) -> None:
73
+ stub = MagicMock()
74
+ stub.get_project_conditions.return_value = None
75
+ mock_bb.return_value = stub
76
+ client = BitbucketClient(BitbucketSettings(BITBUCKET_TOKEN="token"))
77
+
78
+ result = client.get_project_conditions("PRJ")
79
+ assert result == []
@@ -0,0 +1,163 @@
1
+ from __future__ import annotations
2
+
3
+ from unittest.mock import Mock, patch
4
+
5
+ import pytest
6
+ from vds_bitbucket_orchestrator.client import BitbucketClient
7
+ from vds_bitbucket_orchestrator.config import BitbucketSettings
8
+ from vds_bitbucket_orchestrator.errors import BitbucketClientError
9
+
10
+
11
+ class TestBitbucketClientCodeAdvanced:
12
+ """Test suite for BitbucketClient advanced code operations."""
13
+
14
+ @pytest.fixture
15
+ def server_settings(self) -> BitbucketSettings:
16
+ """Create server mode settings for testing."""
17
+ return BitbucketSettings(
18
+ VDS_USERNAME="test_user",
19
+ VDS_PASSWORD="test_pass",
20
+ BITBUCKET_BASE_URL="https://bitbucket.test.com",
21
+ BITBUCKET_MODE="server",
22
+ )
23
+
24
+ @pytest.fixture
25
+ def cloud_settings(self) -> BitbucketSettings:
26
+ """Create cloud mode settings for testing."""
27
+ return BitbucketSettings(
28
+ BITBUCKET_TOKEN="test_token",
29
+ BITBUCKET_MODE="cloud",
30
+ BITBUCKET_CLOUD_WORKSPACE="test_workspace",
31
+ )
32
+
33
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
34
+ def test_get_file_list_success(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
35
+ """Test successful file list retrieval."""
36
+ client = BitbucketClient(server_settings)
37
+ mock_bitbucket = Mock()
38
+ mock_bitbucket.get_file_list.return_value = [{"path": "file1.py"}, {"path": "file2.py"}]
39
+ client._client = mock_bitbucket
40
+
41
+ result = client.get_file_list("PRJ", "repo", sub_folder="src", query="*.py", start=0, limit=100)
42
+
43
+ mock_bitbucket.get_file_list.assert_called_once_with("PRJ", "repo", sub_folder="src", query="*.py", start=0, limit=100)
44
+ assert len(result) == 2
45
+ assert result[0]["path"] == "file1.py"
46
+
47
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
48
+ def test_get_file_list_returns_empty_list(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
49
+ """Test that get_file_list returns empty list when client returns None."""
50
+ client = BitbucketClient(server_settings)
51
+ mock_bitbucket = Mock()
52
+ mock_bitbucket.get_file_list.return_value = None
53
+ client._client = mock_bitbucket
54
+
55
+ result = client.get_file_list("PRJ", "repo")
56
+
57
+ assert result == []
58
+
59
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
60
+ def test_get_file_list_handles_error(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
61
+ """Test that get_file_list handles errors."""
62
+ client = BitbucketClient(server_settings)
63
+ mock_bitbucket = Mock()
64
+ mock_bitbucket.get_file_list.side_effect = Exception("API error")
65
+ client._client = mock_bitbucket
66
+
67
+ with pytest.raises(BitbucketClientError):
68
+ client.get_file_list("PRJ", "repo")
69
+
70
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
71
+ def test_get_commit_info_success(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
72
+ """Test successful commit info retrieval."""
73
+ client = BitbucketClient(server_settings)
74
+ mock_bitbucket = Mock()
75
+ mock_bitbucket.get_commit_info.return_value = {"id": "abc123", "message": "Test commit"}
76
+ client._client = mock_bitbucket
77
+
78
+ result = client.get_commit_info("PRJ", "repo", "abc123", path="file.py")
79
+
80
+ mock_bitbucket.get_commit_info.assert_called_once_with("PRJ", "repo", "abc123", path="file.py")
81
+ assert result["id"] == "abc123"
82
+
83
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
84
+ def test_get_commit_info_handles_error(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
85
+ """Test that get_commit_info handles errors."""
86
+ client = BitbucketClient(server_settings)
87
+ mock_bitbucket = Mock()
88
+ mock_bitbucket.get_commit_info.side_effect = Exception("API error")
89
+ client._client = mock_bitbucket
90
+
91
+ with pytest.raises(BitbucketClientError):
92
+ client.get_commit_info("PRJ", "repo", "abc123")
93
+
94
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
95
+ def test_get_commit_changes_with_commit_id(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
96
+ """Test successful commit changes retrieval with commit_id."""
97
+ client = BitbucketClient(server_settings)
98
+ mock_bitbucket = Mock()
99
+ mock_bitbucket.get_commit_changes.return_value = {"changes": []}
100
+ client._client = mock_bitbucket
101
+
102
+ result = client.get_commit_changes("PRJ", "repo", commit_id="abc123", merges="exclude")
103
+
104
+ mock_bitbucket.get_commit_changes.assert_called_once_with("PRJ", "repo", hash_newest=None, merges="exclude", commit_id="abc123")
105
+ assert result == {"changes": []}
106
+
107
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
108
+ def test_get_commit_changes_with_hash_newest(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
109
+ """Test successful commit changes retrieval with hash_newest."""
110
+ client = BitbucketClient(server_settings)
111
+ mock_bitbucket = Mock()
112
+ mock_bitbucket.get_commit_changes.return_value = {"changes": []}
113
+ client._client = mock_bitbucket
114
+
115
+ result = client.get_commit_changes("PRJ", "repo", hash_newest="def456", merges="include")
116
+
117
+ mock_bitbucket.get_commit_changes.assert_called_once_with("PRJ", "repo", hash_newest="def456", merges="include", commit_id=None)
118
+ assert result == {"changes": []}
119
+
120
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
121
+ def test_get_commit_changes_handles_error(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
122
+ """Test that get_commit_changes handles errors."""
123
+ client = BitbucketClient(server_settings)
124
+ mock_bitbucket = Mock()
125
+ mock_bitbucket.get_commit_changes.side_effect = Exception("API error")
126
+ client._client = mock_bitbucket
127
+
128
+ with pytest.raises(BitbucketClientError):
129
+ client.get_commit_changes("PRJ", "repo", commit_id="abc123")
130
+
131
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
132
+ def test_search_code_requires_cloud_mode(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
133
+ """Test that search_code requires Cloud mode."""
134
+ client = BitbucketClient(server_settings)
135
+
136
+ with pytest.raises(BitbucketClientError, match="Code search is only available in Bitbucket Cloud mode"):
137
+ client.search_code("workspace", "test query")
138
+
139
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
140
+ def test_search_code_success(self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings) -> None:
141
+ """Test successful code search in Cloud mode."""
142
+ client = BitbucketClient(cloud_settings)
143
+ mock_bitbucket = Mock()
144
+ mock_bitbucket.search_code.return_value = {"values": [{"file": {"path": "file.py"}}]}
145
+ client._client = mock_bitbucket
146
+
147
+ result = client.search_code("workspace", "def test", page=1, limit=20)
148
+
149
+ mock_bitbucket.search_code.assert_called_once_with("workspace", "def test", page=1, limit=20)
150
+ assert "values" in result
151
+ assert len(result["values"]) == 1
152
+
153
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
154
+ def test_search_code_handles_error(self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings) -> None:
155
+ """Test that search_code handles errors."""
156
+ client = BitbucketClient(cloud_settings)
157
+ mock_bitbucket = Mock()
158
+ mock_bitbucket.search_code.side_effect = Exception("API error")
159
+ client._client = mock_bitbucket
160
+
161
+ with pytest.raises(BitbucketClientError):
162
+ client.search_code("workspace", "test query")
163
+
@@ -0,0 +1,32 @@
1
+ from __future__ import annotations
2
+
3
+ from unittest.mock import Mock, patch
4
+
5
+ import pytest
6
+ from vds_bitbucket_orchestrator.client import BitbucketClient
7
+ from vds_bitbucket_orchestrator.config import BitbucketSettings
8
+
9
+
10
+ class TestBitbucketClientCodeFile:
11
+ """Tests for file content retrieval."""
12
+
13
+ @pytest.fixture
14
+ def server_settings(self) -> BitbucketSettings:
15
+ return BitbucketSettings(
16
+ VDS_USERNAME="test_user",
17
+ VDS_PASSWORD="test_pass",
18
+ BITBUCKET_BASE_URL="https://bitbucket.test.com",
19
+ BITBUCKET_MODE="server",
20
+ )
21
+
22
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
23
+ def test_get_content_of_file_decodes_bytes(self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings) -> None:
24
+ client = BitbucketClient(server_settings)
25
+ mock_bitbucket = Mock()
26
+ mock_bitbucket.get_content_of_file.return_value = b"hello world"
27
+ client._client = mock_bitbucket
28
+
29
+ result = client.get_content_of_file("PRJ", "repo", "README.md")
30
+
31
+ assert result == "hello world"
32
+