@ngocsangairvds/vsaf 3.1.26 → 3.2.1

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 (305) hide show
  1. package/package.json +2 -2
  2. package/src/global.js +70 -10
  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-push-prd/SKILL.md +43 -40
  16. package/tools/skills/vsaf-push-srs/SKILL.md +44 -41
  17. package/tools/skills/vsaf-ship/SKILL.md +41 -10
  18. package/tools/skills/vsaf-test/SKILL.md +8 -0
  19. package/tools/vds-scripts/.mcp.json +11 -0
  20. package/tools/vds-scripts/.secrets.baseline +133 -0
  21. package/tools/vds-scripts/AGENTS.md +152 -0
  22. package/tools/vds-scripts/CLAUDE.md +101 -0
  23. package/tools/vds-scripts/CLI_COMMAND_OPTIMIZATION.md +156 -0
  24. package/tools/vds-scripts/PACKAGE_P125B_IMPLEMENTATION_SUMMARY.md +131 -0
  25. package/tools/vds-scripts/PROJECT_COMPLETION_SUMMARY.md +45 -0
  26. package/tools/vds-scripts/README.md +97 -0
  27. package/tools/vds-scripts/bitbucket_manifest_mapping.toml +34 -0
  28. package/tools/vds-scripts/bitbucket_orchestrator/ARCHITECTURE_ANALYSIS.md +258 -0
  29. package/tools/vds-scripts/bitbucket_orchestrator/BITBUCKET_API_PRACTICES.md +393 -0
  30. package/tools/vds-scripts/bitbucket_orchestrator/EVALUATION_REPORT.md +61 -0
  31. package/tools/vds-scripts/bitbucket_orchestrator/FEATURES.md +908 -0
  32. package/tools/vds-scripts/bitbucket_orchestrator/README.md +687 -0
  33. package/tools/vds-scripts/bitbucket_orchestrator/pyproject.toml +40 -0
  34. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/__init__.py +20 -0
  35. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/async_client.py +657 -0
  36. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/cli.py +2108 -0
  37. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/client.py +2534 -0
  38. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/config.py +171 -0
  39. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/errors.py +67 -0
  40. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/factory.py +185 -0
  41. package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/protocols.py +244 -0
  42. package/tools/vds-scripts/bitbucket_orchestrator/tests/__init__.py +8 -0
  43. package/tools/vds-scripts/bitbucket_orchestrator/tests/conftest.py +65 -0
  44. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_advanced_search.py +151 -0
  45. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_async_client.py +546 -0
  46. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_branch_permissions.py +145 -0
  47. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_cli.py +115 -0
  48. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client.py +157 -0
  49. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_branch_conditions.py +79 -0
  50. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_code_advanced.py +163 -0
  51. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_code_file.py +32 -0
  52. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_deployment_environments.py +194 -0
  53. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_issues.py +164 -0
  54. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_pipelines_advanced.py +179 -0
  55. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_pr_blockers.py +119 -0
  56. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_repository_variables.py +156 -0
  57. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code.py +98 -0
  58. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code_advanced.py +282 -0
  59. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code_insights.py +335 -0
  60. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_conditions.py +147 -0
  61. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_config.py +131 -0
  62. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_deployment_env.py +352 -0
  63. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_factory.py +371 -0
  64. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_fork_operations.py +204 -0
  65. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_issue_cli.py +261 -0
  66. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_pipeline_advanced.py +270 -0
  67. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_pr_blocker.py +204 -0
  68. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_protocols.py +334 -0
  69. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_repo_settings.py +343 -0
  70. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_repo_variables.py +270 -0
  71. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_webhooks.py +189 -0
  72. package/tools/vds-scripts/bitbucket_orchestrator/tests/test_workspace.py +233 -0
  73. package/tools/vds-scripts/bitbucket_orchestrator/uv.lock +742 -0
  74. package/tools/vds-scripts/confluence_orchestrator/Dockerfile +19 -0
  75. package/tools/vds-scripts/confluence_orchestrator/README.md +412 -0
  76. package/tools/vds-scripts/confluence_orchestrator/SYNC_SCRIPTS.md +127 -0
  77. package/tools/vds-scripts/confluence_orchestrator/SYNC_STANDARDIZATION.md +108 -0
  78. package/tools/vds-scripts/confluence_orchestrator/pyproject.toml +48 -0
  79. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/__init__.py +20 -0
  80. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/cli.py +2532 -0
  81. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/config.py +175 -0
  82. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content.py +290 -0
  83. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content_v2.py +94 -0
  84. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/crawl_tree.py +1835 -0
  85. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/errors.py +80 -0
  86. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/eventing.py +109 -0
  87. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/http.py +1114 -0
  88. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/orchestration.py +165 -0
  89. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/reporting.py +78 -0
  90. package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/tree.py +121 -0
  91. package/tools/vds-scripts/confluence_orchestrator/sync_pdfs_from_markdown.py +213 -0
  92. package/tools/vds-scripts/confluence_orchestrator/sync_pdfs_to_confluence.py +305 -0
  93. package/tools/vds-scripts/confluence_orchestrator/sync_png_attachments.py +305 -0
  94. package/tools/vds-scripts/confluence_orchestrator/tests/__init__.py +0 -0
  95. package/tools/vds-scripts/confluence_orchestrator/tests/conftest.py +8 -0
  96. package/tools/vds-scripts/confluence_orchestrator/tests/test_advanced_content.py +224 -0
  97. package/tools/vds-scripts/confluence_orchestrator/tests/test_advanced_search.py +188 -0
  98. package/tools/vds-scripts/confluence_orchestrator/tests/test_cache_management.py +247 -0
  99. package/tools/vds-scripts/confluence_orchestrator/tests/test_cli.py +499 -0
  100. package/tools/vds-scripts/confluence_orchestrator/tests/test_config.py +83 -0
  101. package/tools/vds-scripts/confluence_orchestrator/tests/test_content.py +186 -0
  102. package/tools/vds-scripts/confluence_orchestrator/tests/test_content_flags.py +27 -0
  103. package/tools/vds-scripts/confluence_orchestrator/tests/test_crawl_tree.py +2250 -0
  104. package/tools/vds-scripts/confluence_orchestrator/tests/test_draft_management.py +223 -0
  105. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing.py +71 -0
  106. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_chaos.py +37 -0
  107. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_rate_limit.py +44 -0
  108. package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_timeout.py +49 -0
  109. package/tools/vds-scripts/confluence_orchestrator/tests/test_export.py +230 -0
  110. package/tools/vds-scripts/confluence_orchestrator/tests/test_history.py +204 -0
  111. package/tools/vds-scripts/confluence_orchestrator/tests/test_http.py +117 -0
  112. package/tools/vds-scripts/confluence_orchestrator/tests/test_orchestration.py +91 -0
  113. package/tools/vds-scripts/confluence_orchestrator/tests/test_reporting.py +24 -0
  114. package/tools/vds-scripts/confluence_orchestrator/tests/test_search_cql.py +34 -0
  115. package/tools/vds-scripts/confluence_orchestrator/tests/test_space_management.py +237 -0
  116. package/tools/vds-scripts/confluence_orchestrator/tests/test_space_permissions.py +332 -0
  117. package/tools/vds-scripts/confluence_orchestrator/tests/test_user_group_management.py +388 -0
  118. package/tools/vds-scripts/confluence_orchestrator/uv.lock +1023 -0
  119. package/tools/vds-scripts/git_orchestrator/ENHANCEMENT_SUMMARY.md +119 -0
  120. package/tools/vds-scripts/git_orchestrator/README.md +280 -0
  121. package/tools/vds-scripts/git_orchestrator/VERIFICATION_REPORT.md +152 -0
  122. package/tools/vds-scripts/git_orchestrator/pyproject.toml +35 -0
  123. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__init__.py +7 -0
  124. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__main__.py +4 -0
  125. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/cli.py +847 -0
  126. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/logging_config.py +63 -0
  127. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/manifest.py +129 -0
  128. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/orchestrator.py +819 -0
  129. package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/reporting.py +53 -0
  130. package/tools/vds-scripts/git_orchestrator/tests/__init__.py +0 -0
  131. package/tools/vds-scripts/git_orchestrator/tests/test_cli_settings.py +21 -0
  132. package/tools/vds-scripts/git_orchestrator/tests/test_integration.py +74 -0
  133. package/tools/vds-scripts/git_orchestrator/tests/test_manifest.py +79 -0
  134. package/tools/vds-scripts/git_orchestrator/tests/test_orchestrator.py +204 -0
  135. package/tools/vds-scripts/git_orchestrator/tests/test_public_api.py +236 -0
  136. package/tools/vds-scripts/git_orchestrator/tests/test_resilience.py +345 -0
  137. package/tools/vds-scripts/git_orchestrator/uv.lock +271 -0
  138. package/tools/vds-scripts/jira_orchestrator/README.md +770 -0
  139. package/tools/vds-scripts/jira_orchestrator/pyproject.toml +39 -0
  140. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/__init__.py +1 -0
  141. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/adapter.py +1320 -0
  142. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/cli.py +2271 -0
  143. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/config.py +138 -0
  144. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/errors.py +67 -0
  145. package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/reporting.py +65 -0
  146. package/tools/vds-scripts/jira_orchestrator/tests/__init__.py +1 -0
  147. package/tools/vds-scripts/jira_orchestrator/tests/conftest.py +86 -0
  148. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_agile_list_payloads.py +54 -0
  149. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_bulk_operations.py +69 -0
  150. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_components.py +57 -0
  151. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_createmeta.py +45 -0
  152. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_dashboard.py +117 -0
  153. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_issue_properties.py +54 -0
  154. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_permissions_compat.py +42 -0
  155. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_reindex.py +42 -0
  156. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_remote_links.py +76 -0
  157. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_transitions.py +91 -0
  158. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_user_management.py +110 -0
  159. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_version_management.py +133 -0
  160. package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_watchers.py +41 -0
  161. package/tools/vds-scripts/jira_orchestrator/tests/test_advanced_search.py +164 -0
  162. package/tools/vds-scripts/jira_orchestrator/tests/test_agile.py +256 -0
  163. package/tools/vds-scripts/jira_orchestrator/tests/test_application_properties.py +193 -0
  164. package/tools/vds-scripts/jira_orchestrator/tests/test_backlog.py +91 -0
  165. package/tools/vds-scripts/jira_orchestrator/tests/test_bulk_operations.py +277 -0
  166. package/tools/vds-scripts/jira_orchestrator/tests/test_cli.py +106 -0
  167. package/tools/vds-scripts/jira_orchestrator/tests/test_components.py +106 -0
  168. package/tools/vds-scripts/jira_orchestrator/tests/test_config.py +164 -0
  169. package/tools/vds-scripts/jira_orchestrator/tests/test_dashboard.py +122 -0
  170. package/tools/vds-scripts/jira_orchestrator/tests/test_discover_fields.py +207 -0
  171. package/tools/vds-scripts/jira_orchestrator/tests/test_filter_management.py +333 -0
  172. package/tools/vds-scripts/jira_orchestrator/tests/test_issue_archiving.py +164 -0
  173. package/tools/vds-scripts/jira_orchestrator/tests/test_issue_links.py +257 -0
  174. package/tools/vds-scripts/jira_orchestrator/tests/test_issue_properties.py +171 -0
  175. package/tools/vds-scripts/jira_orchestrator/tests/test_link_types.py +314 -0
  176. package/tools/vds-scripts/jira_orchestrator/tests/test_parse_set.py +37 -0
  177. package/tools/vds-scripts/jira_orchestrator/tests/test_permissions.py +273 -0
  178. package/tools/vds-scripts/jira_orchestrator/tests/test_reindex.py +81 -0
  179. package/tools/vds-scripts/jira_orchestrator/tests/test_remote_links.py +254 -0
  180. package/tools/vds-scripts/jira_orchestrator/tests/test_security_schemes.py +170 -0
  181. package/tools/vds-scripts/jira_orchestrator/tests/test_transitions_changelog.py +114 -0
  182. package/tools/vds-scripts/jira_orchestrator/tests/test_user_management.py +226 -0
  183. package/tools/vds-scripts/jira_orchestrator/tests/test_version_management.py +339 -0
  184. package/tools/vds-scripts/jira_orchestrator/tests/test_watchers.py +101 -0
  185. package/tools/vds-scripts/jira_orchestrator/tests/test_worklog.py +223 -0
  186. package/tools/vds-scripts/jira_orchestrator/uv.lock +738 -0
  187. package/tools/vds-scripts/mcp_server/Dockerfile +34 -0
  188. package/tools/vds-scripts/mcp_server/README.md +140 -0
  189. package/tools/vds-scripts/mcp_server/pyproject.toml +42 -0
  190. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/__init__.py +4 -0
  191. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/config.py +36 -0
  192. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/server.py +66 -0
  193. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/__init__.py +14 -0
  194. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/bitbucket_tools.py +47 -0
  195. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/confluence_tools.py +59 -0
  196. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/git_tools.py +71 -0
  197. package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/jira_tools.py +63 -0
  198. package/tools/vds-scripts/mcp_server/tests/__init__.py +2 -0
  199. package/tools/vds-scripts/mcp_server/tests/conftest.py +29 -0
  200. package/tools/vds-scripts/mcp_server/tests/unit/__init__.py +2 -0
  201. package/tools/vds-scripts/mcp_server/tests/unit/test_bitbucket_tools.py +25 -0
  202. package/tools/vds-scripts/mcp_server/tests/unit/test_confluence_tools.py +25 -0
  203. package/tools/vds-scripts/mcp_server/tests/unit/test_git_tools.py +32 -0
  204. package/tools/vds-scripts/mcp_server/tests/unit/test_jira_tools.py +32 -0
  205. package/tools/vds-scripts/mcp_server/tests/verification/__init__.py +2 -0
  206. package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_confluence_tools.py +40 -0
  207. package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_jira_tools.py +37 -0
  208. package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_tool_registration.py +47 -0
  209. package/tools/vds-scripts/mcp_server/uv.lock +1032 -0
  210. package/tools/vds-scripts/mypy.ini +5 -0
  211. package/tools/vds-scripts/pyproject.toml +29 -0
  212. package/tools/vds-scripts/repo-manifest.yaml +273 -0
  213. package/tools/vds-scripts/repo-manifest.yaml.example +25 -0
  214. package/tools/vds-scripts/scripts/BRD-Validation-API.postman_collection.json +706 -0
  215. package/tools/vds-scripts/scripts/BRD-Validation-README.md +308 -0
  216. package/tools/vds-scripts/scripts/README.md +162 -0
  217. package/tools/vds-scripts/scripts/bootstrap_uv.sh +30 -0
  218. package/tools/vds-scripts/scripts/brd-validation-environment.json +51 -0
  219. package/tools/vds-scripts/scripts/brd-validation-test-results.json +13023 -0
  220. package/tools/vds-scripts/scripts/brd_coverage_report.json +276 -0
  221. package/tools/vds-scripts/scripts/create_memory_session.py +35 -0
  222. package/tools/vds-scripts/scripts/deployment/load_docker_images_offline.sh +90 -0
  223. package/tools/vds-scripts/scripts/final_completion_report.md +139 -0
  224. package/tools/vds-scripts/scripts/folder_structure_report.json +321 -0
  225. package/tools/vds-scripts/scripts/generate_completion_report.py +125 -0
  226. package/tools/vds-scripts/scripts/generate_intellij_modules.py +150 -0
  227. package/tools/vds-scripts/scripts/link_integrity_report.json +807 -0
  228. package/tools/vds-scripts/scripts/move_audit_artifact_pages.py +255 -0
  229. package/tools/vds-scripts/scripts/move_audit_artifact_pages_rest.py +165 -0
  230. package/tools/vds-scripts/scripts/move_wrong_dept_pages.py +216 -0
  231. package/tools/vds-scripts/scripts/save_intellij_memories.py +120 -0
  232. package/tools/vds-scripts/scripts/save_memories_to_vds_ai.py +83 -0
  233. package/tools/vds-scripts/scripts/save_memories_vds_style.py +129 -0
  234. package/tools/vds-scripts/scripts/search_intellij_memories.py +50 -0
  235. package/tools/vds-scripts/scripts/setup_intellij_workspace.py +65 -0
  236. package/tools/vds-scripts/scripts/target-state-automation/README.md +89 -0
  237. package/tools/vds-scripts/scripts/target-state-automation/confluence_sync_coordinator.sh +27 -0
  238. package/tools/vds-scripts/scripts/target-state-automation/coordination.sh +114 -0
  239. package/tools/vds-scripts/scripts/target-state-automation/diagram_coordinator.sh +25 -0
  240. package/tools/vds-scripts/scripts/target-state-automation/docs_root.sh +22 -0
  241. package/tools/vds-scripts/scripts/target-state-automation/generate_diagrams.sh +22 -0
  242. package/tools/vds-scripts/scripts/target-state-automation/markdown_coordinator.sh +25 -0
  243. package/tools/vds-scripts/scripts/target-state-automation/progress_dashboard.sh +17 -0
  244. package/tools/vds-scripts/scripts/target-state-automation/schema_coordinator.sh +25 -0
  245. package/tools/vds-scripts/scripts/target-state-automation/sync_confluence.sh +30 -0
  246. package/tools/vds-scripts/scripts/target-state-automation/update_dependencies.sh +19 -0
  247. package/tools/vds-scripts/scripts/target-state-automation/validate_links.sh +86 -0
  248. package/tools/vds-scripts/scripts/target-state-automation/validate_markdown.sh +52 -0
  249. package/tools/vds-scripts/scripts/target-state-automation/validate_schemas.sh +26 -0
  250. package/tools/vds-scripts/scripts/target-state-automation/validate_structure.sh +98 -0
  251. package/tools/vds-scripts/scripts/update_modules_xml.py +190 -0
  252. package/tools/vds-scripts/scripts/uv-workspace-alignment-verification-2026-03-25.md +128 -0
  253. package/tools/vds-scripts/scripts/validate_brd_coverage.py +179 -0
  254. package/tools/vds-scripts/scripts/validate_folder_structure.py +240 -0
  255. package/tools/vds-scripts/scripts/validate_link_integrity.py +272 -0
  256. package/tools/vds-scripts/scripts/vds_sh_helpers.sh +180 -0
  257. package/tools/vds-scripts/scripts/verification/phase2_portable_paths_ubuntu_docker.sh +26 -0
  258. package/tools/vds-scripts/scripts/worktree_uv.sh +48 -0
  259. package/tools/vds-scripts/uv.lock +8 -0
  260. package/tools/vds-scripts/vds_cli/README.md +126 -0
  261. package/tools/vds-scripts/vds_cli/VERIFICATION_REPORT.md +41 -0
  262. package/tools/vds-scripts/vds_cli/pyproject.toml +38 -0
  263. package/tools/vds-scripts/vds_cli/src/vds_cli/__init__.py +3 -0
  264. package/tools/vds-scripts/vds_cli/src/vds_cli/cli.py +173 -0
  265. package/tools/vds-scripts/vds_cli/src/vds_cli/docs_sync.py +1203 -0
  266. package/tools/vds-scripts/vds_cli/src/vds_cli/env.py +41 -0
  267. package/tools/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/__init__.py +3 -0
  268. package/tools/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/google_sheets_orchestrator.py +198 -0
  269. package/tools/vds-scripts/vds_cli/src/vds_cli/router.py +93 -0
  270. package/tools/vds-scripts/vds_cli/src/vds_cli/sync_api.py +647 -0
  271. package/tools/vds-scripts/vds_cli/src/vds_cli/sync_service.py +266 -0
  272. package/tools/vds-scripts/vds_cli/tests/__init__.py +2 -0
  273. package/tools/vds-scripts/vds_cli/tests/conftest.py +49 -0
  274. package/tools/vds-scripts/vds_cli/tests/unit/__init__.py +2 -0
  275. package/tools/vds-scripts/vds_cli/tests/unit/test_cli.py +143 -0
  276. package/tools/vds-scripts/vds_cli/tests/unit/test_docs_sync.py +422 -0
  277. package/tools/vds-scripts/vds_cli/tests/unit/test_env.py +51 -0
  278. package/tools/vds-scripts/vds_cli/tests/unit/test_router.py +72 -0
  279. package/tools/vds-scripts/vds_cli/tests/unit/test_sync_api.py +357 -0
  280. package/tools/vds-scripts/vds_cli/tests/unit/test_sync_service.py +160 -0
  281. package/tools/vds-scripts/vds_cli/tests/verification/__init__.py +2 -0
  282. package/tools/vds-scripts/vds_cli/tests/verification/test_bitbucket_real.py +33 -0
  283. package/tools/vds-scripts/vds_cli/tests/verification/test_confluence_real.py +35 -0
  284. package/tools/vds-scripts/vds_cli/tests/verification/test_jira_real.py +41 -0
  285. package/tools/vds-scripts/vds_cli/uv.lock +524 -0
  286. package/tools/vds-scripts/vds_cli_common/README.md +190 -0
  287. package/tools/vds-scripts/vds_cli_common/pyproject.toml +92 -0
  288. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/__init__.py +34 -0
  289. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/completers.py +139 -0
  290. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/context.py +201 -0
  291. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/env.py +119 -0
  292. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/errors.py +318 -0
  293. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/output.py +284 -0
  294. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/paths.py +78 -0
  295. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/testing.py +213 -0
  296. package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/version.py +85 -0
  297. package/tools/vds-scripts/vds_cli_common/tests/__init__.py +1 -0
  298. package/tools/vds-scripts/vds_cli_common/tests/test_completers.py +148 -0
  299. package/tools/vds-scripts/vds_cli_common/tests/test_context.py +192 -0
  300. package/tools/vds-scripts/vds_cli_common/tests/test_env.py +102 -0
  301. package/tools/vds-scripts/vds_cli_common/tests/test_errors.py +186 -0
  302. package/tools/vds-scripts/vds_cli_common/tests/test_output.py +229 -0
  303. package/tools/vds-scripts/vds_cli_common/tests/test_paths.py +61 -0
  304. package/tools/vds-scripts/vds_cli_common/tests/test_testing.py +138 -0
  305. package/tools/vds-scripts/vds_cli_common/tests/test_version.py +64 -0
@@ -0,0 +1,194 @@
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 TestBitbucketClientDeploymentEnvironments:
12
+ """Tests for BitbucketClient deployment environment operations."""
13
+
14
+ @pytest.fixture
15
+ def cloud_settings(self) -> BitbucketSettings:
16
+ return BitbucketSettings(
17
+ BITBUCKET_TOKEN="token",
18
+ BITBUCKET_MODE="cloud",
19
+ BITBUCKET_CLOUD_WORKSPACE="workspace",
20
+ )
21
+
22
+ @pytest.fixture
23
+ def server_settings(self) -> BitbucketSettings:
24
+ return BitbucketSettings(
25
+ VDS_USERNAME="user",
26
+ VDS_PASSWORD="pass",
27
+ BITBUCKET_BASE_URL="https://example.com",
28
+ BITBUCKET_MODE="server",
29
+ )
30
+
31
+ def _mock_repository(self) -> Mock:
32
+ repository = Mock()
33
+ deployment_environments = Mock()
34
+ environment = Mock()
35
+ environment.data = {"uuid": "{env}", "name": "Prod", "category": "production"}
36
+ deployment_environments.each.return_value = [environment]
37
+ deployment_environments.get.return_value = environment
38
+ repository.deployment_environments = deployment_environments
39
+
40
+ env_variables = Mock()
41
+ variable = Mock()
42
+ variable.data = {"uuid": "{var}", "key": "API_URL", "secured": False}
43
+ env_variables.each.return_value = [variable]
44
+ env_variables.get.return_value = variable
45
+ env_variables.create.return_value = variable
46
+ environment.deployment_environment_variables = env_variables
47
+ return repository
48
+
49
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
50
+ def test_list_deployment_environments_success(
51
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
52
+ ) -> None:
53
+ client = BitbucketClient(cloud_settings)
54
+ mock_bitbucket = Mock()
55
+ mock_bitbucket.cloud = Mock()
56
+ repository = self._mock_repository()
57
+ mock_bitbucket.cloud.repositories.get.return_value = repository
58
+ client._client = mock_bitbucket
59
+
60
+ environments = client.list_deployment_environments("workspace", "repo")
61
+
62
+ mock_bitbucket.cloud.repositories.get.assert_called_once_with("workspace", "repo")
63
+ assert len(environments) == 1
64
+ assert environments[0]["name"] == "Prod"
65
+
66
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
67
+ def test_get_deployment_environment_success(
68
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
69
+ ) -> None:
70
+ client = BitbucketClient(cloud_settings)
71
+ mock_bitbucket = Mock()
72
+ mock_bitbucket.cloud = Mock()
73
+ repository = self._mock_repository()
74
+ mock_bitbucket.cloud.repositories.get.return_value = repository
75
+ client._client = mock_bitbucket
76
+
77
+ environment = client.get_deployment_environment("workspace", "repo", "{env}")
78
+
79
+ repository.deployment_environments.get.assert_called_once_with("{env}")
80
+ assert environment["uuid"] == "{env}"
81
+
82
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
83
+ def test_list_deployment_environment_variables_success(
84
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
85
+ ) -> None:
86
+ client = BitbucketClient(cloud_settings)
87
+ mock_bitbucket = Mock()
88
+ mock_bitbucket.cloud = Mock()
89
+ repository = self._mock_repository()
90
+ mock_bitbucket.cloud.repositories.get.return_value = repository
91
+ client._client = mock_bitbucket
92
+
93
+ variables = client.list_deployment_environment_variables("workspace", "repo", "{env}", pagelen=5)
94
+
95
+ repository.deployment_environments.get.assert_called_once_with("{env}")
96
+ environment = repository.deployment_environments.get.return_value
97
+ environment.deployment_environment_variables.each.assert_called_once_with(pagelen=5)
98
+ assert variables[0]["key"] == "API_URL"
99
+
100
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
101
+ def test_create_deployment_environment_variable_success(
102
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
103
+ ) -> None:
104
+ client = BitbucketClient(cloud_settings)
105
+ mock_bitbucket = Mock()
106
+ mock_bitbucket.cloud = Mock()
107
+ repository = self._mock_repository()
108
+ mock_bitbucket.cloud.repositories.get.return_value = repository
109
+ client._client = mock_bitbucket
110
+
111
+ result = client.create_deployment_environment_variable("workspace", "repo", "{env}", "API_URL", "https://")
112
+
113
+ repository.deployment_environments.get.assert_called_once_with("{env}")
114
+ env = repository.deployment_environments.get.return_value
115
+ env.deployment_environment_variables.create.assert_called_once_with("API_URL", "https://", False)
116
+ assert result["key"] == "API_URL"
117
+
118
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
119
+ def test_update_deployment_environment_variable_success(
120
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
121
+ ) -> None:
122
+ client = BitbucketClient(cloud_settings)
123
+ mock_bitbucket = Mock()
124
+ mock_bitbucket.cloud = Mock()
125
+ repository = self._mock_repository()
126
+ mock_bitbucket.cloud.repositories.get.return_value = repository
127
+ client._client = mock_bitbucket
128
+
129
+ result = client.update_deployment_environment_variable(
130
+ "workspace", "repo", "{env}", "{var}", value="rotate", secured=True
131
+ )
132
+
133
+ env = repository.deployment_environments.get.return_value
134
+ env.deployment_environment_variables.get.assert_called_once_with("{var}")
135
+ env.deployment_environment_variables.get.return_value.update.assert_called_once_with(
136
+ value="rotate", secured=True
137
+ )
138
+ assert result["key"] == "API_URL"
139
+
140
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
141
+ def test_update_deployment_environment_variable_requires_fields(
142
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
143
+ ) -> None:
144
+ client = BitbucketClient(cloud_settings)
145
+ mock_bitbucket = Mock()
146
+ mock_bitbucket.cloud = Mock()
147
+ repository = self._mock_repository()
148
+ mock_bitbucket.cloud.repositories.get.return_value = repository
149
+ client._client = mock_bitbucket
150
+
151
+ with pytest.raises(BitbucketClientError):
152
+ client.update_deployment_environment_variable("workspace", "repo", "{env}", "{var}")
153
+
154
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
155
+ def test_delete_deployment_environment_variable_success(
156
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
157
+ ) -> None:
158
+ client = BitbucketClient(cloud_settings)
159
+ mock_bitbucket = Mock()
160
+ mock_bitbucket.cloud = Mock()
161
+ repository = self._mock_repository()
162
+ mock_bitbucket.cloud.repositories.get.return_value = repository
163
+ client._client = mock_bitbucket
164
+
165
+ client.delete_deployment_environment_variable("workspace", "repo", "{env}", "{var}")
166
+
167
+ env = repository.deployment_environments.get.return_value
168
+ env.deployment_environment_variables.get.assert_called_once_with("{var}")
169
+ env.deployment_environment_variables.get.return_value.delete.assert_called_once_with()
170
+
171
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
172
+ def test_deployment_environment_operations_require_cloud(
173
+ self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings
174
+ ) -> None:
175
+ client = BitbucketClient(server_settings)
176
+
177
+ with pytest.raises(BitbucketClientError):
178
+ client.list_deployment_environments("workspace", "repo")
179
+
180
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
181
+ def test_deployment_environment_methods_handle_error(
182
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
183
+ ) -> None:
184
+ client = BitbucketClient(cloud_settings)
185
+ mock_bitbucket = Mock()
186
+ mock_bitbucket.cloud = Mock()
187
+ repository = self._mock_repository()
188
+ repository.deployment_environments.each.side_effect = Exception("API error")
189
+ mock_bitbucket.cloud.repositories.get.return_value = repository
190
+ client._client = mock_bitbucket
191
+
192
+ with pytest.raises(BitbucketClientError):
193
+ client.list_deployment_environments("workspace", "repo")
194
+
@@ -0,0 +1,164 @@
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 TestBitbucketClientIssues:
12
+ """Tests for BitbucketClient repository issue operations."""
13
+
14
+ @pytest.fixture
15
+ def cloud_settings(self) -> BitbucketSettings:
16
+ return BitbucketSettings(
17
+ BITBUCKET_TOKEN="token",
18
+ BITBUCKET_MODE="cloud",
19
+ BITBUCKET_CLOUD_WORKSPACE="workspace",
20
+ )
21
+
22
+ @pytest.fixture
23
+ def server_settings(self) -> BitbucketSettings:
24
+ return BitbucketSettings(
25
+ VDS_USERNAME="user",
26
+ VDS_PASSWORD="pass",
27
+ BITBUCKET_BASE_URL="https://example.com",
28
+ BITBUCKET_MODE="server",
29
+ )
30
+
31
+ def _mock_repository(self) -> Mock:
32
+ repository = Mock()
33
+ issues = Mock()
34
+ issue = Mock()
35
+ issue.data = {"id": 1, "title": "Bug", "state": "open"}
36
+ issues.each.return_value = [issue]
37
+ issues.create.return_value = issue
38
+ issues.get.return_value = issue
39
+ repository.issues = issues
40
+ return repository
41
+
42
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
43
+ def test_list_repository_issues_success(
44
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
45
+ ) -> None:
46
+ client = BitbucketClient(cloud_settings)
47
+ mock_bitbucket = Mock()
48
+ mock_bitbucket.cloud = Mock()
49
+ repository = self._mock_repository()
50
+ mock_bitbucket.cloud.repositories.get.return_value = repository
51
+ client._client = mock_bitbucket
52
+
53
+ issues = client.list_repository_issues("workspace", "repo", query='state = "open"', sort="-updated_on")
54
+
55
+ repository.issues.each.assert_called_once_with(q='state = "open"', sort="-updated_on")
56
+ assert issues[0]["title"] == "Bug"
57
+
58
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
59
+ def test_create_repository_issue_success(
60
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
61
+ ) -> None:
62
+ client = BitbucketClient(cloud_settings)
63
+ mock_bitbucket = Mock()
64
+ mock_bitbucket.cloud = Mock()
65
+ repository = self._mock_repository()
66
+ mock_bitbucket.cloud.repositories.get.return_value = repository
67
+ client._client = mock_bitbucket
68
+
69
+ issue = client.create_repository_issue("workspace", "repo", "Bug found", "Details", kind="bug", priority="critical")
70
+
71
+ repository.issues.create.assert_called_once_with("Bug found", "Details", "bug", "critical")
72
+ assert issue["id"] == 1
73
+
74
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
75
+ def test_create_repository_issue_requires_title(
76
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
77
+ ) -> None:
78
+ client = BitbucketClient(cloud_settings)
79
+
80
+ with pytest.raises(BitbucketClientError):
81
+ client.create_repository_issue("workspace", "repo", "")
82
+
83
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
84
+ def test_get_repository_issue_success(
85
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
86
+ ) -> None:
87
+ client = BitbucketClient(cloud_settings)
88
+ mock_bitbucket = Mock()
89
+ mock_bitbucket.cloud = Mock()
90
+ repository = self._mock_repository()
91
+ mock_bitbucket.cloud.repositories.get.return_value = repository
92
+ client._client = mock_bitbucket
93
+
94
+ issue = client.get_repository_issue("workspace", "repo", 1)
95
+
96
+ repository.issues.get.assert_called_once_with(1)
97
+ assert issue["id"] == 1
98
+
99
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
100
+ def test_update_repository_issue_success(
101
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
102
+ ) -> None:
103
+ client = BitbucketClient(cloud_settings)
104
+ mock_bitbucket = Mock()
105
+ mock_bitbucket.cloud = Mock()
106
+ repository = self._mock_repository()
107
+ mock_bitbucket.cloud.repositories.get.return_value = repository
108
+ client._client = mock_bitbucket
109
+
110
+ issue = client.update_repository_issue(
111
+ "workspace",
112
+ "repo",
113
+ 1,
114
+ title="New Title",
115
+ kind="enhancement",
116
+ priority="minor",
117
+ state="resolved",
118
+ description="Updated details",
119
+ )
120
+
121
+ issue_obj = repository.issues.get.return_value
122
+ issue_obj.update.assert_called_once_with(
123
+ title="New Title",
124
+ kind="enhancement",
125
+ priority="minor",
126
+ state="resolved",
127
+ content={"raw": "Updated details"},
128
+ )
129
+ assert issue["id"] == 1
130
+
131
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
132
+ def test_update_repository_issue_requires_fields(
133
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
134
+ ) -> None:
135
+ client = BitbucketClient(cloud_settings)
136
+
137
+ with pytest.raises(BitbucketClientError):
138
+ client.update_repository_issue("workspace", "repo", 1)
139
+
140
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
141
+ def test_delete_repository_issue_success(
142
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
143
+ ) -> None:
144
+ client = BitbucketClient(cloud_settings)
145
+ mock_bitbucket = Mock()
146
+ mock_bitbucket.cloud = Mock()
147
+ repository = self._mock_repository()
148
+ mock_bitbucket.cloud.repositories.get.return_value = repository
149
+ client._client = mock_bitbucket
150
+
151
+ client.delete_repository_issue("workspace", "repo", 1)
152
+
153
+ repository.issues.get.assert_called_once_with(1)
154
+ repository.issues.get.return_value.delete.assert_called_once_with()
155
+
156
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
157
+ def test_issue_operations_require_cloud(
158
+ self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings
159
+ ) -> None:
160
+ client = BitbucketClient(server_settings)
161
+
162
+ with pytest.raises(BitbucketClientError):
163
+ client.list_repository_issues("workspace", "repo")
164
+
@@ -0,0 +1,179 @@
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 TestBitbucketClientPipelinesAdvanced:
12
+ """Tests for BitbucketClient advanced pipeline operations."""
13
+
14
+ @pytest.fixture
15
+ def cloud_settings(self) -> BitbucketSettings:
16
+ return BitbucketSettings(
17
+ BITBUCKET_TOKEN="token",
18
+ BITBUCKET_MODE="cloud",
19
+ BITBUCKET_CLOUD_WORKSPACE="workspace",
20
+ )
21
+
22
+ @pytest.fixture
23
+ def server_settings(self) -> BitbucketSettings:
24
+ return BitbucketSettings(
25
+ VDS_USERNAME="user",
26
+ VDS_PASSWORD="pass",
27
+ BITBUCKET_BASE_URL="https://example.com",
28
+ BITBUCKET_MODE="server",
29
+ )
30
+
31
+ def _mock_repository(self) -> Mock:
32
+ repository = Mock()
33
+ pipeline = Mock()
34
+ pipeline.data = {"uuid": "{pipeline}", "build_number": 42}
35
+ pipelines = Mock()
36
+ pipelines.get.return_value = pipeline
37
+ pipeline.steps.return_value = []
38
+ repository.pipelines = pipelines
39
+ return repository
40
+
41
+ def _mock_repository_with_step(self) -> Mock:
42
+ repository = Mock()
43
+ pipeline = Mock()
44
+ pipeline.data = {"uuid": "{pipeline}", "build_number": 42}
45
+
46
+ step = Mock()
47
+ step.data = {"uuid": "{step}", "state": "COMPLETED", "duration_in_seconds": 120}
48
+ pipeline.steps.return_value = [step]
49
+ pipeline.step.return_value = step
50
+ step.log.return_value = b"log output"
51
+
52
+ pipelines = Mock()
53
+ pipelines.get.return_value = pipeline
54
+ repository.pipelines = pipelines
55
+ return repository
56
+
57
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
58
+ def test_get_pipeline_success(self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings) -> None:
59
+ client = BitbucketClient(cloud_settings)
60
+ mock_bitbucket = Mock()
61
+ mock_bitbucket.cloud = Mock()
62
+ repository = self._mock_repository()
63
+ mock_bitbucket.cloud.repositories.get.return_value = repository
64
+ client._client = mock_bitbucket
65
+
66
+ pipeline = client.get_pipeline("workspace", "repo", "{pipeline}")
67
+
68
+ repository.pipelines.get.assert_called_once_with("{pipeline}")
69
+ assert pipeline["build_number"] == 42
70
+
71
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
72
+ def test_list_pipeline_steps_success(
73
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
74
+ ) -> None:
75
+ client = BitbucketClient(cloud_settings)
76
+ mock_bitbucket = Mock()
77
+ mock_bitbucket.cloud = Mock()
78
+ repository = self._mock_repository_with_step()
79
+ mock_bitbucket.cloud.repositories.get.return_value = repository
80
+ client._client = mock_bitbucket
81
+
82
+ steps = client.list_pipeline_steps("workspace", "repo", "{pipeline}")
83
+
84
+ assert len(steps) == 1
85
+ assert steps[0]["state"] == "COMPLETED"
86
+
87
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
88
+ def test_get_pipeline_step_success(self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings) -> None:
89
+ client = BitbucketClient(cloud_settings)
90
+ mock_bitbucket = Mock()
91
+ mock_bitbucket.cloud = Mock()
92
+ repository = self._mock_repository_with_step()
93
+ mock_bitbucket.cloud.repositories.get.return_value = repository
94
+ client._client = mock_bitbucket
95
+
96
+ step = client.get_pipeline_step("workspace", "repo", "{pipeline}", "{step}")
97
+
98
+ pipeline = repository.pipelines.get.return_value
99
+ pipeline.step.assert_called_once_with("{step}")
100
+ assert step["uuid"] == "{step}"
101
+
102
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
103
+ def test_get_pipeline_step_log_success(
104
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
105
+ ) -> None:
106
+ client = BitbucketClient(cloud_settings)
107
+ mock_bitbucket = Mock()
108
+ mock_bitbucket.cloud = Mock()
109
+ repository = self._mock_repository_with_step()
110
+ mock_bitbucket.cloud.repositories.get.return_value = repository
111
+ client._client = mock_bitbucket
112
+
113
+ payload = client.get_pipeline_step_log("workspace", "repo", "{pipeline}", "{step}")
114
+
115
+ assert payload["content"] == "log output"
116
+ assert payload["size"] == len("log output")
117
+
118
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
119
+ def test_get_pipeline_step_log_with_range(
120
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
121
+ ) -> None:
122
+ client = BitbucketClient(cloud_settings)
123
+ mock_bitbucket = Mock()
124
+ mock_bitbucket.cloud = Mock()
125
+ repository = self._mock_repository_with_step()
126
+ step = repository.pipelines.get.return_value.step.return_value
127
+ step.log.return_value = ("100", b"partial")
128
+ mock_bitbucket.cloud.repositories.get.return_value = repository
129
+ client._client = mock_bitbucket
130
+
131
+ payload = client.get_pipeline_step_log("workspace", "repo", "{pipeline}", "{step}", start=0, end=50)
132
+
133
+ assert payload["size"] == 100
134
+ assert payload["content"] == "partial"
135
+ assert payload["range_start"] == 0
136
+ assert payload["range_end"] == 50
137
+
138
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
139
+ def test_stop_pipeline_success(self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings) -> None:
140
+ client = BitbucketClient(cloud_settings)
141
+ mock_bitbucket = Mock()
142
+ mock_bitbucket.cloud = Mock()
143
+ repository = self._mock_repository()
144
+ pipeline = repository.pipelines.get.return_value
145
+ mock_bitbucket.cloud.repositories.get.return_value = repository
146
+ client._client = mock_bitbucket
147
+
148
+ payload = client.stop_pipeline("workspace", "repo", "{pipeline}")
149
+
150
+ pipeline.stop.assert_called_once_with()
151
+ assert payload["status"] == "stopped"
152
+
153
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
154
+ def test_pipeline_operations_require_cloud(
155
+ self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings
156
+ ) -> None:
157
+ client = BitbucketClient(server_settings)
158
+
159
+ with pytest.raises(BitbucketClientError):
160
+ client.get_pipeline("workspace", "repo", "{pipeline}")
161
+
162
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
163
+ def test_pipeline_step_requires_fields(
164
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
165
+ ) -> None:
166
+ client = BitbucketClient(cloud_settings)
167
+ mock_bitbucket = Mock()
168
+ mock_bitbucket.cloud = Mock()
169
+ repository = self._mock_repository_with_step()
170
+ pipeline = repository.pipelines.get.return_value
171
+ pipeline.steps.return_value = []
172
+ pipeline.step.side_effect = Exception("API error")
173
+ mock_bitbucket.cloud.repositories.get.return_value = repository
174
+ client._client = mock_bitbucket
175
+
176
+ with pytest.raises(BitbucketClientError):
177
+ client.get_pipeline_step("workspace", "repo", "{pipeline}", "{step}")
178
+
179
+
@@ -0,0 +1,119 @@
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 TestBitbucketClientPullRequestBlockers:
12
+ """Tests for BitbucketClient pull request blocker operations."""
13
+
14
+ @pytest.fixture
15
+ def cloud_settings(self) -> BitbucketSettings:
16
+ return BitbucketSettings(
17
+ BITBUCKET_TOKEN="token",
18
+ BITBUCKET_MODE="cloud",
19
+ BITBUCKET_CLOUD_WORKSPACE="workspace",
20
+ )
21
+
22
+ @pytest.fixture
23
+ def server_settings(self) -> BitbucketSettings:
24
+ return BitbucketSettings(
25
+ VDS_USERNAME="user",
26
+ VDS_PASSWORD="pass",
27
+ BITBUCKET_BASE_URL="https://example.com",
28
+ BITBUCKET_MODE="server",
29
+ )
30
+
31
+ def _mock_repository(self) -> Mock:
32
+ repository = Mock()
33
+ pull_request = Mock()
34
+ pull_request.get.return_value = {"values": [{"uuid": "{blocker}", "message": "Fix tests"}]}
35
+ pull_request.post.return_value = {"uuid": "{blocker}", "message": "Fix tests"}
36
+ repository.pullrequests.get.return_value = pull_request
37
+ return repository
38
+
39
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
40
+ def test_list_pull_request_blockers_success(
41
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
42
+ ) -> None:
43
+ client = BitbucketClient(cloud_settings)
44
+ mock_bitbucket = Mock()
45
+ mock_bitbucket.cloud = Mock()
46
+ repository = self._mock_repository()
47
+ mock_bitbucket.cloud.repositories.get.return_value = repository
48
+ client._client = mock_bitbucket
49
+
50
+ blockers = client.list_pull_request_blockers("workspace", "repo", 1, query="state = \"OPEN\"")
51
+
52
+ repository.pullrequests.get.assert_called_once_with(1)
53
+ pull_request = repository.pullrequests.get.return_value
54
+ pull_request.get.assert_called_once_with("blockers", params={"q": "state = \"OPEN\""})
55
+ assert blockers[0]["message"] == "Fix tests"
56
+
57
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
58
+ def test_add_pull_request_blocker_success(
59
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
60
+ ) -> None:
61
+ client = BitbucketClient(cloud_settings)
62
+ mock_bitbucket = Mock()
63
+ mock_bitbucket.cloud = Mock()
64
+ repository = self._mock_repository()
65
+ mock_bitbucket.cloud.repositories.get.return_value = repository
66
+ client._client = mock_bitbucket
67
+
68
+ blocker = client.add_pull_request_blocker("workspace", "repo", 1, "Needs QA", reason="QA failure")
69
+
70
+ pull_request = repository.pullrequests.get.return_value
71
+ pull_request.post.assert_called_once_with(
72
+ "blockers",
73
+ {"message": "Needs QA", "reason": "QA failure"},
74
+ )
75
+ assert blocker["uuid"] == "{blocker}"
76
+
77
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
78
+ def test_delete_pull_request_blocker_success(
79
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
80
+ ) -> None:
81
+ client = BitbucketClient(cloud_settings)
82
+ mock_bitbucket = Mock()
83
+ mock_bitbucket.cloud = Mock()
84
+ repository = self._mock_repository()
85
+ mock_bitbucket.cloud.repositories.get.return_value = repository
86
+ client._client = mock_bitbucket
87
+
88
+ client.delete_pull_request_blocker("workspace", "repo", 1, "{blocker}")
89
+
90
+ pull_request = repository.pullrequests.get.return_value
91
+ pull_request.delete.assert_called_once_with("blockers/{blocker}")
92
+
93
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
94
+ def test_add_pull_request_blocker_requires_message(
95
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
96
+ ) -> None:
97
+ client = BitbucketClient(cloud_settings)
98
+
99
+ with pytest.raises(BitbucketClientError):
100
+ client.add_pull_request_blocker("workspace", "repo", 1, "")
101
+
102
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
103
+ def test_delete_pull_request_blocker_requires_uuid(
104
+ self, mock_bitbucket_class: Mock, cloud_settings: BitbucketSettings
105
+ ) -> None:
106
+ client = BitbucketClient(cloud_settings)
107
+
108
+ with pytest.raises(BitbucketClientError):
109
+ client.delete_pull_request_blocker("workspace", "repo", 1, "")
110
+
111
+ @patch("vds_bitbucket_orchestrator.client.AtlassianBitbucket")
112
+ def test_pull_request_blocker_operations_require_cloud(
113
+ self, mock_bitbucket_class: Mock, server_settings: BitbucketSettings
114
+ ) -> None:
115
+ client = BitbucketClient(server_settings)
116
+
117
+ with pytest.raises(BitbucketClientError):
118
+ client.list_pull_request_blockers("workspace", "repo", 1)
119
+