framework-m-studio 0.8.2__tar.gz → 0.8.5__tar.gz

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 (165) hide show
  1. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/CHANGELOG.md +41 -0
  2. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/PKG-INFO +3 -3
  3. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/pyproject.toml +11 -4
  4. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/deps.py +69 -16
  5. framework_m_studio-0.8.5/src/framework_m_studio/cli/release/__init__.py +76 -0
  6. framework_m_studio-0.8.5/src/framework_m_studio/cli/release/cli.py +201 -0
  7. framework_m_studio-0.8.5/src/framework_m_studio/cli/release/gitops.py +194 -0
  8. framework_m_studio-0.8.5/src/framework_m_studio/cli/release/models.py +76 -0
  9. framework_m_studio-0.8.5/src/framework_m_studio/cli/release/orchestrator.py +389 -0
  10. framework_m_studio-0.8.5/src/framework_m_studio/cli/release/versioning.py +172 -0
  11. framework_m_studio-0.8.2/src/framework_m_studio/static/assets/index-BT9-FyVu.css → framework_m_studio-0.8.5/src/framework_m_studio/static/assets/index-BXzUquLi.css +1 -1
  12. framework_m_studio-0.8.2/src/framework_m_studio/static/assets/index-D11hOvMw.js → framework_m_studio-0.8.5/src/framework_m_studio/static/assets/index-C7HXLlUt.js +52 -52
  13. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/static/index.html +2 -2
  14. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/package.json +1 -1
  15. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/plugin/package.json.template +4 -4
  16. framework_m_studio-0.8.5/studio_ui/CHANGELOG.md +37 -0
  17. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/package.json +13 -13
  18. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_release_cli.py +271 -74
  19. framework_m_studio-0.8.2/src/framework_m_studio/cli/release.py +0 -888
  20. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/.gitignore +0 -0
  21. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/LICENSE +0 -0
  22. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/README.md +0 -0
  23. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/docs/api/index.md +0 -0
  24. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/docs/user-guide.md +0 -0
  25. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/__init__.py +0 -0
  26. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/app.py +0 -0
  27. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/__init__.py +0 -0
  28. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/codegen.py +0 -0
  29. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/constants.py +0 -0
  30. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/contrib.py +0 -0
  31. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/dev.py +0 -0
  32. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/docs.py +0 -0
  33. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/new.py +0 -0
  34. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/quality.py +0 -0
  35. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/studio.py +0 -0
  36. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/utility.py +0 -0
  37. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/cli/verify.py +0 -0
  38. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/codegen/__init__.py +0 -0
  39. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/codegen/generator.py +0 -0
  40. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/codegen/parser.py +0 -0
  41. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/codegen/templates/doctype.py.jinja2 +0 -0
  42. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/codegen/templates/test_doctype.py.jinja2 +0 -0
  43. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/codegen/test_generator.py +0 -0
  44. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/codegen/transformer.py +0 -0
  45. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/core/frontend.py +0 -0
  46. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/core/gitops.py +0 -0
  47. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/core/shell.py +0 -0
  48. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/discovery.py +0 -0
  49. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/docs/ast_parsers.py +0 -0
  50. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/docs/audit.py +0 -0
  51. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/docs/exporters.py +0 -0
  52. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/docs/formatters.py +0 -0
  53. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/docs/generator.py +0 -0
  54. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/docs/openapi.py +0 -0
  55. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/git/__init__.py +0 -0
  56. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/git/adapter.py +0 -0
  57. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/git/github_provider.py +0 -0
  58. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/git/protocol.py +0 -0
  59. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/protocol_scanner.py +0 -0
  60. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/py.typed +0 -0
  61. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/routes.py +0 -0
  62. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/sdk_generator.py +0 -0
  63. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/static/.gitkeep +0 -0
  64. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/static/favicon.ico +0 -0
  65. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/.gitignore +0 -0
  66. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/.npmrc +0 -0
  67. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/README.md +0 -0
  68. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/index.html +0 -0
  69. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/src/App.tsx +0 -0
  70. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/src/components/AppNavbar.tsx +0 -0
  71. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/src/components/AppSidebar.tsx +0 -0
  72. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/src/index.tsx +0 -0
  73. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/src/pages/LoginPage.tsx +0 -0
  74. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/src/theme.css +0 -0
  75. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/tsconfig.json +0 -0
  76. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/frontend/vite.config.ts +0 -0
  77. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/plugin/Dashboard.tsx.template +0 -0
  78. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/plugin/README.md.template +0 -0
  79. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/plugin/plugin.config.ts.template +0 -0
  80. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/plugin/tsconfig.json.template +0 -0
  81. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/templates/plugin/vite.config.mfe.ts.template +0 -0
  82. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/src/framework_m_studio/workspace.py +0 -0
  83. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/.gitignore +0 -0
  84. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/.npmrc +0 -0
  85. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/Dockerfile +0 -0
  86. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/README.md +0 -0
  87. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/eslint.config.js +0 -0
  88. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/index.html +0 -0
  89. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/pnpm-lock.yaml +0 -0
  90. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/App.css +0 -0
  91. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/App.test.tsx +0 -0
  92. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/App.tsx +0 -0
  93. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/AutoForm.tsx +0 -0
  94. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/AutoTable.tsx +0 -0
  95. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/CodePreview.tsx +0 -0
  96. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/ControllerEditor.tsx +0 -0
  97. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/ERDView.tsx +0 -0
  98. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/FieldEditor.tsx +0 -0
  99. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/LayoutDesigner.tsx +0 -0
  100. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/ModuleExplorer.tsx +0 -0
  101. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/NestedEditorDrawer.tsx +0 -0
  102. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/SandboxPreview.tsx +0 -0
  103. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/TableFieldEditor.tsx +0 -0
  104. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/breadcrumb/index.tsx +0 -0
  105. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/fields/DefaultFieldComponents.tsx +0 -0
  106. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/fields/index.ts +0 -0
  107. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/fields/resolveFieldComponent.ts +0 -0
  108. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/layout/index.tsx +0 -0
  109. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/components/menu/index.tsx +0 -0
  110. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/index.css +0 -0
  111. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/index.tsx +0 -0
  112. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/pages/doctypes/edit.tsx +0 -0
  113. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/pages/doctypes/index.ts +0 -0
  114. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/pages/doctypes/list.tsx +0 -0
  115. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/pages/index.ts +0 -0
  116. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/providers/ThemeContext.ts +0 -0
  117. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/providers/constants.ts +0 -0
  118. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/providers/data.ts +0 -0
  119. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/providers/theme.tsx +0 -0
  120. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/providers/useTheme.ts +0 -0
  121. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/registry/defaultComponents.ts +0 -0
  122. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/registry/fieldComponents.ts +0 -0
  123. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/registry/index.ts +0 -0
  124. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/services/mock_data.ts +0 -0
  125. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/setupTests.ts +0 -0
  126. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/utils/mockDataGenerator.ts +0 -0
  127. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/src/vite-env.d.ts +0 -0
  128. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/tsconfig.json +0 -0
  129. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/tsconfig.node.json +0 -0
  130. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/vite.config.ts +0 -0
  131. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/studio_ui/vitest.config.ts +0 -0
  132. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/cli/test_new.py +0 -0
  133. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/cli/test_verify.py +0 -0
  134. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/conftest.py +0 -0
  135. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/core/test_frontend.py +0 -0
  136. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/core/test_gitops.py +0 -0
  137. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/core/test_shell.py +0 -0
  138. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_api_routes.py +0 -0
  139. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_cli.py +0 -0
  140. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_cli_openapi.py +0 -0
  141. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_contrib_cli.py +0 -0
  142. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_deps_cli.py +0 -0
  143. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_dev.py +0 -0
  144. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_dev_cli_coverage.py +0 -0
  145. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_discovery.py +0 -0
  146. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_docs_audit.py +0 -0
  147. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_docs_generator.py +0 -0
  148. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_docs_generator_enhanced.py +0 -0
  149. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_frontend_integration.py +0 -0
  150. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_generator.py +0 -0
  151. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_git_adapter.py +0 -0
  152. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_git_protocol.py +0 -0
  153. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_github_provider.py +0 -0
  154. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_new_cli.py +0 -0
  155. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_parser.py +0 -0
  156. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_protocol_scanner.py +0 -0
  157. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_quality_cli.py +0 -0
  158. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_screenshot_pipeline.py +0 -0
  159. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_sdk_generator.py +0 -0
  160. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_studio.py +0 -0
  161. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_studio_codegen_generator.py +0 -0
  162. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_transformer.py +0 -0
  163. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_utility_cli.py +0 -0
  164. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_utility_cli_enhanced.py +0 -0
  165. {framework_m_studio-0.8.2 → framework_m_studio-0.8.5}/tests/test_workspace.py +0 -0
@@ -1,3 +1,44 @@
1
+ ## framework-m-studio v0.8.5
2
+
3
+ ### Bug Fixes
4
+
5
+ - add node types to tsconfig and sync related apps (da1934f)
6
+
7
+ ## framework-m-studio v0.8.4
8
+
9
+ ### Bug Fixes
10
+
11
+ - implement bulk dependency upgrades and fix typecheck stubs (bf01d94)
12
+ - install pnpm and coreutils in release phase (ed335f8)
13
+ - enforce tool availability and install pnpm in CI (b8f9465)
14
+ - enforce lockfile sync, stage templates, and fix types (a41aad0)
15
+ - enhance local dry-run and silence check-ignore spam (29f9ef6)
16
+ - modernize gitops auth and api integration (7f15453)
17
+ - secure staging logic and resolve test regressions (e31d701)
18
+ - implement pnpm/uv lockfile sync and config cleanup (8302956)
19
+ - lint cleanup for cli.py (40b3a78)
20
+ - support GITLAB_TOKEN and harden auth check (c08b25c)
21
+ - implement atomic direct push for CI/CD stability (2947270)
22
+ - harden sync orchestration and align warning filters (714f9ba)
23
+ - modularize release package and resolve test regressions (fe8c676)
24
+
25
+ ## framework-m-studio v0.8.3
26
+
27
+ ### Bug Fixes
28
+
29
+ - install pnpm and coreutils in release phase (ed335f8)
30
+ - enforce tool availability and install pnpm in CI (b8f9465)
31
+ - enforce lockfile sync, stage templates, and fix types (a41aad0)
32
+ - enhance local dry-run and silence check-ignore spam (29f9ef6)
33
+ - modernize gitops auth and api integration (7f15453)
34
+ - secure staging logic and resolve test regressions (e31d701)
35
+ - implement pnpm/uv lockfile sync and config cleanup (8302956)
36
+ - lint cleanup for cli.py (40b3a78)
37
+ - support GITLAB_TOKEN and harden auth check (c08b25c)
38
+ - implement atomic direct push for CI/CD stability (2947270)
39
+ - harden sync orchestration and align warning filters (714f9ba)
40
+ - modularize release package and resolve test regressions (fe8c676)
41
+
1
42
  # Changelog
2
43
 
3
44
  ## framework-m-studio v0.8.2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: framework-m-studio
3
- Version: 0.8.2
3
+ Version: 0.8.5
4
4
  Summary: Framework M Studio - Visual DocType Builder & Developer Tools
5
5
  Project-URL: Homepage, https://gitlab.com/castlecraft/framework-m
6
6
  Project-URL: Documentation, https://gitlab.com/castlecraft/framework-m#readme
@@ -20,8 +20,8 @@ Classifier: Typing :: Typed
20
20
  Requires-Python: >=3.12
21
21
  Requires-Dist: bandit>=1.9.4
22
22
  Requires-Dist: build>=1.0.0
23
- Requires-Dist: framework-m-core>=0.11.2
24
- Requires-Dist: framework-m>=0.6.6
23
+ Requires-Dist: framework-m-core>=0.11.4
24
+ Requires-Dist: framework-m>=0.6.8
25
25
  Requires-Dist: honcho>=1.1.0
26
26
  Requires-Dist: httpx>=0.27.0
27
27
  Requires-Dist: ipython>=9.11.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "framework-m-studio"
3
- version = "0.8.2"
3
+ version = "0.8.5"
4
4
  description = "Framework M Studio - Visual DocType Builder & Developer Tools"
5
5
  readme = "README.md"
6
6
  license = { text = "Apache-2.0" }
@@ -21,8 +21,8 @@ classifiers = [
21
21
  ]
22
22
 
23
23
  dependencies = [
24
- "framework-m-core>=0.11.2",
25
- "framework-m>=0.6.6",
24
+ "framework-m-core>=0.11.4",
25
+ "framework-m>=0.6.8",
26
26
  # Code generation
27
27
  "libcst>=1.0.0",
28
28
  "jinja2>=3.1.0",
@@ -116,7 +116,10 @@ asyncio_mode = "auto"
116
116
  testpaths = ["tests"]
117
117
  addopts = "-v --tb=short"
118
118
  filterwarnings = [
119
- "ignore:Core Pydantic V1 functionality isn't compatible with Python .* or greater.:UserWarning",
119
+ "ignore::DeprecationWarning",
120
+ "ignore::pytest.PytestRemovedIn9Warning",
121
+ "ignore:Core Pydantic V1 functionality isn't compatible.*:UserWarning:litestar.*",
122
+ "ignore:unclosed database in <sqlite3.Connection.*:ResourceWarning",
120
123
  ]
121
124
 
122
125
  [tool.coverage.run]
@@ -145,6 +148,10 @@ ignore_missing_imports = true
145
148
  module = "honcho.*"
146
149
  ignore_missing_imports = true
147
150
 
151
+ [[tool.mypy.overrides]]
152
+ module = "yaml"
153
+ ignore_missing_imports = true
154
+
148
155
  [tool.ruff]
149
156
  line-length = 88
150
157
  target-version = "py312"
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  import json
6
6
  import os
7
7
  import sys
8
+ from datetime import datetime
8
9
  from pathlib import Path
9
10
  from typing import Annotated
10
11
 
@@ -94,7 +95,10 @@ def deps_check_command(
94
95
 
95
96
  @deps_app.command(name="upgrade")
96
97
  async def deps_upgrade_command(
97
- package: str,
98
+ package: Annotated[
99
+ str | None,
100
+ cyclopts.Parameter(name="package", help="Package to upgrade (omit for all)"),
101
+ ] = None,
98
102
  manager: Annotated[
99
103
  str, cyclopts.Parameter(name="--manager", help="uv or pnpm")
100
104
  ] = "uv",
@@ -113,6 +117,12 @@ async def deps_upgrade_command(
113
117
  root: Annotated[
114
118
  str | None, cyclopts.Parameter(name="--root", help="Project root directory")
115
119
  ] = None,
120
+ skip_branch: Annotated[
121
+ bool,
122
+ cyclopts.Parameter(
123
+ name="--skip-branch", help="Skip branch creation, keep changes unstaged"
124
+ ),
125
+ ] = False,
116
126
  ) -> None:
117
127
  """Upgrade a dependency and create a merge request."""
118
128
  root_path = Path(root) if root else Path.cwd()
@@ -124,30 +134,73 @@ async def deps_upgrade_command(
124
134
  )
125
135
  final_project_id = project_id or os.environ.get("CI_PROJECT_ID") or ""
126
136
 
127
- if manager == "uv":
128
- run_cmd(f"uv lock --upgrade-package {package}", cwd=root_path)
129
- elif manager == "pnpm":
130
- run_cmd(f"pnpm update -r {package}", cwd=root_path)
137
+ # Check for changes in lockfiles and git status
138
+ uv_lock = root_path / "uv.lock"
139
+ pnpm_lock = root_path / "pnpm-lock.yaml"
140
+
141
+ uv_mtime = uv_lock.stat().st_mtime if uv_lock.exists() else 0
142
+ pnpm_mtime = pnpm_lock.stat().st_mtime if pnpm_lock.exists() else 0
143
+
144
+ if not package:
145
+ print(f"Checking for all outdated packages using {manager}...")
146
+ if manager == "uv":
147
+ outdated = _check_uv_outdated(root_path)
148
+ packages_to_upgrade = [pkg["name"] for pkg in outdated]
149
+ if not packages_to_upgrade:
150
+ print("All uv dependencies are up to date.")
151
+ return
152
+
153
+ print(f"Upgrading {len(packages_to_upgrade)} packages...")
154
+ pkg_args = " ".join(
155
+ [f"--upgrade-package {pkg}" for pkg in packages_to_upgrade]
156
+ )
157
+ run_cmd(f"uv lock {pkg_args}", cwd=root_path)
158
+ elif manager == "pnpm":
159
+ run_cmd("pnpm update -r", cwd=root_path)
160
+ print("Running pnpm audit fix...")
161
+ run_cmd("pnpm audit fix", cwd=root_path, check=False)
162
+ else:
163
+ print(f"Unknown manager: {manager}", file=sys.stderr)
164
+ return
165
+ package = "all"
131
166
  else:
132
- print(f"Unknown manager: {manager}", file=sys.stderr)
167
+ if manager == "uv":
168
+ run_cmd(f"uv lock --upgrade-package {package}", cwd=root_path)
169
+ elif manager == "pnpm":
170
+ run_cmd(f"pnpm update -r {package}", cwd=root_path)
171
+ else:
172
+ print(f"Unknown manager: {manager}", file=sys.stderr)
173
+ return
174
+
175
+ # Check if anything actually changed
176
+ new_uv_mtime = uv_lock.stat().st_mtime if uv_lock.exists() else 0
177
+ new_pnpm_mtime = pnpm_lock.stat().st_mtime if pnpm_lock.exists() else 0
178
+
179
+ lock_changed = (new_uv_mtime != uv_mtime) or (new_pnpm_mtime != pnpm_mtime)
180
+ git_status = run_cmd("git status --short", cwd=root_path)
181
+
182
+ if not (git_status or lock_changed):
183
+ print(f"No changes found after updating {package or 'all'}. Skipping MR.")
133
184
  return
134
185
 
135
- if dry_run:
136
- print(f"[DRY RUN] Would create MR for {package}")
186
+ if dry_run or skip_branch:
187
+ if dry_run:
188
+ print(f"[DRY RUN] Would create MR for {package or 'all'}")
137
189
  return
138
190
 
139
- safe_name = package.replace("@", "").replace("/", "-")
140
- branch_name = f"deps/{manager}-{safe_name}"
191
+ # Create and switch to new branch
192
+ timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
193
+ branch_name = f"deps/{manager}-{package or 'all'}-{timestamp}"
141
194
 
142
- run_cmd("git checkout main", cwd=root_path, check=False)
195
+ # Check for existing branch and delete it
143
196
  run_cmd(f"git branch -D {branch_name}", cwd=root_path, check=False)
144
197
  run_cmd(f"git checkout -b {branch_name}", cwd=root_path)
145
198
 
146
- status = run_cmd("git status --short", cwd=root_path)
147
- if not status:
148
- print(f"No changes found after updating {package}. Skipping MR.")
149
- run_cmd("git checkout main", cwd=root_path)
150
- return
199
+ # Force add lockfiles if they are ignored
200
+ if manager == "uv":
201
+ run_cmd("git add -f uv.lock", cwd=root_path, check=False)
202
+ elif manager == "pnpm":
203
+ run_cmd("git add -f pnpm-lock.yaml", cwd=root_path, check=False)
151
204
 
152
205
  run_cmd("git add .", cwd=root_path)
153
206
 
@@ -0,0 +1,76 @@
1
+ """Release orchestration package.
2
+ This module provides a unified namespace for automated releases,
3
+ re-exporting specialized submodules while ensuring compatibility
4
+ with the existing test suite's mocks.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from framework_m_studio.core.shell import run_cmd
10
+
11
+ from .cli import (
12
+ release_app,
13
+ release_auto_command,
14
+ release_mr_command,
15
+ release_plan_command,
16
+ release_prepare_command,
17
+ release_push_command,
18
+ release_schema_command,
19
+ release_tag_command,
20
+ )
21
+ from .gitops import (
22
+ GitLabProvider,
23
+ GitProviderProtocol,
24
+ _get_commits_since,
25
+ _get_last_tag,
26
+ push_release_branch,
27
+ )
28
+ from .models import Commit, ReleaseConfig, ReleasePackage, ReleaseSync, ReleaseUpdate
29
+ from .orchestrator import (
30
+ _determine_version_bump,
31
+ _load_release_config,
32
+ compute_release_plan,
33
+ create_or_update_mr,
34
+ prepare_release,
35
+ run_release_orchestration,
36
+ tag_and_release,
37
+ )
38
+ from .versioning import (
39
+ _bump_version,
40
+ _pin_inter_package_dependencies,
41
+ _prepend_changelog,
42
+ _update_file_version,
43
+ )
44
+
45
+ __all__ = [
46
+ "Commit",
47
+ "GitLabProvider",
48
+ "GitProviderProtocol",
49
+ "ReleaseConfig",
50
+ "ReleasePackage",
51
+ "ReleaseSync",
52
+ "ReleaseUpdate",
53
+ "_bump_version",
54
+ "_determine_version_bump",
55
+ "_get_commits_since",
56
+ "_get_last_tag",
57
+ "_load_release_config",
58
+ "_pin_inter_package_dependencies",
59
+ "_prepend_changelog",
60
+ "_update_file_version",
61
+ "compute_release_plan",
62
+ "create_or_update_mr",
63
+ "prepare_release",
64
+ "push_release_branch",
65
+ "release_app",
66
+ "release_auto_command",
67
+ "release_mr_command",
68
+ "release_plan_command",
69
+ "release_prepare_command",
70
+ "release_push_command",
71
+ "release_schema_command",
72
+ "release_tag_command",
73
+ "run_cmd",
74
+ "run_release_orchestration",
75
+ "tag_and_release",
76
+ ]
@@ -0,0 +1,201 @@
1
+ """CLI commands for release orchestration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import sys
7
+ from pathlib import Path
8
+ from typing import Annotated
9
+
10
+ import cyclopts
11
+
12
+ from .gitops import GitLabProvider
13
+ from .models import ReleaseConfig
14
+ from .orchestrator import (
15
+ _load_release_config,
16
+ compute_release_plan,
17
+ create_or_update_mr,
18
+ prepare_release,
19
+ push_release_branch,
20
+ run_release_orchestration,
21
+ tag_and_release,
22
+ )
23
+
24
+ # Main CLI app instance
25
+ release_app = cyclopts.App(name="release")
26
+
27
+
28
+ @release_app.command(name="auto")
29
+ async def release_auto_command(
30
+ provider: str = "gitlab",
31
+ token: Annotated[str | None, cyclopts.Parameter(help="Git provider token")] = None,
32
+ project_id: Annotated[str | None, cyclopts.Parameter(help="Git project ID")] = None,
33
+ dry_run: Annotated[bool, cyclopts.Parameter(help="Dry run")] = False,
34
+ ) -> None:
35
+ """Automated multi-package release workflow."""
36
+ await run_release_orchestration(
37
+ provider=provider,
38
+ token=token
39
+ or os.environ.get("CITADEL_CI_TOKEN")
40
+ or os.environ.get("GITLAB_TOKEN")
41
+ or "",
42
+ project_id=project_id or os.environ.get("CI_PROJECT_ID") or "",
43
+ dry_run=dry_run,
44
+ )
45
+
46
+
47
+ @release_app.command(name="plan")
48
+ def release_plan_command(
49
+ config: str = "release-config.json", root: str | None = None, json: bool = False
50
+ ) -> None:
51
+ """Preview which components will be released."""
52
+ root_path = Path(root) if root else Path.cwd()
53
+ release_config = _load_release_config(config, root=root_path)
54
+ updates = compute_release_plan(release_config, root_path)
55
+ if json:
56
+ import json as _json
57
+
58
+ print(_json.dumps([u.model_dump() for u in updates], indent=2))
59
+ return
60
+ if not updates:
61
+ print("✅ No releases needed.")
62
+ return
63
+ for u in updates:
64
+ print(f"🚀 {u.component}: {u.current_version} -> {u.new_version} ({u.bump})")
65
+
66
+
67
+ @release_app.command(name="prepare")
68
+ def release_prepare_command(
69
+ config: str = "release-config.json",
70
+ branch: str = "release/next",
71
+ root: str | None = None,
72
+ no_sbom: bool = False,
73
+ dry_run: bool = False,
74
+ ) -> None:
75
+ """Prepare a release branch with bumped versions."""
76
+ root_path = Path(root) if root else Path.cwd()
77
+ try:
78
+ release_config = _load_release_config(config, root=root_path)
79
+ except FileNotFoundError:
80
+ if dry_run:
81
+ release_config = ReleaseConfig(packages=[])
82
+ else:
83
+ raise
84
+
85
+ updates = compute_release_plan(release_config, root_path)
86
+ if not updates:
87
+ if dry_run:
88
+ pass
89
+ else:
90
+ print("✅ No releases needed.")
91
+ return
92
+
93
+ if dry_run:
94
+ print(f"[DRY RUN] Would prepare branch {branch} for {len(updates)} components")
95
+ return
96
+ prepare_release(updates, branch, root_path, release_config, sbom=not no_sbom)
97
+ print(f"✅ Prepared release files for {branch}")
98
+
99
+
100
+ @release_app.command(name="push")
101
+ def release_push_command(
102
+ branch: str = "release/next",
103
+ host: str | None = None,
104
+ project_path: str | None = None,
105
+ token: str | None = None,
106
+ dry_run: bool = False,
107
+ ) -> None:
108
+ """Push the release branch to the origin remote."""
109
+ final_host = host or os.environ.get("CI_SERVER_HOST", "gitlab.com")
110
+ final_path = project_path or os.environ.get("CI_PROJECT_PATH", "")
111
+ final_token = (
112
+ token or os.environ.get("CITADEL_CI_TOKEN") or os.environ.get("GITLAB_TOKEN")
113
+ )
114
+ if dry_run:
115
+ print(f"[DRY RUN] Would push branch {branch} to {final_host}/{final_path}")
116
+ return
117
+ if not final_token:
118
+ print("Error: token missing", file=sys.stderr)
119
+ raise SystemExit(1)
120
+ push_release_branch(branch, final_host, final_path, final_token)
121
+ print(f"✅ Pushed branch {branch}")
122
+
123
+
124
+ @release_app.command(name="mr")
125
+ async def release_mr_command(
126
+ branch: str = "release/next",
127
+ target_branch: str = "main",
128
+ provider: str = "gitlab",
129
+ token: str | None = None,
130
+ project_id: str | None = None,
131
+ dry_run: bool = False,
132
+ ) -> None:
133
+ """Create or update a merge request."""
134
+ final_token = (
135
+ token or os.environ.get("CITADEL_CI_TOKEN") or os.environ.get("GITLAB_TOKEN")
136
+ )
137
+ final_project_id = project_id or os.environ.get("CI_PROJECT_ID")
138
+
139
+ if provider != "gitlab":
140
+ print(f"Provider '{provider}' not yet supported.", file=sys.stderr)
141
+ raise SystemExit(1)
142
+
143
+ if dry_run:
144
+ print(f"[DRY RUN] Would create/update MR for {branch} into {target_branch}")
145
+ return
146
+ if not final_token or not final_project_id:
147
+ print("Error: token/project_id missing", file=sys.stderr)
148
+ raise SystemExit(1)
149
+ provider_cls = GitLabProvider(token=final_token, project_id=final_project_id)
150
+ title = "chore(release): automated multi-package release"
151
+ desc = "## Automated Release"
152
+ await create_or_update_mr(branch, target_branch, title, desc, provider_cls)
153
+
154
+
155
+ @release_app.command(name="tag")
156
+ async def release_tag_command(
157
+ config: str = "release-config.json",
158
+ provider: str = "gitlab",
159
+ token: str | None = None,
160
+ project_id: str | None = None,
161
+ dry_run: bool = False,
162
+ ) -> None:
163
+ """Create tags and releases for updated components."""
164
+ final_token = (
165
+ token or os.environ.get("CITADEL_CI_TOKEN") or os.environ.get("GITLAB_TOKEN")
166
+ )
167
+ final_project_id = project_id or os.environ.get("CI_PROJECT_ID")
168
+ root_path = Path.cwd()
169
+
170
+ try:
171
+ release_config = _load_release_config(config, root=root_path)
172
+ except Exception:
173
+ if provider != "gitlab":
174
+ print(f"Provider '{provider}' not yet supported.", file=sys.stderr)
175
+ raise SystemExit(1) from None
176
+ raise
177
+
178
+ git_provider: GitLabProvider | None = None
179
+ if final_token and final_project_id:
180
+ if provider == "gitlab":
181
+ git_provider = GitLabProvider(
182
+ token=final_token, project_id=final_project_id
183
+ )
184
+ else:
185
+ print(f"Provider '{provider}' not yet supported.", file=sys.stderr)
186
+ raise SystemExit(1)
187
+ await tag_and_release(release_config, root_path, git_provider, dry_run)
188
+
189
+
190
+ def release_schema_command(output: str | None = None) -> None:
191
+ """Generate JSON schema for the release configuration."""
192
+ from .models import ReleaseConfig
193
+
194
+ schema = ReleaseConfig.model_json_schema()
195
+ import json as _json
196
+
197
+ content = _json.dumps(schema, indent=2)
198
+ if output:
199
+ Path(output).write_text(content)
200
+ else:
201
+ print(content)