@ngocsangairvds/vsaf 3.1.27 → 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 (303) 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-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,284 @@
1
+ """Output Manager for unified CLI output across VDS CLIs.
2
+
3
+ This module provides OutputManager, a class that handles:
4
+ - JSON output (compact/pretty based on mode)
5
+ - Rich tables, panels, and formatted output
6
+ - Spinners for long-running operations
7
+ - Progress bars for batch operations
8
+ - Error messages with hints
9
+
10
+ Usage:
11
+ ctx = CLIContext.from_options(json_only=False)
12
+ out = OutputManager(ctx)
13
+
14
+ with out.spinner("Connecting..."):
15
+ result = client.ping()
16
+
17
+ out.output_json({"status": "ok"})
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import json
23
+ import sys
24
+ from collections.abc import Iterator
25
+ from contextlib import contextmanager
26
+ from typing import TYPE_CHECKING, Any
27
+
28
+ if TYPE_CHECKING:
29
+ from rich.progress import Progress
30
+ from rich.table import Table
31
+
32
+ from .context import CLIContext
33
+
34
+
35
+ class NullProgress:
36
+ """No-op progress bar for non-TTY environments."""
37
+
38
+ def add_task(self, description: str, total: float = 100.0, **kwargs: Any) -> int:
39
+ """Add a task (no-op)."""
40
+ return 0
41
+
42
+ def update(self, task_id: int, advance: float = 1.0, **kwargs: Any) -> None:
43
+ """Update task progress (no-op)."""
44
+
45
+ def __enter__(self) -> NullProgress:
46
+ """Enter context."""
47
+ return self
48
+
49
+ def __exit__(self, *args: Any) -> None:
50
+ """Exit context."""
51
+
52
+
53
+ class OutputManager:
54
+ """Unified output manager for VDS CLIs.
55
+
56
+ Handles all output operations with context-aware formatting:
57
+ - JSON output (always clean, parseable)
58
+ - Rich tables (TTY only)
59
+ - Spinners (TTY only, respects quiet mode)
60
+ - Progress bars (TTY only, respects quiet mode)
61
+ - Error messages (always shown, styled for TTY)
62
+ - Success/info/warning messages (respects quiet mode)
63
+
64
+ Args:
65
+ ctx: CLIContext instance for output settings
66
+ """
67
+
68
+ def __init__(self, ctx: CLIContext) -> None:
69
+ """Initialize OutputManager with CLI context."""
70
+
71
+ self.ctx: CLIContext = ctx
72
+ self._console = ctx.console
73
+ self._err_console = ctx.err_console
74
+
75
+ def output_json(self, data: dict[str, Any] | list[Any], pretty: bool = True) -> None:
76
+ """Output data as JSON to stdout.
77
+
78
+ In json_only mode, always outputs compact JSON.
79
+ Otherwise, outputs pretty-printed JSON or uses Rich JSON highlighting.
80
+
81
+ Args:
82
+ data: Data to output as JSON
83
+ pretty: Whether to pretty-print (ignored in json_only mode)
84
+ """
85
+ if self.ctx.json_only:
86
+ # Compact JSON for piping/parsing
87
+ print(json.dumps(data, default=str, ensure_ascii=False))
88
+ elif pretty and self.ctx.use_rich_output:
89
+ # Pretty JSON with syntax highlighting
90
+ from rich.json import JSON
91
+
92
+ self._console.print(JSON.from_data(data))
93
+ elif pretty:
94
+ print(json.dumps(data, indent=2, default=str, ensure_ascii=False))
95
+ else:
96
+ print(json.dumps(data, default=str, ensure_ascii=False))
97
+
98
+ def output_error(
99
+ self,
100
+ message: str,
101
+ *,
102
+ hint: str | None = None,
103
+ details: dict[str, Any] | None = None,
104
+ ) -> None:
105
+ """Output error message to stderr.
106
+
107
+ In json_only mode, outputs JSON error object.
108
+ Otherwise, outputs styled error with optional hint.
109
+
110
+ Args:
111
+ message: Error message
112
+ hint: Optional hint for resolution
113
+ details: Optional additional details
114
+ """
115
+ if self.ctx.json_only:
116
+ error_obj: dict[str, Any] = {"error": True, "message": message}
117
+ if hint:
118
+ error_obj["hint"] = hint
119
+ if details:
120
+ error_obj["details"] = details
121
+ print(json.dumps(error_obj), file=sys.stderr)
122
+ else:
123
+ self._err_console.print(f"[bold red]✗ Error:[/bold red] {message}")
124
+ if hint:
125
+ self._err_console.print(f"[yellow] 💡 Hint:[/yellow] {hint}")
126
+ if details:
127
+ for key, value in details.items():
128
+ self._err_console.print(f"[dim] {key}:[/dim] {value}")
129
+
130
+ def output_success(self, message: str) -> None:
131
+ """Output success message (suppressed in quiet/json mode).
132
+
133
+ Args:
134
+ message: Success message to display
135
+ """
136
+ if self.ctx.show_hints:
137
+ self._console.print(f"[bold green]✓[/bold green] {message}")
138
+
139
+ def output_warning(self, message: str) -> None:
140
+ """Output warning message (suppressed in quiet/json mode).
141
+
142
+ Args:
143
+ message: Warning message to display
144
+ """
145
+ if self.ctx.show_hints:
146
+ self._console.print(f"[bold yellow]⚠[/bold yellow] {message}")
147
+
148
+ def output_info(self, message: str) -> None:
149
+ """Output info message (suppressed in quiet/json mode).
150
+
151
+ Args:
152
+ message: Info message to display
153
+ """
154
+ if self.ctx.show_hints:
155
+ self._console.print(f"[blue]ℹ[/blue] {message}")
156
+
157
+ def suggest_next(self, commands: list[str]) -> None:
158
+ """Suggest next commands to run (suppressed in quiet/json mode).
159
+
160
+ Args:
161
+ commands: List of suggested commands
162
+ """
163
+ if self.ctx.show_hints and commands:
164
+ suggestions = ", ".join(f"[cyan]{cmd}[/cyan]" for cmd in commands)
165
+ self._console.print(f"\n[dim]Try next:[/dim] {suggestions}")
166
+
167
+ @contextmanager
168
+ def spinner(self, message: str) -> Iterator[None]:
169
+ """Show a spinner while executing a block.
170
+
171
+ The spinner is only shown when:
172
+ - stdout is a TTY
173
+ - not in json_only mode
174
+ - not in quiet mode
175
+
176
+ Args:
177
+ message: Message to display with spinner
178
+
179
+ Yields:
180
+ None
181
+ """
182
+ if not self.ctx.use_spinner:
183
+ yield
184
+ return
185
+
186
+ with self._err_console.status(f"[bold green]{message}", spinner="dots"):
187
+ yield
188
+
189
+ @contextmanager
190
+ def progress(
191
+ self,
192
+ description: str,
193
+ total: float = 100.0,
194
+ ) -> Iterator[Progress | NullProgress]:
195
+ """Create a progress bar context.
196
+
197
+ Returns NullProgress if progress should be hidden.
198
+
199
+ Args:
200
+ description: Description of the progress
201
+ total: Total number of steps
202
+
203
+ Yields:
204
+ Progress bar instance (or NullProgress if hidden)
205
+ """
206
+ if not self.ctx.use_progress:
207
+ yield NullProgress()
208
+ return
209
+
210
+ from rich.progress import (
211
+ BarColumn,
212
+ MofNCompleteColumn,
213
+ Progress,
214
+ SpinnerColumn,
215
+ TaskProgressColumn,
216
+ TextColumn,
217
+ TimeElapsedColumn,
218
+ TimeRemainingColumn,
219
+ )
220
+
221
+ progress = Progress(
222
+ SpinnerColumn(),
223
+ TextColumn("[bold blue]{task.description}"),
224
+ BarColumn(),
225
+ TaskProgressColumn(),
226
+ MofNCompleteColumn(),
227
+ TimeElapsedColumn(),
228
+ TimeRemainingColumn(),
229
+ console=self._err_console,
230
+ transient=True,
231
+ )
232
+
233
+ with progress:
234
+ yield progress
235
+
236
+ def table(
237
+ self,
238
+ title: str | None = None,
239
+ columns: list[str] | None = None,
240
+ rows: list[list[Any]] | None = None,
241
+ ) -> Table | None:
242
+ """Create and optionally populate a Rich table for output.
243
+
244
+ Returns None if tables should not be used (json_only or not TTY).
245
+
246
+ Args:
247
+ title: Optional table title
248
+ columns: Optional list of column names
249
+ rows: Optional list of row data
250
+
251
+ Returns:
252
+ Rich Table instance or None if tables shouldn't be used
253
+ """
254
+ if not self.ctx.use_rich_output:
255
+ return None
256
+
257
+ from rich.table import Table
258
+
259
+ table = Table(title=title)
260
+ if columns:
261
+ for col in columns:
262
+ table.add_column(col)
263
+ if rows:
264
+ for row in rows:
265
+ table.add_row(*[str(cell) for cell in row])
266
+ return table
267
+
268
+ def print(self, *args: Any, **kwargs: Any) -> None:
269
+ """Print to console (respects color settings).
270
+
271
+ Args:
272
+ *args: Arguments to print
273
+ **kwargs: Keyword arguments for console.print
274
+ """
275
+ self._console.print(*args, **kwargs)
276
+
277
+ def print_err(self, *args: Any, **kwargs: Any) -> None:
278
+ """Print to stderr (respects color settings).
279
+
280
+ Args:
281
+ *args: Arguments to print
282
+ **kwargs: Keyword arguments for console.print
283
+ """
284
+ self._err_console.print(*args, **kwargs)
@@ -0,0 +1,78 @@
1
+ """Path and configuration helpers for VDS scripts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from pathlib import Path
7
+
8
+ APP_NAME = "vds"
9
+ APP_AUTHOR = "VDS"
10
+ _PROJECT_ROOT = Path(__file__).resolve().parents[3]
11
+ _SCRIPTS_DIR = _PROJECT_ROOT.parent
12
+
13
+
14
+ def _default_vds_home() -> Path:
15
+ return Path.home() / ".vds"
16
+
17
+
18
+ def _optional_override(env_key: str) -> Path | None:
19
+ raw = (os.getenv(env_key) or "").strip()
20
+ if not raw:
21
+ return None
22
+ return Path(raw).expanduser().resolve()
23
+
24
+
25
+ def get_vds_config_root() -> Path:
26
+ override = _optional_override("VDS_CONFIG_DIR")
27
+ if override is not None:
28
+ return override
29
+ return _default_vds_home()
30
+
31
+
32
+ def get_vds_cache_root() -> Path:
33
+ override = _optional_override("VDS_CACHE_DIR")
34
+ if override is not None:
35
+ return override
36
+ return get_vds_config_root() / "cache"
37
+
38
+
39
+ def get_vds_data_root() -> Path:
40
+ override = _optional_override("VDS_DATA_DIR")
41
+ if override is not None:
42
+ return override
43
+ return get_vds_config_root() / "data"
44
+
45
+
46
+ def get_vds_log_root() -> Path:
47
+ override = _optional_override("VDS_LOG_DIR")
48
+ if override is not None:
49
+ return override
50
+ return get_vds_config_root() / "logs"
51
+
52
+
53
+ def get_shared_env_path() -> Path:
54
+ override = _optional_override("VDS_ENV_FILE")
55
+ if override is not None:
56
+ return override
57
+ return get_vds_config_root() / ".env"
58
+
59
+
60
+ def get_scripts_dir() -> Path:
61
+ return _SCRIPTS_DIR
62
+
63
+
64
+ def get_default_env_paths() -> tuple[Path, ...]:
65
+ return (get_shared_env_path(),)
66
+
67
+
68
+ __all__ = [
69
+ "APP_AUTHOR",
70
+ "APP_NAME",
71
+ "get_default_env_paths",
72
+ "get_scripts_dir",
73
+ "get_shared_env_path",
74
+ "get_vds_cache_root",
75
+ "get_vds_config_root",
76
+ "get_vds_data_root",
77
+ "get_vds_log_root",
78
+ ]
@@ -0,0 +1,213 @@
1
+ """Test fixtures and helpers for VDS CLI testing.
2
+
3
+ This module provides pytest fixtures and helper functions for testing
4
+ CLI components with TTY mocking, output capture, and environment control.
5
+
6
+ Usage:
7
+ from vds_cli_common.testing import mock_tty, mock_pipe, create_test_context
8
+
9
+ def test_tty_detection(mock_tty):
10
+ ctx = CLIContext()
11
+ assert ctx.is_tty is True
12
+
13
+ def test_pipe_mode(mock_pipe):
14
+ ctx = CLIContext()
15
+ assert ctx.is_tty is False
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import os
21
+ import sys
22
+ from collections.abc import Iterator
23
+ from contextlib import contextmanager
24
+ from typing import TYPE_CHECKING
25
+ from unittest.mock import patch
26
+
27
+ if TYPE_CHECKING:
28
+ from .context import CLIContext
29
+ from .output import OutputManager
30
+
31
+
32
+ @contextmanager
33
+ def mock_tty() -> Iterator[None]:
34
+ """Context manager to mock stdout as a TTY.
35
+
36
+ Usage:
37
+ with mock_tty():
38
+ ctx = CLIContext()
39
+ assert ctx.is_tty is True
40
+
41
+ Yields:
42
+ None
43
+ """
44
+ with patch.object(sys.stdout, "isatty", return_value=True):
45
+ yield
46
+
47
+
48
+ @contextmanager
49
+ def mock_pipe() -> Iterator[None]:
50
+ """Context manager to mock stdout as a pipe (non-TTY).
51
+
52
+ Usage:
53
+ with mock_pipe():
54
+ ctx = CLIContext()
55
+ assert ctx.is_tty is False
56
+
57
+ Yields:
58
+ None
59
+ """
60
+ with patch.object(sys.stdout, "isatty", return_value=False):
61
+ yield
62
+
63
+
64
+ @contextmanager
65
+ def mock_no_color_env() -> Iterator[None]:
66
+ """Context manager to mock NO_COLOR environment variable.
67
+
68
+ Usage:
69
+ with mock_no_color_env():
70
+ ctx = CLIContext()
71
+ assert ctx.use_color is False
72
+
73
+ Yields:
74
+ None
75
+ """
76
+ with patch.dict(os.environ, {"NO_COLOR": "1"}):
77
+ yield
78
+
79
+
80
+ @contextmanager
81
+ def mock_force_color_env() -> Iterator[None]:
82
+ """Context manager to mock FORCE_COLOR environment variable.
83
+
84
+ Usage:
85
+ with mock_force_color_env():
86
+ ctx = CLIContext()
87
+ assert ctx.use_color is True
88
+
89
+ Yields:
90
+ None
91
+ """
92
+ with patch.dict(os.environ, {"FORCE_COLOR": "1"}):
93
+ yield
94
+
95
+
96
+ @contextmanager
97
+ def capture_output() -> Iterator[dict[str, list[str]]]:
98
+ """Context manager to capture stdout and stderr for testing.
99
+
100
+ Usage:
101
+ with capture_output() as captured:
102
+ print("Hello")
103
+ assert "Hello" in captured["stdout"][0]
104
+
105
+ Yields:
106
+ Dictionary with "stdout" and "stderr" lists
107
+ """
108
+ captured: dict[str, list[str]] = {"stdout": [], "stderr": []}
109
+
110
+ original_stdout_write = sys.stdout.write
111
+ original_stderr_write = sys.stderr.write
112
+
113
+ def mock_stdout_write(text: str) -> int:
114
+ if text.strip(): # Skip empty/whitespace-only
115
+ captured["stdout"].append(text)
116
+ return len(text)
117
+
118
+ def mock_stderr_write(text: str) -> int:
119
+ if text.strip(): # Skip empty/whitespace-only
120
+ captured["stderr"].append(text)
121
+ return len(text)
122
+
123
+ with patch.object(sys.stdout, "write", mock_stdout_write), patch.object(sys.stderr, "write", mock_stderr_write):
124
+ yield captured
125
+
126
+
127
+ def create_test_context(
128
+ *,
129
+ json_only: bool = False,
130
+ quiet: bool = False,
131
+ no_color: bool = False,
132
+ force_color: bool = False,
133
+ is_tty: bool = True,
134
+ ) -> CLIContext:
135
+ """Create a CLIContext for testing with specified settings.
136
+
137
+ Args:
138
+ json_only: Enable JSON-only mode
139
+ quiet: Enable quiet mode
140
+ no_color: Disable colors
141
+ force_color: Force colors
142
+ is_tty: Mock TTY detection result
143
+
144
+ Returns:
145
+ Configured CLIContext instance
146
+ """
147
+ from .context import CLIContext
148
+
149
+ with patch.object(sys.stdout, "isatty", return_value=is_tty):
150
+ return CLIContext.from_options(
151
+ json_only=json_only,
152
+ quiet=quiet,
153
+ no_color=no_color,
154
+ force_color=force_color,
155
+ )
156
+
157
+
158
+ def create_test_output(ctx: CLIContext | None = None) -> OutputManager:
159
+ """Create an OutputManager for testing.
160
+
161
+ Args:
162
+ ctx: Optional CLIContext (creates default if not provided)
163
+
164
+ Returns:
165
+ Configured OutputManager instance
166
+ """
167
+ from .output import OutputManager
168
+
169
+ if ctx is None:
170
+ ctx = create_test_context()
171
+ return OutputManager(ctx)
172
+
173
+
174
+ # Pytest fixtures (can be used directly or as reference)
175
+ def pytest_fixtures() -> str:
176
+ """Return pytest fixture definitions for copy-paste into conftest.py.
177
+
178
+ Returns:
179
+ String containing pytest fixture code
180
+ """
181
+ return '''
182
+ import pytest
183
+ from vds_cli_common.testing import (
184
+ mock_tty as _mock_tty,
185
+ mock_pipe as _mock_pipe,
186
+ mock_no_color_env as _mock_no_color_env,
187
+ mock_force_color_env as _mock_force_color_env,
188
+ )
189
+
190
+ @pytest.fixture
191
+ def mock_tty():
192
+ """Mock stdout as a TTY."""
193
+ with _mock_tty():
194
+ yield
195
+
196
+ @pytest.fixture
197
+ def mock_pipe():
198
+ """Mock stdout as a pipe (non-TTY)."""
199
+ with _mock_pipe():
200
+ yield
201
+
202
+ @pytest.fixture
203
+ def mock_no_color_env():
204
+ """Mock NO_COLOR environment variable."""
205
+ with _mock_no_color_env():
206
+ yield
207
+
208
+ @pytest.fixture
209
+ def mock_force_color_env():
210
+ """Mock FORCE_COLOR environment variable."""
211
+ with _mock_force_color_env():
212
+ yield
213
+ '''
@@ -0,0 +1,85 @@
1
+ """Version callback factory for VDS CLIs.
2
+
3
+ This module provides a factory function for creating --version flag callbacks
4
+ that work consistently across all VDS CLIs.
5
+
6
+ Usage:
7
+ from vds_cli_common import create_version_callback
8
+
9
+ version_callback = create_version_callback("vds-elastic-orchestrator")
10
+
11
+ @app.callback()
12
+ def main(
13
+ version: bool = typer.Option(
14
+ False,
15
+ "--version",
16
+ "-V",
17
+ callback=version_callback,
18
+ is_eager=True,
19
+ help="Show version and exit",
20
+ ),
21
+ ):
22
+ pass
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import importlib.metadata
28
+ from collections.abc import Callable
29
+
30
+ import typer
31
+
32
+
33
+ def create_version_callback(package_name: str) -> Callable[[bool], None]:
34
+ """Create a version callback for a package.
35
+
36
+ The callback prints the package version and exits when --version is provided.
37
+
38
+ Args:
39
+ package_name: The package name to look up version for
40
+
41
+ Returns:
42
+ A callback function suitable for typer.Option
43
+
44
+ Example:
45
+ version_callback = create_version_callback("vds-elastic-orchestrator")
46
+
47
+ @app.callback()
48
+ def main(
49
+ version: bool = typer.Option(
50
+ False,
51
+ "--version",
52
+ "-V",
53
+ callback=version_callback,
54
+ is_eager=True,
55
+ help="Show version and exit",
56
+ ),
57
+ ):
58
+ pass
59
+ """
60
+
61
+ def callback(value: bool) -> None:
62
+ if value:
63
+ try:
64
+ version = importlib.metadata.version(package_name)
65
+ except importlib.metadata.PackageNotFoundError:
66
+ version = "unknown"
67
+ typer.echo(f"{package_name} {version}")
68
+ raise typer.Exit(0)
69
+
70
+ return callback
71
+
72
+
73
+ def get_package_version(package_name: str) -> str:
74
+ """Get the version of an installed package.
75
+
76
+ Args:
77
+ package_name: The package name to look up
78
+
79
+ Returns:
80
+ Version string or "unknown" if not found
81
+ """
82
+ try:
83
+ return importlib.metadata.version(package_name)
84
+ except importlib.metadata.PackageNotFoundError:
85
+ return "unknown"
@@ -0,0 +1 @@
1
+ """Tests for vds_cli_common package."""