kanon-cli 1.2.0__tar.gz → 1.3.1__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 (680) hide show
  1. kanon_cli-1.3.1/.github/actions/setup-kanon/action.yml +116 -0
  2. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.github/workflows/main-validation.yml +135 -68
  3. kanon_cli-1.3.1/.github/workflows/pr-validation.yml +244 -0
  4. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.gitignore +10 -0
  5. kanon_cli-1.3.1/CHANGELOG.md +2443 -0
  6. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/CONTRIBUTING.md +30 -1
  7. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/Makefile +22 -7
  8. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/PKG-INFO +62 -51
  9. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/README.md +61 -50
  10. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/docs/configuration.md +35 -1
  11. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/docs/creating-manifest-repos.md +17 -1
  12. kanon_cli-1.3.1/docs/how-it-works.md +107 -0
  13. kanon_cli-1.3.1/docs/integration-testing.md +5885 -0
  14. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/docs/lifecycle.md +22 -22
  15. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/docs/pipeline-integration.md +4 -4
  16. kanon_cli-1.3.1/docs/repo/README.md +41 -0
  17. kanon_cli-1.3.1/docs/repo/internal-fs-layout.md +276 -0
  18. kanon_cli-1.3.1/docs/repo/manifest-format.md +689 -0
  19. kanon_cli-1.3.1/docs/repo/python-support.md +21 -0
  20. kanon_cli-1.3.1/docs/repo/repo-hooks.md +175 -0
  21. kanon_cli-1.3.1/docs/repo/smart-sync.md +129 -0
  22. kanon_cli-1.3.1/docs/repo/windows.md +169 -0
  23. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/docs/setup-guide.md +20 -4
  24. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/docs/version-resolution.md +42 -16
  25. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/git-hooks/pre-push +13 -1
  26. kanon_cli-1.3.1/link +1 -0
  27. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/pyproject.toml +21 -3
  28. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/requirements-dev.txt +1 -0
  29. kanon_cli-1.3.1/scripts/check_archive_no_duplicates.py +80 -0
  30. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/__init__.py +1 -1
  31. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/catalog/kanon/.kanon +0 -6
  32. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/catalog/kanon/kanon-readme.md +6 -9
  33. kanon_cli-1.3.1/src/kanon_cli/cli.py +119 -0
  34. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/commands/bootstrap.py +7 -2
  35. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/commands/clean.py +10 -0
  36. kanon_cli-1.3.1/src/kanon_cli/commands/install.py +134 -0
  37. kanon_cli-1.3.1/src/kanon_cli/commands/repo.py +119 -0
  38. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/commands/validate.py +14 -3
  39. kanon_cli-1.3.1/src/kanon_cli/constants.py +54 -0
  40. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/bootstrap.py +21 -18
  41. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/clean.py +13 -8
  42. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/install.py +82 -86
  43. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/kanonenv.py +143 -11
  44. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/marketplace.py +54 -17
  45. kanon_cli-1.3.1/src/kanon_cli/repo/__init__.py +292 -0
  46. kanon_cli-1.3.1/src/kanon_cli/repo/color.py +218 -0
  47. kanon_cli-1.3.1/src/kanon_cli/repo/command.py +529 -0
  48. kanon_cli-1.3.1/src/kanon_cli/repo/editor.py +116 -0
  49. kanon_cli-1.3.1/src/kanon_cli/repo/error.py +189 -0
  50. kanon_cli-1.3.1/src/kanon_cli/repo/event_log.py +195 -0
  51. kanon_cli-1.3.1/src/kanon_cli/repo/fetch.py +52 -0
  52. kanon_cli-1.3.1/src/kanon_cli/repo/git_command.py +613 -0
  53. kanon_cli-1.3.1/src/kanon_cli/repo/git_config.py +855 -0
  54. kanon_cli-1.3.1/src/kanon_cli/repo/git_refs.py +163 -0
  55. kanon_cli-1.3.1/src/kanon_cli/repo/git_ssh +17 -0
  56. kanon_cli-1.3.1/src/kanon_cli/repo/git_superproject.py +560 -0
  57. kanon_cli-1.3.1/src/kanon_cli/repo/git_trace2_event_log.py +32 -0
  58. kanon_cli-1.3.1/src/kanon_cli/repo/git_trace2_event_log_base.py +339 -0
  59. kanon_cli-1.3.1/src/kanon_cli/repo/hooks/commit-msg +113 -0
  60. kanon_cli-1.3.1/src/kanon_cli/repo/hooks/pre-auto-gc +46 -0
  61. kanon_cli-1.3.1/src/kanon_cli/repo/hooks.py +508 -0
  62. kanon_cli-1.3.1/src/kanon_cli/repo/main.py +906 -0
  63. kanon_cli-1.3.1/src/kanon_cli/repo/manifest_xml.py +2217 -0
  64. kanon_cli-1.3.1/src/kanon_cli/repo/pager.py +139 -0
  65. kanon_cli-1.3.1/src/kanon_cli/repo/platform_utils.py +246 -0
  66. kanon_cli-1.3.1/src/kanon_cli/repo/platform_utils_win32.py +238 -0
  67. kanon_cli-1.3.1/src/kanon_cli/repo/progress.py +238 -0
  68. kanon_cli-1.3.1/src/kanon_cli/repo/project.py +4767 -0
  69. kanon_cli-1.3.1/src/kanon_cli/repo/repo +1444 -0
  70. kanon_cli-1.3.1/src/kanon_cli/repo/repo_logging.py +91 -0
  71. kanon_cli-1.3.1/src/kanon_cli/repo/repo_trace.py +179 -0
  72. kanon_cli-1.3.1/src/kanon_cli/repo/requirements.jsonc +59 -0
  73. kanon_cli-1.3.1/src/kanon_cli/repo/ssh.py +350 -0
  74. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/__init__.py +48 -0
  75. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/abandon.py +142 -0
  76. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/branches.py +213 -0
  77. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/checkout.py +110 -0
  78. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/cherry_pick.py +145 -0
  79. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/diff.py +82 -0
  80. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/diffmanifests.py +246 -0
  81. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/download.py +205 -0
  82. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/envsubst.py +260 -0
  83. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/forall.py +415 -0
  84. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/gc.py +282 -0
  85. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/grep.py +397 -0
  86. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/help.py +184 -0
  87. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/info.py +254 -0
  88. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/init.py +392 -0
  89. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/list.py +128 -0
  90. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/manifest.py +353 -0
  91. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/overview.py +103 -0
  92. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/prune.py +89 -0
  93. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/rebase.py +201 -0
  94. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/selfupdate.py +83 -0
  95. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/smartsync.py +33 -0
  96. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/stage.py +123 -0
  97. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/start.py +151 -0
  98. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/status.py +198 -0
  99. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/sync.py +2733 -0
  100. kanon_cli-1.3.1/src/kanon_cli/repo/subcmds/upload.py +780 -0
  101. kanon_cli-1.3.1/src/kanon_cli/repo/version_constraints.py +91 -0
  102. kanon_cli-1.3.1/src/kanon_cli/repo/wrapper.py +36 -0
  103. kanon_cli-1.3.1/src/kanon_cli/version.py +290 -0
  104. kanon_cli-1.3.1/tests/conftest.py +117 -0
  105. kanon_cli-1.3.1/tests/fixtures/repo/.gitignore +2 -0
  106. kanon_cli-1.3.1/tests/fixtures/repo/README.md +20 -0
  107. kanon_cli-1.3.1/tests/fixtures/repo/linter-test-bad.invalid-yaml +10 -0
  108. kanon_cli-1.3.1/tests/fixtures/repo/linter-test-bad.md +13 -0
  109. kanon_cli-1.3.1/tests/fixtures/repo/linter-test-bad.py +11 -0
  110. kanon_cli-1.3.1/tests/fixtures/repo/sample-manifest.xml +23 -0
  111. kanon_cli-1.3.1/tests/fixtures/repo/sample-project-config.json +9 -0
  112. kanon_cli-1.3.1/tests/fixtures/repo/test.gitconfig +21 -0
  113. kanon_cli-1.3.1/tests/fixtures/repo/version_constraints_data.json +144 -0
  114. kanon_cli-1.3.1/tests/functional/conftest.py +899 -0
  115. kanon_cli-1.3.1/tests/functional/test_argparse_errors.py +636 -0
  116. kanon_cli-1.3.1/tests/functional/test_argparse_help.py +470 -0
  117. kanon_cli-1.3.1/tests/functional/test_bootstrap_catalog_source.py +234 -0
  118. kanon_cli-1.3.1/tests/functional/test_bootstrap_errors.py +169 -0
  119. kanon_cli-1.3.1/tests/functional/test_bootstrap_list_and_default_target.py +104 -0
  120. kanon_cli-1.3.1/tests/functional/test_bootstrap_output_dir.py +204 -0
  121. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/functional/test_cli_entry_point.py +16 -12
  122. kanon_cli-1.3.1/tests/functional/test_exit_code_matrix.py +1058 -0
  123. kanon_cli-1.3.1/tests/functional/test_groups_filter.py +962 -0
  124. kanon_cli-1.3.1/tests/functional/test_help_text_contract.py +608 -0
  125. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/functional/test_install_lifecycle.py +46 -35
  126. kanon_cli-1.3.1/tests/functional/test_install_real_kanon.py +161 -0
  127. kanon_cli-1.3.1/tests/functional/test_kanon_repo_cli.py +604 -0
  128. kanon_cli-1.3.1/tests/functional/test_kanon_repo_e2e.py +488 -0
  129. kanon_cli-1.3.1/tests/functional/test_kanon_repo_lifecycle_journey.py +1023 -0
  130. kanon_cli-1.3.1/tests/functional/test_repo_abandon_errors.py +858 -0
  131. kanon_cli-1.3.1/tests/functional/test_repo_abandon_flags.py +962 -0
  132. kanon_cli-1.3.1/tests/functional/test_repo_abandon_happy.py +486 -0
  133. kanon_cli-1.3.1/tests/functional/test_repo_branches_errors.py +770 -0
  134. kanon_cli-1.3.1/tests/functional/test_repo_branches_flags.py +835 -0
  135. kanon_cli-1.3.1/tests/functional/test_repo_branches_happy.py +370 -0
  136. kanon_cli-1.3.1/tests/functional/test_repo_checkout_errors.py +686 -0
  137. kanon_cli-1.3.1/tests/functional/test_repo_checkout_flags.py +838 -0
  138. kanon_cli-1.3.1/tests/functional/test_repo_checkout_happy.py +407 -0
  139. kanon_cli-1.3.1/tests/functional/test_repo_cherry_pick_errors.py +725 -0
  140. kanon_cli-1.3.1/tests/functional/test_repo_cherry_pick_flags.py +625 -0
  141. kanon_cli-1.3.1/tests/functional/test_repo_cherry_pick_happy.py +430 -0
  142. kanon_cli-1.3.1/tests/functional/test_repo_diff_errors.py +732 -0
  143. kanon_cli-1.3.1/tests/functional/test_repo_diff_flags.py +655 -0
  144. kanon_cli-1.3.1/tests/functional/test_repo_diff_happy.py +445 -0
  145. kanon_cli-1.3.1/tests/functional/test_repo_diffmanifests_errors.py +698 -0
  146. kanon_cli-1.3.1/tests/functional/test_repo_diffmanifests_flags.py +808 -0
  147. kanon_cli-1.3.1/tests/functional/test_repo_diffmanifests_happy.py +516 -0
  148. kanon_cli-1.3.1/tests/functional/test_repo_dir_override.py +359 -0
  149. kanon_cli-1.3.1/tests/functional/test_repo_download_errors.py +699 -0
  150. kanon_cli-1.3.1/tests/functional/test_repo_download_flags.py +1083 -0
  151. kanon_cli-1.3.1/tests/functional/test_repo_download_happy.py +486 -0
  152. kanon_cli-1.3.1/tests/functional/test_repo_envsubst_errors.py +816 -0
  153. kanon_cli-1.3.1/tests/functional/test_repo_envsubst_flags.py +879 -0
  154. kanon_cli-1.3.1/tests/functional/test_repo_envsubst_happy.py +403 -0
  155. kanon_cli-1.3.1/tests/functional/test_repo_exit_codes.py +656 -0
  156. kanon_cli-1.3.1/tests/functional/test_repo_forall_errors.py +917 -0
  157. kanon_cli-1.3.1/tests/functional/test_repo_forall_flags.py +1017 -0
  158. kanon_cli-1.3.1/tests/functional/test_repo_forall_happy.py +391 -0
  159. kanon_cli-1.3.1/tests/functional/test_repo_gc_errors.py +857 -0
  160. kanon_cli-1.3.1/tests/functional/test_repo_gc_flags.py +707 -0
  161. kanon_cli-1.3.1/tests/functional/test_repo_gc_happy.py +433 -0
  162. kanon_cli-1.3.1/tests/functional/test_repo_grep_errors.py +830 -0
  163. kanon_cli-1.3.1/tests/functional/test_repo_grep_flags.py +1097 -0
  164. kanon_cli-1.3.1/tests/functional/test_repo_grep_happy.py +483 -0
  165. kanon_cli-1.3.1/tests/functional/test_repo_help_errors.py +598 -0
  166. kanon_cli-1.3.1/tests/functional/test_repo_help_flags.py +520 -0
  167. kanon_cli-1.3.1/tests/functional/test_repo_help_happy.py +250 -0
  168. kanon_cli-1.3.1/tests/functional/test_repo_info_errors.py +856 -0
  169. kanon_cli-1.3.1/tests/functional/test_repo_info_flags.py +924 -0
  170. kanon_cli-1.3.1/tests/functional/test_repo_info_happy.py +396 -0
  171. kanon_cli-1.3.1/tests/functional/test_repo_init_errors.py +865 -0
  172. kanon_cli-1.3.1/tests/functional/test_repo_init_flags.py +1241 -0
  173. kanon_cli-1.3.1/tests/functional/test_repo_init_happy.py +444 -0
  174. kanon_cli-1.3.1/tests/functional/test_repo_init_mirror.py +225 -0
  175. kanon_cli-1.3.1/tests/functional/test_repo_list_errors.py +858 -0
  176. kanon_cli-1.3.1/tests/functional/test_repo_list_flags.py +1085 -0
  177. kanon_cli-1.3.1/tests/functional/test_repo_list_happy.py +447 -0
  178. kanon_cli-1.3.1/tests/functional/test_repo_manifest_errors.py +860 -0
  179. kanon_cli-1.3.1/tests/functional/test_repo_manifest_flags.py +1015 -0
  180. kanon_cli-1.3.1/tests/functional/test_repo_manifest_happy.py +459 -0
  181. kanon_cli-1.3.1/tests/functional/test_repo_manifest_revision_as_tag.py +283 -0
  182. kanon_cli-1.3.1/tests/functional/test_repo_overview_errors.py +858 -0
  183. kanon_cli-1.3.1/tests/functional/test_repo_overview_flags.py +785 -0
  184. kanon_cli-1.3.1/tests/functional/test_repo_overview_happy.py +458 -0
  185. kanon_cli-1.3.1/tests/functional/test_repo_passthrough.py +705 -0
  186. kanon_cli-1.3.1/tests/functional/test_repo_prune_errors.py +559 -0
  187. kanon_cli-1.3.1/tests/functional/test_repo_prune_flags.py +639 -0
  188. kanon_cli-1.3.1/tests/functional/test_repo_prune_happy.py +430 -0
  189. kanon_cli-1.3.1/tests/functional/test_repo_rebase_errors.py +638 -0
  190. kanon_cli-1.3.1/tests/functional/test_repo_rebase_flags.py +1076 -0
  191. kanon_cli-1.3.1/tests/functional/test_repo_rebase_happy.py +323 -0
  192. kanon_cli-1.3.1/tests/functional/test_repo_selfupdate_disabled.py +155 -0
  193. kanon_cli-1.3.1/tests/functional/test_repo_selfupdate_errors.py +746 -0
  194. kanon_cli-1.3.1/tests/functional/test_repo_selfupdate_flags.py +532 -0
  195. kanon_cli-1.3.1/tests/functional/test_repo_selfupdate_happy.py +257 -0
  196. kanon_cli-1.3.1/tests/functional/test_repo_smartsync_errors.py +751 -0
  197. kanon_cli-1.3.1/tests/functional/test_repo_smartsync_flags.py +1010 -0
  198. kanon_cli-1.3.1/tests/functional/test_repo_smartsync_happy.py +416 -0
  199. kanon_cli-1.3.1/tests/functional/test_repo_stage_errors.py +900 -0
  200. kanon_cli-1.3.1/tests/functional/test_repo_stage_flags.py +666 -0
  201. kanon_cli-1.3.1/tests/functional/test_repo_stage_happy.py +366 -0
  202. kanon_cli-1.3.1/tests/functional/test_repo_start_errors.py +645 -0
  203. kanon_cli-1.3.1/tests/functional/test_repo_start_flags.py +1033 -0
  204. kanon_cli-1.3.1/tests/functional/test_repo_start_happy.py +469 -0
  205. kanon_cli-1.3.1/tests/functional/test_repo_status_errors.py +739 -0
  206. kanon_cli-1.3.1/tests/functional/test_repo_status_flags.py +685 -0
  207. kanon_cli-1.3.1/tests/functional/test_repo_status_happy.py +390 -0
  208. kanon_cli-1.3.1/tests/functional/test_repo_sync_errors.py +911 -0
  209. kanon_cli-1.3.1/tests/functional/test_repo_sync_flags.py +1035 -0
  210. kanon_cli-1.3.1/tests/functional/test_repo_sync_happy.py +367 -0
  211. kanon_cli-1.3.1/tests/functional/test_repo_upload_errors.py +906 -0
  212. kanon_cli-1.3.1/tests/functional/test_repo_upload_flags.py +794 -0
  213. kanon_cli-1.3.1/tests/functional/test_repo_upload_happy.py +413 -0
  214. kanon_cli-1.3.1/tests/functional/test_stdout_stderr_discipline.py +586 -0
  215. kanon_cli-1.3.1/tests/functional/test_validate_marketplace.py +594 -0
  216. kanon_cli-1.3.1/tests/functional/test_validate_xml_errors.py +237 -0
  217. kanon_cli-1.3.1/tests/functional/test_validate_xml_repo_root.py +187 -0
  218. kanon_cli-1.3.1/tests/integration/repo/__init__.py +0 -0
  219. kanon_cli-1.3.1/tests/integration/repo/test_bug_fixes.py +1078 -0
  220. kanon_cli-1.3.1/tests/integration/repo/test_consolidated_constraints_e2e.py +328 -0
  221. kanon_cli-1.3.1/tests/integration/repo/test_envsubst_integration.py +780 -0
  222. kanon_cli-1.3.1/tests/integration/repo/test_import_functional.py +102 -0
  223. kanon_cli-1.3.1/tests/integration/repo/test_linkfile_copyfile.py +478 -0
  224. kanon_cli-1.3.1/tests/integration/repo/test_linkfile_exclude_journey.py +685 -0
  225. kanon_cli-1.3.1/tests/integration/repo/test_manifest_parsing.py +550 -0
  226. kanon_cli-1.3.1/tests/integration/repo/test_process_isolation.py +650 -0
  227. kanon_cli-1.3.1/tests/integration/repo/test_repo_module_smoke.py +93 -0
  228. kanon_cli-1.3.1/tests/integration/repo/test_repo_pipeline.py +636 -0
  229. kanon_cli-1.3.1/tests/integration/repo/test_repo_run_lifecycle.py +171 -0
  230. kanon_cli-1.3.1/tests/integration/repo/test_repo_sync_lifecycle.py +335 -0
  231. kanon_cli-1.3.1/tests/integration/repo/test_version_constraints_integration.py +552 -0
  232. kanon_cli-1.3.1/tests/integration/repo/test_xml_annotation_roundtrip.py +447 -0
  233. kanon_cli-1.3.1/tests/integration/repo/test_xml_contactinfo_roundtrip.py +337 -0
  234. kanon_cli-1.3.1/tests/integration/repo/test_xml_copyfile_roundtrip.py +408 -0
  235. kanon_cli-1.3.1/tests/integration/repo/test_xml_default_roundtrip.py +474 -0
  236. kanon_cli-1.3.1/tests/integration/repo/test_xml_extend_project_roundtrip.py +362 -0
  237. kanon_cli-1.3.1/tests/integration/repo/test_xml_include_roundtrip.py +385 -0
  238. kanon_cli-1.3.1/tests/integration/repo/test_xml_linkfile_roundtrip.py +495 -0
  239. kanon_cli-1.3.1/tests/integration/repo/test_xml_manifest_roundtrip.py +404 -0
  240. kanon_cli-1.3.1/tests/integration/repo/test_xml_manifest_server_roundtrip.py +336 -0
  241. kanon_cli-1.3.1/tests/integration/repo/test_xml_notice_roundtrip.py +340 -0
  242. kanon_cli-1.3.1/tests/integration/repo/test_xml_project_roundtrip.py +419 -0
  243. kanon_cli-1.3.1/tests/integration/repo/test_xml_remote_roundtrip.py +451 -0
  244. kanon_cli-1.3.1/tests/integration/repo/test_xml_remove_project_roundtrip.py +363 -0
  245. kanon_cli-1.3.1/tests/integration/repo/test_xml_repo_hooks_roundtrip.py +370 -0
  246. kanon_cli-1.3.1/tests/integration/repo/test_xml_submanifest_roundtrip.py +394 -0
  247. kanon_cli-1.3.1/tests/integration/repo/test_xml_superproject_roundtrip.py +368 -0
  248. kanon_cli-1.3.1/tests/integration/test_auto_discovery.py +115 -0
  249. kanon_cli-1.3.1/tests/integration/test_bootstrap.py +164 -0
  250. kanon_cli-1.3.1/tests/integration/test_catalog_constraints.py +121 -0
  251. kanon_cli-1.3.1/tests/integration/test_ci_validation.py +235 -0
  252. kanon_cli-1.3.1/tests/integration/test_clean_lifecycle.py +246 -0
  253. kanon_cli-1.3.1/tests/integration/test_clean_paths.py +207 -0
  254. kanon_cli-1.3.1/tests/integration/test_cli_entry_points.py +98 -0
  255. kanon_cli-1.3.1/tests/integration/test_concurrency.py +788 -0
  256. kanon_cli-1.3.1/tests/integration/test_copyfile_fs_effects.py +525 -0
  257. kanon_cli-1.3.1/tests/integration/test_doc_validation.py +253 -0
  258. kanon_cli-1.3.1/tests/integration/test_envsubst_command.py +237 -0
  259. kanon_cli-1.3.1/tests/integration/test_fs_fault_extended.py +637 -0
  260. kanon_cli-1.3.1/tests/integration/test_fs_fault_injection.py +486 -0
  261. kanon_cli-1.3.1/tests/integration/test_full_user_journey.py +1033 -0
  262. kanon_cli-1.3.1/tests/integration/test_git_fault_injection.py +428 -0
  263. kanon_cli-1.3.1/tests/integration/test_git_retry_env.py +573 -0
  264. kanon_cli-1.3.1/tests/integration/test_gitignore_idempotency.py +150 -0
  265. kanon_cli-1.3.1/tests/integration/test_install_command.py +177 -0
  266. kanon_cli-1.3.1/tests/integration/test_install_errors.py +561 -0
  267. kanon_cli-1.3.1/tests/integration/test_install_lifecycle.py +914 -0
  268. kanon_cli-1.3.1/tests/integration/test_install_optional_vars.py +503 -0
  269. kanon_cli-1.3.1/tests/integration/test_install_paths.py +209 -0
  270. kanon_cli-1.3.1/tests/integration/test_install_required_vars.py +143 -0
  271. kanon_cli-1.3.1/tests/integration/test_kanon_clean_embedded.py +211 -0
  272. kanon_cli-1.3.1/tests/integration/test_kanon_full_lifecycle.py +465 -0
  273. kanon_cli-1.3.1/tests/integration/test_kanon_install_embedded.py +363 -0
  274. kanon_cli-1.3.1/tests/integration/test_kanonenv_parsing.py +240 -0
  275. kanon_cli-1.3.1/tests/integration/test_lifecycle_recovery.py +363 -0
  276. kanon_cli-1.3.1/tests/integration/test_linkfile_fs_effects.py +605 -0
  277. kanon_cli-1.3.1/tests/integration/test_marketplace_install.py +440 -0
  278. kanon_cli-1.3.1/tests/integration/test_marketplace_lifecycle.py +311 -0
  279. kanon_cli-1.3.1/tests/integration/test_misc_features.py +286 -0
  280. kanon_cli-1.3.1/tests/integration/test_multi_source_aggregation.py +414 -0
  281. kanon_cli-1.3.1/tests/integration/test_no_hardcoded_org_values.py +143 -0
  282. kanon_cli-1.3.1/tests/integration/test_observability.py +515 -0
  283. kanon_cli-1.3.1/tests/integration/test_platform_parity.py +740 -0
  284. kanon_cli-1.3.1/tests/integration/test_signal_handling.py +472 -0
  285. kanon_cli-1.3.1/tests/integration/test_unicode_encoding.py +541 -0
  286. kanon_cli-1.3.1/tests/integration/test_validate_marketplace.py +226 -0
  287. kanon_cli-1.3.1/tests/integration/test_validate_xml.py +156 -0
  288. kanon_cli-1.3.1/tests/integration/test_version_resolution.py +207 -0
  289. kanon_cli-1.3.1/tests/integration/test_wheel_e2e.py +483 -0
  290. kanon_cli-1.3.1/tests/regression/test_e0_f1_s2_t5_regression.py +622 -0
  291. kanon_cli-1.3.1/tests/regression/test_e0_f5_s2_t7_regression.py +508 -0
  292. kanon_cli-1.3.1/tests/regression/test_e0_f6_s1_t1_regression.py +251 -0
  293. kanon_cli-1.3.1/tests/regression/test_e0_f6_s1_t2_regression.py +454 -0
  294. kanon_cli-1.3.1/tests/regression/test_e0_f6_s1_t3_regression.py +484 -0
  295. kanon_cli-1.3.1/tests/regression/test_e0_f6_s1_t4_regression.py +505 -0
  296. kanon_cli-1.3.1/tests/regression/test_e0_f6_s2_t1_regression.py +297 -0
  297. kanon_cli-1.3.1/tests/regression/test_e0_f6_s2_t2_regression.py +471 -0
  298. kanon_cli-1.3.1/tests/regression/test_e0_f6_s2_t3_regression.py +443 -0
  299. kanon_cli-1.3.1/tests/regression/test_e0_f6_s2_t4_regression.py +459 -0
  300. kanon_cli-1.3.1/tests/regression/test_e0_f6_s2_t5_regression.py +465 -0
  301. kanon_cli-1.3.1/tests/regression/test_e0_f6_s2_t6_regression.py +359 -0
  302. kanon_cli-1.3.1/tests/regression/test_e0_f6_s3_t1_regression.py +640 -0
  303. kanon_cli-1.3.1/tests/regression/test_e0_f6_s3_t2_regression.py +518 -0
  304. kanon_cli-1.3.1/tests/regression/test_e0_install_relative_regression.py +498 -0
  305. kanon_cli-1.3.1/tests/scenarios/__init__.py +0 -0
  306. kanon_cli-1.3.1/tests/scenarios/_rp_helpers.py +92 -0
  307. kanon_cli-1.3.1/tests/scenarios/conftest.py +421 -0
  308. kanon_cli-1.3.1/tests/scenarios/test_ad.py +267 -0
  309. kanon_cli-1.3.1/tests/scenarios/test_bs.py +89 -0
  310. kanon_cli-1.3.1/tests/scenarios/test_cd.py +183 -0
  311. kanon_cli-1.3.1/tests/scenarios/test_cs.py +217 -0
  312. kanon_cli-1.3.1/tests/scenarios/test_ec.py +102 -0
  313. kanon_cli-1.3.1/tests/scenarios/test_ep.py +39 -0
  314. kanon_cli-1.3.1/tests/scenarios/test_ev.py +190 -0
  315. kanon_cli-1.3.1/tests/scenarios/test_hv.py +72 -0
  316. kanon_cli-1.3.1/tests/scenarios/test_ic.py +263 -0
  317. kanon_cli-1.3.1/tests/scenarios/test_id.py +178 -0
  318. kanon_cli-1.3.1/tests/scenarios/test_ks.py +450 -0
  319. kanon_cli-1.3.1/tests/scenarios/test_lf.py +141 -0
  320. kanon_cli-1.3.1/tests/scenarios/test_mk.py +948 -0
  321. kanon_cli-1.3.1/tests/scenarios/test_ms.py +141 -0
  322. kanon_cli-1.3.1/tests/scenarios/test_pk.py +596 -0
  323. kanon_cli-1.3.1/tests/scenarios/test_rp_abandon.py +69 -0
  324. kanon_cli-1.3.1/tests/scenarios/test_rp_branches.py +119 -0
  325. kanon_cli-1.3.1/tests/scenarios/test_rp_checkout.py +53 -0
  326. kanon_cli-1.3.1/tests/scenarios/test_rp_cherry_pick.py +109 -0
  327. kanon_cli-1.3.1/tests/scenarios/test_rp_diff.py +112 -0
  328. kanon_cli-1.3.1/tests/scenarios/test_rp_diffmanifests.py +161 -0
  329. kanon_cli-1.3.1/tests/scenarios/test_rp_download.py +72 -0
  330. kanon_cli-1.3.1/tests/scenarios/test_rp_envsubst.py +47 -0
  331. kanon_cli-1.3.1/tests/scenarios/test_rp_forall.py +137 -0
  332. kanon_cli-1.3.1/tests/scenarios/test_rp_gc.py +63 -0
  333. kanon_cli-1.3.1/tests/scenarios/test_rp_grep.py +64 -0
  334. kanon_cli-1.3.1/tests/scenarios/test_rp_help.py +45 -0
  335. kanon_cli-1.3.1/tests/scenarios/test_rp_info.py +145 -0
  336. kanon_cli-1.3.1/tests/scenarios/test_rp_init.py +435 -0
  337. kanon_cli-1.3.1/tests/scenarios/test_rp_list.py +173 -0
  338. kanon_cli-1.3.1/tests/scenarios/test_rp_manifest.py +215 -0
  339. kanon_cli-1.3.1/tests/scenarios/test_rp_overview.py +106 -0
  340. kanon_cli-1.3.1/tests/scenarios/test_rp_prune.py +44 -0
  341. kanon_cli-1.3.1/tests/scenarios/test_rp_rebase.py +162 -0
  342. kanon_cli-1.3.1/tests/scenarios/test_rp_smartsync.py +22 -0
  343. kanon_cli-1.3.1/tests/scenarios/test_rp_stage.py +21 -0
  344. kanon_cli-1.3.1/tests/scenarios/test_rp_start.py +66 -0
  345. kanon_cli-1.3.1/tests/scenarios/test_rp_status.py +134 -0
  346. kanon_cli-1.3.1/tests/scenarios/test_rp_sync.py +401 -0
  347. kanon_cli-1.3.1/tests/scenarios/test_rp_upload.py +78 -0
  348. kanon_cli-1.3.1/tests/scenarios/test_rp_wrap.py +111 -0
  349. kanon_cli-1.3.1/tests/scenarios/test_rx.py +273 -0
  350. kanon_cli-1.3.1/tests/scenarios/test_scenario_coverage_meta.py +89 -0
  351. kanon_cli-1.3.1/tests/scenarios/test_tc_bootstrap.py +157 -0
  352. kanon_cli-1.3.1/tests/scenarios/test_tc_clean.py +160 -0
  353. kanon_cli-1.3.1/tests/scenarios/test_tc_install.py +234 -0
  354. kanon_cli-1.3.1/tests/scenarios/test_tc_validate.py +174 -0
  355. kanon_cli-1.3.1/tests/scenarios/test_uj.py +692 -0
  356. kanon_cli-1.3.1/tests/scenarios/test_va.py +161 -0
  357. kanon_cli-1.3.1/tests/security/__init__.py +0 -0
  358. kanon_cli-1.3.1/tests/security/test_security_hardening.py +301 -0
  359. kanon_cli-1.3.1/tests/unit/__init__.py +0 -0
  360. kanon_cli-1.3.1/tests/unit/commands/test_repo_dir_resolution.py +166 -0
  361. kanon_cli-1.3.1/tests/unit/repo/__init__.py +0 -0
  362. kanon_cli-1.3.1/tests/unit/repo/conftest.py +231 -0
  363. kanon_cli-1.3.1/tests/unit/repo/fixtures/.gitignore +2 -0
  364. kanon_cli-1.3.1/tests/unit/repo/fixtures/README.md +22 -0
  365. kanon_cli-1.3.1/tests/unit/repo/fixtures/sample-manifest.xml +23 -0
  366. kanon_cli-1.3.1/tests/unit/repo/fixtures/sample-project-config.json +9 -0
  367. kanon_cli-1.3.1/tests/unit/repo/fixtures/test.gitconfig +21 -0
  368. kanon_cli-1.3.1/tests/unit/repo/fixtures/version_constraints_data.json +144 -0
  369. kanon_cli-1.3.1/tests/unit/repo/functional/__init__.py +0 -0
  370. kanon_cli-1.3.1/tests/unit/repo/functional/test_features.py +265 -0
  371. kanon_cli-1.3.1/tests/unit/repo/subcmds/__init__.py +0 -0
  372. kanon_cli-1.3.1/tests/unit/repo/subcmds/test_init_mirror.py +195 -0
  373. kanon_cli-1.3.1/tests/unit/repo/subcmds/test_manifest_revision_as_tag.py +294 -0
  374. kanon_cli-1.3.1/tests/unit/repo/subcmds/test_manifest_revision_as_tag_pep440.py +154 -0
  375. kanon_cli-1.3.1/tests/unit/repo/subcmds/test_selfupdate_stub.py +230 -0
  376. kanon_cli-1.3.1/tests/unit/repo/test_abandon_massive.py +352 -0
  377. kanon_cli-1.3.1/tests/unit/repo/test_branches_coverage.py +408 -0
  378. kanon_cli-1.3.1/tests/unit/repo/test_bug10_selfupdate_incompatible.py +283 -0
  379. kanon_cli-1.3.1/tests/unit/repo/test_bug11_race_condition.py +176 -0
  380. kanon_cli-1.3.1/tests/unit/repo/test_bug12_backup_preserved.py +91 -0
  381. kanon_cli-1.3.1/tests/unit/repo/test_bug13_init_reinit_warning.py +201 -0
  382. kanon_cli-1.3.1/tests/unit/repo/test_bug14_non_tty_log.py +176 -0
  383. kanon_cli-1.3.1/tests/unit/repo/test_bug15_prerelease_docs.py +89 -0
  384. kanon_cli-1.3.1/tests/unit/repo/test_bug16_nested_var_warning.py +219 -0
  385. kanon_cli-1.3.1/tests/unit/repo/test_bug18_envsubst_double_parse.py +151 -0
  386. kanon_cli-1.3.1/tests/unit/repo/test_bug19_glob_src_error.py +125 -0
  387. kanon_cli-1.3.1/tests/unit/repo/test_bug1_envsubst_malformed_xml.py +219 -0
  388. kanon_cli-1.3.1/tests/unit/repo/test_bug20_glob_dest_file.py +185 -0
  389. kanon_cli-1.3.1/tests/unit/repo/test_bug2_linkfile_errors.py +255 -0
  390. kanon_cli-1.3.1/tests/unit/repo/test_bug3_execv_replaces_process.py +341 -0
  391. kanon_cli-1.3.1/tests/unit/repo/test_bug4_symlink_overwrite.py +303 -0
  392. kanon_cli-1.3.1/tests/unit/repo/test_bug5_empty_envsubst_list.py +101 -0
  393. kanon_cli-1.3.1/tests/unit/repo/test_bug6_undefined_env_vars.py +382 -0
  394. kanon_cli-1.3.1/tests/unit/repo/test_bug7_git_ls_remote_retry.py +420 -0
  395. kanon_cli-1.3.1/tests/unit/repo/test_bug8_ls_remote_stderr.py +188 -0
  396. kanon_cli-1.3.1/tests/unit/repo/test_bug9_constraint_resolution_cache.py +225 -0
  397. kanon_cli-1.3.1/tests/unit/repo/test_checklocalpath_rules_1_5.py +220 -0
  398. kanon_cli-1.3.1/tests/unit/repo/test_checklocalpath_rules_6_11.py +341 -0
  399. kanon_cli-1.3.1/tests/unit/repo/test_checkout_massive.py +345 -0
  400. kanon_cli-1.3.1/tests/unit/repo/test_cherrypick_coverage.py +309 -0
  401. kanon_cli-1.3.1/tests/unit/repo/test_color.py +460 -0
  402. kanon_cli-1.3.1/tests/unit/repo/test_command.py +1115 -0
  403. kanon_cli-1.3.1/tests/unit/repo/test_conftest_fixtures.py +156 -0
  404. kanon_cli-1.3.1/tests/unit/repo/test_diffmanifests_deep.py +509 -0
  405. kanon_cli-1.3.1/tests/unit/repo/test_doc_validate_git_preconditions.py +336 -0
  406. kanon_cli-1.3.1/tests/unit/repo/test_download_coverage.py +62 -0
  407. kanon_cli-1.3.1/tests/unit/repo/test_editor.py +297 -0
  408. kanon_cli-1.3.1/tests/unit/repo/test_embedded_mode.py +292 -0
  409. kanon_cli-1.3.1/tests/unit/repo/test_envsubst_basic.py +324 -0
  410. kanon_cli-1.3.1/tests/unit/repo/test_envsubst_edge.py +678 -0
  411. kanon_cli-1.3.1/tests/unit/repo/test_envsubst_massive.py +228 -0
  412. kanon_cli-1.3.1/tests/unit/repo/test_error.py +355 -0
  413. kanon_cli-1.3.1/tests/unit/repo/test_event_log.py +280 -0
  414. kanon_cli-1.3.1/tests/unit/repo/test_event_log_massive.py +263 -0
  415. kanon_cli-1.3.1/tests/unit/repo/test_fetch.py +120 -0
  416. kanon_cli-1.3.1/tests/unit/repo/test_fixture_files.py +72 -0
  417. kanon_cli-1.3.1/tests/unit/repo/test_forall_deep.py +628 -0
  418. kanon_cli-1.3.1/tests/unit/repo/test_git_command.py +603 -0
  419. kanon_cli-1.3.1/tests/unit/repo/test_git_config.py +588 -0
  420. kanon_cli-1.3.1/tests/unit/repo/test_git_refs.py +542 -0
  421. kanon_cli-1.3.1/tests/unit/repo/test_git_superproject.py +661 -0
  422. kanon_cli-1.3.1/tests/unit/repo/test_git_trace2_event_log.py +762 -0
  423. kanon_cli-1.3.1/tests/unit/repo/test_gitconfig_coverage.py +419 -0
  424. kanon_cli-1.3.1/tests/unit/repo/test_grep_deep.py +421 -0
  425. kanon_cli-1.3.1/tests/unit/repo/test_harness_smoke.py +105 -0
  426. kanon_cli-1.3.1/tests/unit/repo/test_hooks.py +500 -0
  427. kanon_cli-1.3.1/tests/unit/repo/test_import_verification.py +140 -0
  428. kanon_cli-1.3.1/tests/unit/repo/test_imports.py +99 -0
  429. kanon_cli-1.3.1/tests/unit/repo/test_include_path_resolution.py +653 -0
  430. kanon_cli-1.3.1/tests/unit/repo/test_info_deep.py +476 -0
  431. kanon_cli-1.3.1/tests/unit/repo/test_init_deep.py +342 -0
  432. kanon_cli-1.3.1/tests/unit/repo/test_list_massive.py +379 -0
  433. kanon_cli-1.3.1/tests/unit/repo/test_main.py +792 -0
  434. kanon_cli-1.3.1/tests/unit/repo/test_main_coverage.py +354 -0
  435. kanon_cli-1.3.1/tests/unit/repo/test_main_init_download_boost.py +1902 -0
  436. kanon_cli-1.3.1/tests/unit/repo/test_makefile_lint_format.py +90 -0
  437. kanon_cli-1.3.1/tests/unit/repo/test_makefile_structure.py +196 -0
  438. kanon_cli-1.3.1/tests/unit/repo/test_makefile_test_targets.py +148 -0
  439. kanon_cli-1.3.1/tests/unit/repo/test_manifest_coverage_boost.py +2391 -0
  440. kanon_cli-1.3.1/tests/unit/repo/test_manifest_deep.py +1611 -0
  441. kanon_cli-1.3.1/tests/unit/repo/test_manifest_doc_rp_flags.py +193 -0
  442. kanon_cli-1.3.1/tests/unit/repo/test_manifest_massive.py +869 -0
  443. kanon_cli-1.3.1/tests/unit/repo/test_manifest_subcmd_massive.py +385 -0
  444. kanon_cli-1.3.1/tests/unit/repo/test_manifest_xml.py +2743 -0
  445. kanon_cli-1.3.1/tests/unit/repo/test_manifest_xml_pep440.py +222 -0
  446. kanon_cli-1.3.1/tests/unit/repo/test_medium_files_boost.py +1590 -0
  447. kanon_cli-1.3.1/tests/unit/repo/test_mkdtemp_cleanup.py +137 -0
  448. kanon_cli-1.3.1/tests/unit/repo/test_overview_massive.py +340 -0
  449. kanon_cli-1.3.1/tests/unit/repo/test_package_structure.py +45 -0
  450. kanon_cli-1.3.1/tests/unit/repo/test_pager.py +396 -0
  451. kanon_cli-1.3.1/tests/unit/repo/test_parselist.py +238 -0
  452. kanon_cli-1.3.1/tests/unit/repo/test_pep440_edge_1.py +396 -0
  453. kanon_cli-1.3.1/tests/unit/repo/test_pep440_edge_2.py +386 -0
  454. kanon_cli-1.3.1/tests/unit/repo/test_pep440_ops_ge.py +215 -0
  455. kanon_cli-1.3.1/tests/unit/repo/test_pep440_ops_rest.py +483 -0
  456. kanon_cli-1.3.1/tests/unit/repo/test_platform_utils.py +431 -0
  457. kanon_cli-1.3.1/tests/unit/repo/test_process_isolation.py +209 -0
  458. kanon_cli-1.3.1/tests/unit/repo/test_progress.py +548 -0
  459. kanon_cli-1.3.1/tests/unit/repo/test_project.py +2459 -0
  460. kanon_cli-1.3.1/tests/unit/repo/test_project_coverage_boost.py +1747 -0
  461. kanon_cli-1.3.1/tests/unit/repo/test_project_coverage_threshold.py +3087 -0
  462. kanon_cli-1.3.1/tests/unit/repo/test_project_deep.py +1119 -0
  463. kanon_cli-1.3.1/tests/unit/repo/test_project_deep_boost.py +1074 -0
  464. kanon_cli-1.3.1/tests/unit/repo/test_project_final_boost.py +476 -0
  465. kanon_cli-1.3.1/tests/unit/repo/test_project_integration.py +932 -0
  466. kanon_cli-1.3.1/tests/unit/repo/test_project_massive.py +1190 -0
  467. kanon_cli-1.3.1/tests/unit/repo/test_project_metaproject_boost.py +1360 -0
  468. kanon_cli-1.3.1/tests/unit/repo/test_project_methods.py +667 -0
  469. kanon_cli-1.3.1/tests/unit/repo/test_project_sync.py +206 -0
  470. kanon_cli-1.3.1/tests/unit/repo/test_prune_massive.py +352 -0
  471. kanon_cli-1.3.1/tests/unit/repo/test_rebase_coverage.py +459 -0
  472. kanon_cli-1.3.1/tests/unit/repo/test_remaining_coverage_boost.py +1426 -0
  473. kanon_cli-1.3.1/tests/unit/repo/test_repo_envsubst_api.py +418 -0
  474. kanon_cli-1.3.1/tests/unit/repo/test_repo_logging.py +288 -0
  475. kanon_cli-1.3.1/tests/unit/repo/test_repo_run_api.py +332 -0
  476. kanon_cli-1.3.1/tests/unit/repo/test_repo_sync_api.py +510 -0
  477. kanon_cli-1.3.1/tests/unit/repo/test_repo_trace.py +360 -0
  478. kanon_cli-1.3.1/tests/unit/repo/test_revision_inheritance.py +386 -0
  479. kanon_cli-1.3.1/tests/unit/repo/test_revision_tag_branch_sha.py +285 -0
  480. kanon_cli-1.3.1/tests/unit/repo/test_ruff_config.py +57 -0
  481. kanon_cli-1.3.1/tests/unit/repo/test_selfupdate_embedded.py +243 -0
  482. kanon_cli-1.3.1/tests/unit/repo/test_selfupdate_massive.py +239 -0
  483. kanon_cli-1.3.1/tests/unit/repo/test_small_files_boost.py +1733 -0
  484. kanon_cli-1.3.1/tests/unit/repo/test_ssh.py +401 -0
  485. kanon_cli-1.3.1/tests/unit/repo/test_ssh_deep.py +421 -0
  486. kanon_cli-1.3.1/tests/unit/repo/test_stage_coverage.py +308 -0
  487. kanon_cli-1.3.1/tests/unit/repo/test_stage_massive.py +338 -0
  488. kanon_cli-1.3.1/tests/unit/repo/test_start_coverage.py +282 -0
  489. kanon_cli-1.3.1/tests/unit/repo/test_status_coverage.py +263 -0
  490. kanon_cli-1.3.1/tests/unit/repo/test_status_gaps.py +219 -0
  491. kanon_cli-1.3.1/tests/unit/repo/test_status_massive.py +264 -0
  492. kanon_cli-1.3.1/tests/unit/repo/test_subcmd_imports.py +128 -0
  493. kanon_cli-1.3.1/tests/unit/repo/test_subcmds.py +137 -0
  494. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_abandon.py +134 -0
  495. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_branches.py +101 -0
  496. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_checkout.py +113 -0
  497. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_cherry_pick.py +45 -0
  498. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_diff.py +65 -0
  499. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_diffmanifests.py +80 -0
  500. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_download.py +87 -0
  501. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_envsubst.py +299 -0
  502. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_forall.py +341 -0
  503. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_gc.py +336 -0
  504. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_grep.py +328 -0
  505. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_help.py +131 -0
  506. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_info.py +217 -0
  507. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_init.py +373 -0
  508. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_list.py +45 -0
  509. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_manifest.py +210 -0
  510. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_overview.py +45 -0
  511. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_prune.py +45 -0
  512. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_rebase.py +54 -0
  513. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_selfupdate.py +45 -0
  514. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_smartsync.py +45 -0
  515. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_stage.py +41 -0
  516. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_start.py +45 -0
  517. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_status.py +45 -0
  518. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_sync.py +1799 -0
  519. kanon_cli-1.3.1/tests/unit/repo/test_subcmds_upload.py +347 -0
  520. kanon_cli-1.3.1/tests/unit/repo/test_superproject_deep.py +930 -0
  521. kanon_cli-1.3.1/tests/unit/repo/test_sync_coverage_boost.py +1412 -0
  522. kanon_cli-1.3.1/tests/unit/repo/test_sync_deep.py +2509 -0
  523. kanon_cli-1.3.1/tests/unit/repo/test_sync_deep_boost.py +1193 -0
  524. kanon_cli-1.3.1/tests/unit/repo/test_sync_massive.py +734 -0
  525. kanon_cli-1.3.1/tests/unit/repo/test_upload_deep.py +927 -0
  526. kanon_cli-1.3.1/tests/unit/repo/test_version_consolidation.py +464 -0
  527. kanon_cli-1.3.1/tests/unit/repo/test_version_constraints.py +246 -0
  528. kanon_cli-1.3.1/tests/unit/repo/test_wheel_contents.py +376 -0
  529. kanon_cli-1.3.1/tests/unit/repo/test_wrapper.py +565 -0
  530. kanon_cli-1.3.1/tests/unit/repo/test_xml_annotation_attributes.py +715 -0
  531. kanon_cli-1.3.1/tests/unit/repo/test_xml_annotation_crossref.py +1151 -0
  532. kanon_cli-1.3.1/tests/unit/repo/test_xml_annotation_happy.py +703 -0
  533. kanon_cli-1.3.1/tests/unit/repo/test_xml_contactinfo_attributes.py +443 -0
  534. kanon_cli-1.3.1/tests/unit/repo/test_xml_contactinfo_crossref.py +986 -0
  535. kanon_cli-1.3.1/tests/unit/repo/test_xml_contactinfo_happy.py +566 -0
  536. kanon_cli-1.3.1/tests/unit/repo/test_xml_copyfile_attributes.py +647 -0
  537. kanon_cli-1.3.1/tests/unit/repo/test_xml_copyfile_crossref.py +999 -0
  538. kanon_cli-1.3.1/tests/unit/repo/test_xml_copyfile_happy.py +680 -0
  539. kanon_cli-1.3.1/tests/unit/repo/test_xml_default_attributes.py +1118 -0
  540. kanon_cli-1.3.1/tests/unit/repo/test_xml_default_crossref.py +1040 -0
  541. kanon_cli-1.3.1/tests/unit/repo/test_xml_default_happy.py +770 -0
  542. kanon_cli-1.3.1/tests/unit/repo/test_xml_extend_project_attributes.py +766 -0
  543. kanon_cli-1.3.1/tests/unit/repo/test_xml_extend_project_crossref.py +991 -0
  544. kanon_cli-1.3.1/tests/unit/repo/test_xml_extend_project_happy.py +758 -0
  545. kanon_cli-1.3.1/tests/unit/repo/test_xml_fault_malformed.py +551 -0
  546. kanon_cli-1.3.1/tests/unit/repo/test_xml_fault_structural.py +626 -0
  547. kanon_cli-1.3.1/tests/unit/repo/test_xml_include_attributes.py +749 -0
  548. kanon_cli-1.3.1/tests/unit/repo/test_xml_include_crossref.py +1192 -0
  549. kanon_cli-1.3.1/tests/unit/repo/test_xml_include_cycles.py +1007 -0
  550. kanon_cli-1.3.1/tests/unit/repo/test_xml_include_happy.py +770 -0
  551. kanon_cli-1.3.1/tests/unit/repo/test_xml_linkfile_attributes.py +762 -0
  552. kanon_cli-1.3.1/tests/unit/repo/test_xml_linkfile_crossref.py +1003 -0
  553. kanon_cli-1.3.1/tests/unit/repo/test_xml_linkfile_happy.py +782 -0
  554. kanon_cli-1.3.1/tests/unit/repo/test_xml_manifest_attributes.py +1116 -0
  555. kanon_cli-1.3.1/tests/unit/repo/test_xml_manifest_crossref.py +847 -0
  556. kanon_cli-1.3.1/tests/unit/repo/test_xml_manifest_happy.py +807 -0
  557. kanon_cli-1.3.1/tests/unit/repo/test_xml_manifest_server_attributes.py +843 -0
  558. kanon_cli-1.3.1/tests/unit/repo/test_xml_manifest_server_crossref.py +1031 -0
  559. kanon_cli-1.3.1/tests/unit/repo/test_xml_manifest_server_flow.py +709 -0
  560. kanon_cli-1.3.1/tests/unit/repo/test_xml_manifest_server_happy.py +639 -0
  561. kanon_cli-1.3.1/tests/unit/repo/test_xml_notice_attributes.py +660 -0
  562. kanon_cli-1.3.1/tests/unit/repo/test_xml_notice_crossref.py +924 -0
  563. kanon_cli-1.3.1/tests/unit/repo/test_xml_notice_happy.py +581 -0
  564. kanon_cli-1.3.1/tests/unit/repo/test_xml_project_attributes.py +1221 -0
  565. kanon_cli-1.3.1/tests/unit/repo/test_xml_project_crossref.py +985 -0
  566. kanon_cli-1.3.1/tests/unit/repo/test_xml_project_happy.py +980 -0
  567. kanon_cli-1.3.1/tests/unit/repo/test_xml_remote_attributes.py +973 -0
  568. kanon_cli-1.3.1/tests/unit/repo/test_xml_remote_crossref.py +1027 -0
  569. kanon_cli-1.3.1/tests/unit/repo/test_xml_remote_happy.py +827 -0
  570. kanon_cli-1.3.1/tests/unit/repo/test_xml_remove_project_attributes.py +873 -0
  571. kanon_cli-1.3.1/tests/unit/repo/test_xml_remove_project_crossref.py +1180 -0
  572. kanon_cli-1.3.1/tests/unit/repo/test_xml_remove_project_happy.py +700 -0
  573. kanon_cli-1.3.1/tests/unit/repo/test_xml_repo_hooks_attributes.py +520 -0
  574. kanon_cli-1.3.1/tests/unit/repo/test_xml_repo_hooks_crossref.py +850 -0
  575. kanon_cli-1.3.1/tests/unit/repo/test_xml_repo_hooks_happy.py +659 -0
  576. kanon_cli-1.3.1/tests/unit/repo/test_xml_submanifest_attributes.py +923 -0
  577. kanon_cli-1.3.1/tests/unit/repo/test_xml_submanifest_crossref.py +1070 -0
  578. kanon_cli-1.3.1/tests/unit/repo/test_xml_submanifest_happy.py +700 -0
  579. kanon_cli-1.3.1/tests/unit/repo/test_xml_superproject_attributes.py +616 -0
  580. kanon_cli-1.3.1/tests/unit/repo/test_xml_superproject_crossref.py +867 -0
  581. kanon_cli-1.3.1/tests/unit/repo/test_xml_superproject_flow.py +874 -0
  582. kanon_cli-1.3.1/tests/unit/repo/test_xml_superproject_happy.py +675 -0
  583. kanon_cli-1.3.1/tests/unit/repo/test_xmlbool.py +194 -0
  584. kanon_cli-1.3.1/tests/unit/repo/test_xmlint.py +541 -0
  585. kanon_cli-1.3.1/tests/unit/repo/test_yamllint_config.py +52 -0
  586. kanon_cli-1.3.1/tests/unit/test_bare_semver_to_tag.py +82 -0
  587. kanon_cli-1.3.1/tests/unit/test_bootstrap.py +240 -0
  588. kanon_cli-1.3.1/tests/unit/test_ci_workflows.py +268 -0
  589. kanon_cli-1.3.1/tests/unit/test_clean.py +157 -0
  590. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/unit/test_clean_command.py +76 -0
  591. kanon_cli-1.3.1/tests/unit/test_cli.py +141 -0
  592. kanon_cli-1.3.1/tests/unit/test_coverage_gaps.py +122 -0
  593. kanon_cli-1.3.1/tests/unit/test_discover_source_names_missing_url.py +83 -0
  594. kanon_cli-1.3.1/tests/unit/test_docs_embedded_architecture.py +107 -0
  595. kanon_cli-1.3.1/tests/unit/test_docs_remaining_and_catalog.py +237 -0
  596. kanon_cli-1.3.1/tests/unit/test_envsubst_subcommand.py +281 -0
  597. kanon_cli-1.3.1/tests/unit/test_install.py +311 -0
  598. kanon_cli-1.3.1/tests/unit/test_install_command.py +367 -0
  599. kanon_cli-1.3.1/tests/unit/test_integration_testing_doc_manifest_paths.py +306 -0
  600. kanon_cli-1.3.1/tests/unit/test_integration_testing_doc_s2_t14.py +74 -0
  601. kanon_cli-1.3.1/tests/unit/test_integration_testing_doc_s2_t4.py +78 -0
  602. kanon_cli-1.3.1/tests/unit/test_integration_testing_doc_s2_t5.py +97 -0
  603. kanon_cli-1.3.1/tests/unit/test_integration_testing_doc_s2_t6.py +57 -0
  604. kanon_cli-1.3.1/tests/unit/test_integration_testing_doc_s2_t7.py +60 -0
  605. kanon_cli-1.3.1/tests/unit/test_integration_testing_doc_s2_tier1.py +229 -0
  606. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/unit/test_kanonenv.py +37 -0
  607. kanon_cli-1.3.1/tests/unit/test_kanonenv_advanced_edge_cases.py +160 -0
  608. kanon_cli-1.3.1/tests/unit/test_kanonenv_edge_cases.py +204 -0
  609. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/unit/test_marketplace.py +44 -11
  610. kanon_cli-1.3.1/tests/unit/test_marketplace_install.py +182 -0
  611. kanon_cli-1.3.1/tests/unit/test_marketplace_non_plugin_skip.py +123 -0
  612. kanon_cli-1.3.1/tests/unit/test_pre_push_hook.py +296 -0
  613. kanon_cli-1.3.1/tests/unit/test_preamble_semver_tags.py +138 -0
  614. kanon_cli-1.3.1/tests/unit/test_pyproject_build_config.py +116 -0
  615. kanon_cli-1.3.1/tests/unit/test_repo_abspath.py +129 -0
  616. kanon_cli-1.3.1/tests/unit/test_repo_command.py +221 -0
  617. kanon_cli-1.3.1/tests/unit/test_revision_resolve.py +190 -0
  618. kanon_cli-1.3.1/tests/unit/test_rx_catalog_sub_repo.py +250 -0
  619. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/unit/test_validate_command.py +30 -3
  620. kanon_cli-1.3.1/tests/unit/test_version_constraint_errors.py +63 -0
  621. kanon_cli-1.3.1/uv.lock +179 -0
  622. kanon_cli-1.2.0/.github/workflows/pr-validation.yml +0 -152
  623. kanon_cli-1.2.0/CHANGELOG.md +0 -657
  624. kanon_cli-1.2.0/docs/how-it-works.md +0 -74
  625. kanon_cli-1.2.0/docs/integration-testing.md +0 -1818
  626. kanon_cli-1.2.0/src/kanon_cli/cli.py +0 -67
  627. kanon_cli-1.2.0/src/kanon_cli/commands/install.py +0 -213
  628. kanon_cli-1.2.0/src/kanon_cli/constants.py +0 -32
  629. kanon_cli-1.2.0/src/kanon_cli/version.py +0 -189
  630. kanon_cli-1.2.0/tests/conftest.py +0 -37
  631. kanon_cli-1.2.0/tests/unit/test_bootstrap.py +0 -126
  632. kanon_cli-1.2.0/tests/unit/test_clean.py +0 -110
  633. kanon_cli-1.2.0/tests/unit/test_cli.py +0 -67
  634. kanon_cli-1.2.0/tests/unit/test_install.py +0 -217
  635. kanon_cli-1.2.0/tests/unit/test_install_command.py +0 -352
  636. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.claude/settings.json +0 -0
  637. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/.devcontainer.postcreate.sh +0 -0
  638. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/VERSION +0 -0
  639. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/catalog-entry.json +0 -0
  640. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/devcontainer-functions.sh +0 -0
  641. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/devcontainer.json +0 -0
  642. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/fix-line-endings.py +0 -0
  643. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/nix-family-os/README.md +0 -0
  644. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/nix-family-os/tinyproxy-daemon.sh +0 -0
  645. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/nix-family-os/tinyproxy.conf.template +0 -0
  646. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/postcreate-wrapper.sh +0 -0
  647. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/project-setup.sh +0 -0
  648. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/wsl-family-os/README.md +0 -0
  649. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/wsl-family-os/tinyproxy-daemon.sh +0 -0
  650. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.devcontainer/wsl-family-os/tinyproxy.conf.template +0 -0
  651. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.github/CODEOWNERS +0 -0
  652. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.github/workflows/codeql-analysis.yml +0 -0
  653. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.github/workflows/publish.yml +0 -0
  654. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.pre-commit-config.yaml +0 -0
  655. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.tool-versions +0 -0
  656. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/.yamllint +0 -0
  657. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/CLAUDE.md +0 -0
  658. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/LICENSE +0 -0
  659. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/docs/claude-marketplaces-guide.md +0 -0
  660. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/docs/creating-packages.md +0 -0
  661. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/docs/multi-source-guide.md +0 -0
  662. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/git-hooks/pre-commit +0 -0
  663. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/requirements.txt +0 -0
  664. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/__main__.py +0 -0
  665. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/commands/__init__.py +0 -0
  666. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/__init__.py +0 -0
  667. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/catalog.py +0 -0
  668. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/discover.py +0 -0
  669. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/marketplace_validator.py +0 -0
  670. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/src/kanon_cli/core/xml_validator.py +0 -0
  671. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/__init__.py +0 -0
  672. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/functional/__init__.py +0 -0
  673. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/functional/test_clean_lifecycle.py +0 -0
  674. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/functional/test_validate_lifecycle.py +0 -0
  675. {kanon_cli-1.2.0/tests/unit → kanon_cli-1.3.1/tests/integration}/__init__.py +0 -0
  676. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/unit/test_catalog.py +0 -0
  677. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/unit/test_discover.py +0 -0
  678. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/unit/test_marketplace_validator.py +0 -0
  679. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/unit/test_version.py +0 -0
  680. {kanon_cli-1.2.0 → kanon_cli-1.3.1}/tests/unit/test_xml_validator.py +0 -0
@@ -0,0 +1,116 @@
1
+ name: Setup kanon CI environment
2
+ description: |
3
+ Composite action shared by every job in pr-validation.yml and
4
+ main-validation.yml. Handles checkout, optional simulate-merge,
5
+ Python install, asdf bootstrap (plus plugin install per
6
+ .tool-versions), pip dependency cache, dev dependency install via
7
+ `make install-dev`, and uv install. Each parallel CI job calls this
8
+ action once before invoking its own singular Make target / pytest
9
+ invocation, so the per-job step list stays minimal and the setup
10
+ drift between jobs is impossible.
11
+
12
+ inputs:
13
+ base-ref:
14
+ description: >-
15
+ Base ref to simulate-merge against. Leave empty to skip the
16
+ simulate-merge step (e.g. for push-to-main runs); set to the
17
+ pull-request base ref for pull_request runs.
18
+ required: false
19
+ default: ''
20
+ head-sha:
21
+ description: >-
22
+ Head SHA to merge into the base ref. Required when base-ref is
23
+ non-empty; ignored otherwise.
24
+ required: false
25
+ default: ''
26
+
27
+ runs:
28
+ using: composite
29
+ steps:
30
+ # NOTE: callers MUST run `actions/checkout@v6` BEFORE `uses: ./...setup-kanon`
31
+ # because GitHub Actions resolves the composite action path against the
32
+ # runner's working directory; without a prior checkout the action file
33
+ # is not yet on disk. Every job in pr-validation.yml / main-validation.yml
34
+ # does its own `actions/checkout@v6` step explicitly.
35
+ # Configure a global git identity unconditionally so the runner
36
+ # environment is identical for pull_request and push-to-main runs.
37
+ # Previously this was nested inside the `if: inputs.base-ref != ''`
38
+ # Simulate-merge step, which fires only on PR runs; push-to-main
39
+ # runs ran with no global identity, so any test that depended on
40
+ # one passed on PR validation but failed on Main Branch Validation.
41
+ # Tests should not depend on this baseline (each test fixture
42
+ # configures identity locally on its own repos) but having a
43
+ # consistent environment across both workflows prevents the same
44
+ # class of divergence from masking future test fixture bugs at PR
45
+ # time.
46
+ - name: Configure default git identity
47
+ shell: bash
48
+ run: |
49
+ git config --global user.name "GitHub Actions"
50
+ git config --global user.email "actions@github.com"
51
+
52
+ - name: Simulate merge
53
+ if: inputs.base-ref != ''
54
+ shell: bash
55
+ run: |
56
+ git fetch origin ${{ inputs.base-ref }}
57
+ git checkout -b pr-validation origin/${{ inputs.base-ref }}
58
+ git merge --no-commit --no-ff ${{ inputs.head-sha }}
59
+
60
+ - name: Setup Python
61
+ uses: actions/setup-python@v6
62
+ with:
63
+ python-version: '3.14'
64
+
65
+ - name: Cache ASDF installation
66
+ uses: actions/cache@v5
67
+ with:
68
+ path: ~/.asdf
69
+ key: ${{ runner.os }}-asdf-v0.15.0-${{ hashFiles('.tool-versions') }}
70
+ restore-keys: |
71
+ ${{ runner.os }}-asdf-v0.15.0-
72
+
73
+ - name: Install ASDF
74
+ shell: bash
75
+ run: |
76
+ if [ ! -d ~/.asdf ]; then
77
+ git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.15.0
78
+ fi
79
+ echo "$HOME/.asdf/bin" >> $GITHUB_PATH
80
+ echo "$HOME/.asdf/shims" >> $GITHUB_PATH
81
+ source $HOME/.asdf/asdf.sh
82
+
83
+ - name: Install ASDF plugins and tools
84
+ shell: bash
85
+ run: |
86
+ cd $GITHUB_WORKSPACE
87
+ source $HOME/.asdf/asdf.sh
88
+ cut -d' ' -f1 .tool-versions | xargs -I{} asdf plugin add {} || true
89
+ asdf plugin remove python 2>/dev/null || true
90
+ asdf install
91
+ asdf reshim
92
+
93
+ - name: Cache Python dependencies
94
+ uses: actions/cache@v5
95
+ with:
96
+ path: |
97
+ ~/.cache/pip
98
+ ~/.local/lib/python*/site-packages
99
+ key: ${{ runner.os }}-pip-${{ hashFiles('requirements-dev.txt', 'pyproject.toml') }}
100
+ restore-keys: |
101
+ ${{ runner.os }}-pip-
102
+
103
+ - name: Install dependencies
104
+ shell: bash
105
+ run: |
106
+ pip install --upgrade pip
107
+ make install-dev
108
+
109
+ - name: Install uv
110
+ # `tests/unit/repo/test_wheel_contents.py`,
111
+ # `tests/integration/test_wheel_e2e.py`, and
112
+ # `tests/integration/test_ci_validation.py` shell out to
113
+ # `uv build` to produce the wheel under test; uv must be on
114
+ # PATH for any job that runs those suites (including the
115
+ # full-suite regression job that runs every test together).
116
+ uses: astral-sh/setup-uv@v6
@@ -13,81 +13,90 @@ concurrency:
13
13
  cancel-in-progress: false
14
14
 
15
15
  jobs:
16
- validate:
17
- name: Validate Main
16
+ pre-commit:
17
+ name: Pre-commit hooks
18
18
  if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
19
19
  runs-on: ubuntu-24.04
20
-
21
20
  steps:
22
21
  - name: Checkout code
23
22
  uses: actions/checkout@v6
24
23
  with:
25
24
  fetch-depth: 0
26
-
27
- - name: Setup Python
28
- uses: actions/setup-python@v6
29
- with:
30
- python-version: '3.14'
31
-
32
- - name: Cache ASDF installation
33
- uses: actions/cache@v5
34
- with:
35
- path: ~/.asdf
36
- key: ${{ runner.os }}-asdf-v0.15.0-${{ hashFiles('.tool-versions') }}
37
- restore-keys: |
38
- ${{ runner.os }}-asdf-v0.15.0-
39
-
40
- - name: Install ASDF
41
- run: |
42
- if [ ! -d ~/.asdf ]; then
43
- git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.15.0
44
- fi
45
- echo "$HOME/.asdf/bin" >> $GITHUB_PATH
46
- echo "$HOME/.asdf/shims" >> $GITHUB_PATH
47
- source $HOME/.asdf/asdf.sh
25
+ - uses: ./.github/actions/setup-kanon
26
+ - name: Run pre-commit checks
48
27
  shell: bash
49
-
50
- - name: Install ASDF plugins and tools
51
28
  run: |
52
- cd $GITHUB_WORKSPACE
53
29
  source $HOME/.asdf/asdf.sh
54
- cut -d' ' -f1 .tool-versions | xargs -I{} asdf plugin add {} || true
55
- asdf plugin remove python 2>/dev/null || true
56
- asdf install
57
- asdf reshim
58
- shell: bash
30
+ make pre-commit-check
59
31
 
60
- - name: Cache Python dependencies
61
- uses: actions/cache@v5
32
+ lint-check:
33
+ name: Lint (ruff check)
34
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
35
+ runs-on: ubuntu-24.04
36
+ steps:
37
+ - name: Checkout code
38
+ uses: actions/checkout@v6
62
39
  with:
63
- path: |
64
- ~/.cache/pip
65
- ~/.local/lib/python*/site-packages
66
- key: ${{ runner.os }}-pip-${{ hashFiles('requirements-dev.txt', 'pyproject.toml') }}
67
- restore-keys: |
68
- ${{ runner.os }}-pip-
69
-
70
- - name: Install dependencies
71
- run: |
72
- pip install --upgrade pip
73
- make install-dev
40
+ fetch-depth: 0
41
+ - uses: ./.github/actions/setup-kanon
42
+ - name: Run ruff check
74
43
  shell: bash
44
+ run: make lint-check
75
45
 
76
- - name: Run pre-commit checks
77
- run: |
78
- source $HOME/.asdf/asdf.sh
79
- make pre-commit-check
46
+ format-check:
47
+ name: Format check (ruff format --check)
48
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
49
+ runs-on: ubuntu-24.04
50
+ steps:
51
+ - name: Checkout code
52
+ uses: actions/checkout@v6
53
+ with:
54
+ fetch-depth: 0
55
+ - uses: ./.github/actions/setup-kanon
56
+ - name: Run ruff format --check
80
57
  shell: bash
58
+ run: make format-check
81
59
 
82
- - name: Lint
83
- run: make lint
60
+ security-scan:
61
+ name: Security scan (bandit)
62
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
63
+ runs-on: ubuntu-24.04
64
+ steps:
65
+ - name: Checkout code
66
+ uses: actions/checkout@v6
67
+ with:
68
+ fetch-depth: 0
69
+ - uses: ./.github/actions/setup-kanon
70
+ - name: Run bandit
84
71
  shell: bash
72
+ run: make security-scan
85
73
 
86
- - name: Build
87
- run: make publish
74
+ build:
75
+ name: Build wheel
76
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
77
+ runs-on: ubuntu-24.04
78
+ steps:
79
+ - name: Checkout code
80
+ uses: actions/checkout@v6
81
+ with:
82
+ fetch-depth: 0
83
+ - uses: ./.github/actions/setup-kanon
84
+ - name: Build distribution
88
85
  shell: bash
86
+ run: make publish
89
87
 
90
- - name: Run unit tests with coverage threshold
88
+ unit-tests:
89
+ name: Unit tests (with coverage gate)
90
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
91
+ runs-on: ubuntu-24.04
92
+ steps:
93
+ - name: Checkout code
94
+ uses: actions/checkout@v6
95
+ with:
96
+ fetch-depth: 0
97
+ - uses: ./.github/actions/setup-kanon
98
+ - name: Run unit tests with 90% coverage gate
99
+ shell: bash
91
100
  run: |
92
101
  python -m pytest -m unit --cov=kanon_cli --cov-report=term-missing
93
102
  coverage json
@@ -97,16 +106,62 @@ jobs:
97
106
  echo "Error: Code coverage is below 90% threshold ($coverage_percent%)"
98
107
  exit 1
99
108
  fi
109
+
110
+ integration-tests:
111
+ name: Integration tests
112
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
113
+ runs-on: ubuntu-24.04
114
+ steps:
115
+ - name: Checkout code
116
+ uses: actions/checkout@v6
117
+ with:
118
+ fetch-depth: 0
119
+ - uses: ./.github/actions/setup-kanon
120
+ - name: Run integration tests
100
121
  shell: bash
122
+ run: python -m pytest -m integration
101
123
 
124
+ functional-tests:
125
+ name: Functional tests
126
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
127
+ runs-on: ubuntu-24.04
128
+ steps:
129
+ - name: Checkout code
130
+ uses: actions/checkout@v6
131
+ with:
132
+ fetch-depth: 0
133
+ - uses: ./.github/actions/setup-kanon
102
134
  - name: Run functional tests
135
+ shell: bash
103
136
  run: make test-functional
137
+
138
+ scenario-tests:
139
+ name: Scenario tests (docs/integration-testing.md)
140
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
141
+ runs-on: ubuntu-24.04
142
+ steps:
143
+ - name: Checkout code
144
+ uses: actions/checkout@v6
145
+ with:
146
+ fetch-depth: 0
147
+ - uses: ./.github/actions/setup-kanon
148
+ - name: Run scenario tests
104
149
  shell: bash
150
+ run: make test-scenarios
105
151
 
106
- - name: Print coverage summary
107
- run: |
108
- python -m pytest -m unit --cov=kanon_cli --cov-report=term-missing
152
+ full-suite-regression:
153
+ name: Full suite regression (cross-suite isolation guard)
154
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
155
+ runs-on: ubuntu-24.04
156
+ steps:
157
+ - name: Checkout code
158
+ uses: actions/checkout@v6
159
+ with:
160
+ fetch-depth: 0
161
+ - uses: ./.github/actions/setup-kanon
162
+ - name: Run the full suite together
109
163
  shell: bash
164
+ run: make test
110
165
 
111
166
  codeql:
112
167
  name: CodeQL Analysis
@@ -134,7 +189,18 @@ jobs:
134
189
  manual-approval:
135
190
  name: Manual QA Approval
136
191
  if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
137
- needs: [validate, codeql]
192
+ needs:
193
+ - pre-commit
194
+ - lint-check
195
+ - format-check
196
+ - security-scan
197
+ - build
198
+ - unit-tests
199
+ - integration-tests
200
+ - functional-tests
201
+ - scenario-tests
202
+ - full-suite-regression
203
+ - codeql
138
204
  runs-on: ubuntu-24.04
139
205
  environment:
140
206
  name: qa-approval
@@ -142,6 +208,7 @@ jobs:
142
208
 
143
209
  steps:
144
210
  - name: QA Approval
211
+ shell: bash
145
212
  run: echo "QA has been approved"
146
213
 
147
214
  create-release:
@@ -180,6 +247,7 @@ jobs:
180
247
  ${{ runner.os }}-asdf-v0.15.0-
181
248
 
182
249
  - name: Install ASDF
250
+ shell: bash
183
251
  run: |
184
252
  if [ ! -d ~/.asdf ]; then
185
253
  git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.15.0
@@ -187,9 +255,9 @@ jobs:
187
255
  echo "$HOME/.asdf/bin" >> $GITHUB_PATH
188
256
  echo "$HOME/.asdf/shims" >> $GITHUB_PATH
189
257
  source $HOME/.asdf/asdf.sh
190
- shell: bash
191
258
 
192
259
  - name: Install ASDF plugins and tools
260
+ shell: bash
193
261
  run: |
194
262
  cd $GITHUB_WORKSPACE
195
263
  source $HOME/.asdf/asdf.sh
@@ -197,7 +265,6 @@ jobs:
197
265
  asdf plugin remove python 2>/dev/null || true
198
266
  asdf install
199
267
  asdf reshim
200
- shell: bash
201
268
 
202
269
  - name: Cache Python dependencies for release
203
270
  uses: actions/cache@v5
@@ -211,15 +278,16 @@ jobs:
211
278
  ${{ runner.os }}-pip-
212
279
 
213
280
  - name: Install dependencies
281
+ shell: bash
214
282
  run: |
215
283
  pip install --upgrade pip
216
284
  make install-dev
217
- shell: bash
218
285
 
219
286
  - name: Compute next version
220
287
  id: semantic-release
221
288
  env:
222
289
  GH_TOKEN: ${{ steps.generate_token.outputs.token }}
290
+ shell: bash
223
291
  run: |
224
292
  NEW_VERSION=$(python -m semantic_release version --print | sed 's/^v//')
225
293
  echo "New version: $NEW_VERSION"
@@ -229,11 +297,11 @@ jobs:
229
297
  echo "Current version: $NEW_VERSION"
230
298
  fi
231
299
  echo "version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
232
- shell: bash
233
300
 
234
301
  - name: Generate changelog and update version files
235
302
  env:
236
303
  GH_TOKEN: ${{ steps.generate_token.outputs.token }}
304
+ shell: bash
237
305
  run: |
238
306
  python -m semantic_release version --no-push --no-vcs-release --no-commit
239
307
 
@@ -246,12 +314,12 @@ jobs:
246
314
  sed -i 's/[[:space:]]*$//' CHANGELOG.md pyproject.toml src/kanon_cli/__init__.py
247
315
 
248
316
  rm -rf dist/ build/ src/kanon_cli.egg-info/
249
- shell: bash
250
317
 
251
318
  - name: Commit changelog and version bump
252
319
  id: commit-changes
253
320
  env:
254
321
  GH_TOKEN: ${{ steps.generate_token.outputs.token }}
322
+ shell: bash
255
323
  run: |
256
324
  VERSION=$(grep '^version = ' pyproject.toml | sed 's/.*version = "\([^"]*\)".*/\1/')
257
325
  echo "VERSION: $VERSION"
@@ -275,7 +343,7 @@ jobs:
275
343
  echo "$STAGED"
276
344
 
277
345
  if [[ -z "$STAGED" ]]; then
278
- echo "No file changes detected no version bump needed. Skipping release."
346
+ echo "No file changes detected -- no version bump needed. Skipping release."
279
347
  echo "skip_release=true" >> "$GITHUB_OUTPUT"
280
348
  exit 0
281
349
  fi
@@ -297,12 +365,12 @@ jobs:
297
365
 
298
366
  gh pr merge ${PR_URL} --admin --merge
299
367
  echo "Pull request merged successfully"
300
- shell: bash
301
368
 
302
369
  - name: Wait for PR to merge and create Git tag
303
370
  if: steps.commit-changes.outputs.skip_release != 'true'
304
371
  env:
305
372
  GH_TOKEN: ${{ steps.generate_token.outputs.token }}
373
+ shell: bash
306
374
  run: |
307
375
  set -euo pipefail
308
376
 
@@ -341,13 +409,12 @@ jobs:
341
409
 
342
410
  echo "Cleaning up release branch: release-$NEW_VERSION"
343
411
  git push origin --delete release-$NEW_VERSION || echo "Branch already deleted or doesn't exist"
344
- shell: bash
345
412
 
346
413
  - name: Trigger publish workflow
347
414
  if: steps.commit-changes.outputs.skip_release != 'true'
348
415
  env:
349
416
  GH_TOKEN: ${{ steps.generate_token.outputs.token }}
417
+ shell: bash
350
418
  run: |
351
419
  NEW_VERSION=$(grep '^version = ' pyproject.toml | sed 's/.*version = "\([^"]*\)".*/\1/')
352
420
  gh workflow run publish.yml -f tag="$NEW_VERSION"
353
- shell: bash
@@ -0,0 +1,244 @@
1
+ name: PR Validation
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened]
6
+
7
+ jobs:
8
+ pre-commit:
9
+ name: Pre-commit hooks
10
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
11
+ runs-on: ubuntu-24.04
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v6
15
+ with:
16
+ fetch-depth: 0
17
+ - uses: ./.github/actions/setup-kanon
18
+ with:
19
+ base-ref: ${{ github.base_ref }}
20
+ head-sha: ${{ github.event.pull_request.head.sha }}
21
+ - name: Run pre-commit checks
22
+ shell: bash
23
+ run: |
24
+ source $HOME/.asdf/asdf.sh
25
+ make pre-commit-check
26
+
27
+ lint-check:
28
+ name: Lint (ruff check)
29
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
30
+ runs-on: ubuntu-24.04
31
+ steps:
32
+ - name: Checkout code
33
+ uses: actions/checkout@v6
34
+ with:
35
+ fetch-depth: 0
36
+ - uses: ./.github/actions/setup-kanon
37
+ with:
38
+ base-ref: ${{ github.base_ref }}
39
+ head-sha: ${{ github.event.pull_request.head.sha }}
40
+ - name: Run ruff check
41
+ shell: bash
42
+ run: make lint-check
43
+
44
+ format-check:
45
+ name: Format check (ruff format --check)
46
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
47
+ runs-on: ubuntu-24.04
48
+ steps:
49
+ - name: Checkout code
50
+ uses: actions/checkout@v6
51
+ with:
52
+ fetch-depth: 0
53
+ - uses: ./.github/actions/setup-kanon
54
+ with:
55
+ base-ref: ${{ github.base_ref }}
56
+ head-sha: ${{ github.event.pull_request.head.sha }}
57
+ - name: Run ruff format --check
58
+ shell: bash
59
+ run: make format-check
60
+
61
+ security-scan:
62
+ name: Security scan (bandit)
63
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
64
+ runs-on: ubuntu-24.04
65
+ steps:
66
+ - name: Checkout code
67
+ uses: actions/checkout@v6
68
+ with:
69
+ fetch-depth: 0
70
+ - uses: ./.github/actions/setup-kanon
71
+ with:
72
+ base-ref: ${{ github.base_ref }}
73
+ head-sha: ${{ github.event.pull_request.head.sha }}
74
+ - name: Run bandit
75
+ shell: bash
76
+ run: make security-scan
77
+
78
+ build:
79
+ name: Build wheel
80
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
81
+ runs-on: ubuntu-24.04
82
+ steps:
83
+ - name: Checkout code
84
+ uses: actions/checkout@v6
85
+ with:
86
+ fetch-depth: 0
87
+ - uses: ./.github/actions/setup-kanon
88
+ with:
89
+ base-ref: ${{ github.base_ref }}
90
+ head-sha: ${{ github.event.pull_request.head.sha }}
91
+ - name: Build distribution
92
+ shell: bash
93
+ run: make publish
94
+
95
+ unit-tests:
96
+ name: Unit tests (with coverage gate)
97
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
98
+ runs-on: ubuntu-24.04
99
+ steps:
100
+ - name: Checkout code
101
+ uses: actions/checkout@v6
102
+ with:
103
+ fetch-depth: 0
104
+ - uses: ./.github/actions/setup-kanon
105
+ with:
106
+ base-ref: ${{ github.base_ref }}
107
+ head-sha: ${{ github.event.pull_request.head.sha }}
108
+ - name: Run unit tests with 90% coverage gate
109
+ shell: bash
110
+ run: |
111
+ python -m pytest -m unit --cov=kanon_cli --cov-report=term-missing
112
+ coverage json
113
+ coverage_percent=$(python -c "import json; f=open('coverage.json'); print(json.load(f)['totals']['percent_covered'])")
114
+ echo "Coverage: $coverage_percent%"
115
+ if (( $(echo "$coverage_percent < 90" | bc -l) )); then
116
+ echo "Error: Code coverage is below 90% threshold ($coverage_percent%)"
117
+ exit 1
118
+ fi
119
+
120
+ integration-tests:
121
+ name: Integration tests
122
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
123
+ runs-on: ubuntu-24.04
124
+ steps:
125
+ - name: Checkout code
126
+ uses: actions/checkout@v6
127
+ with:
128
+ fetch-depth: 0
129
+ - uses: ./.github/actions/setup-kanon
130
+ with:
131
+ base-ref: ${{ github.base_ref }}
132
+ head-sha: ${{ github.event.pull_request.head.sha }}
133
+ - name: Run integration tests
134
+ shell: bash
135
+ run: python -m pytest -m integration
136
+
137
+ functional-tests:
138
+ name: Functional tests
139
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
140
+ runs-on: ubuntu-24.04
141
+ steps:
142
+ - name: Checkout code
143
+ uses: actions/checkout@v6
144
+ with:
145
+ fetch-depth: 0
146
+ - uses: ./.github/actions/setup-kanon
147
+ with:
148
+ base-ref: ${{ github.base_ref }}
149
+ head-sha: ${{ github.event.pull_request.head.sha }}
150
+ - name: Run functional tests
151
+ shell: bash
152
+ run: make test-functional
153
+
154
+ scenario-tests:
155
+ name: Scenario tests (docs/integration-testing.md)
156
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
157
+ runs-on: ubuntu-24.04
158
+ steps:
159
+ - name: Checkout code
160
+ uses: actions/checkout@v6
161
+ with:
162
+ fetch-depth: 0
163
+ - uses: ./.github/actions/setup-kanon
164
+ with:
165
+ base-ref: ${{ github.base_ref }}
166
+ head-sha: ${{ github.event.pull_request.head.sha }}
167
+ - name: Run scenario tests
168
+ shell: bash
169
+ run: make test-scenarios
170
+
171
+ full-suite-regression:
172
+ name: Full suite regression (cross-suite isolation guard)
173
+ # Runs `make test` -- the same `pytest --cov=kanon_cli` invocation
174
+ # that exercises unit + integration + functional + scenarios in a
175
+ # single process. The singular jobs above pass individually but
176
+ # this job catches the class of cross-suite isolation regressions
177
+ # documented in `git log --grep cross-suite` (e.g. session-scoped
178
+ # autouse fixtures leaking env state into later suites). It runs
179
+ # in parallel with the singular jobs so the wall-clock impact on
180
+ # PR feedback is bounded by the slowest single job, not summed.
181
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
182
+ runs-on: ubuntu-24.04
183
+ steps:
184
+ - name: Checkout code
185
+ uses: actions/checkout@v6
186
+ with:
187
+ fetch-depth: 0
188
+ - uses: ./.github/actions/setup-kanon
189
+ with:
190
+ base-ref: ${{ github.base_ref }}
191
+ head-sha: ${{ github.event.pull_request.head.sha }}
192
+ - name: Run the full suite together
193
+ shell: bash
194
+ run: make test
195
+
196
+ code-owners:
197
+ name: Code owners
198
+ if: ${{ github.actor != 'caylent-platform-bot[bot]' }}
199
+ runs-on: ubuntu-24.04
200
+ steps:
201
+ - name: Checkout code
202
+ uses: actions/checkout@v6
203
+ with:
204
+ fetch-depth: 0
205
+ - name: Find code owners
206
+ id: codeowners
207
+ shell: bash
208
+ run: |
209
+ DEFAULT_OWNER=""
210
+ if [ -f ".github/CODEOWNERS" ]; then
211
+ DEFAULT_OWNER=$(grep -E "^\*|^/" .github/CODEOWNERS | awk '{print $2}' || true)
212
+ fi
213
+
214
+ CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }} ${{ github.event.pull_request.head.sha }})
215
+ echo "Changed files: $CHANGED_FILES"
216
+
217
+ SPECIFIC_OWNERS=""
218
+ if [ -f ".github/CODEOWNERS" ]; then
219
+ for FILE in $CHANGED_FILES; do
220
+ while [[ "$FILE" == */* ]]; do
221
+ DIR=$(dirname "$FILE")
222
+ MATCH=$(grep -E "^$DIR/" .github/CODEOWNERS | awk '{for(i=2;i<=NF;i++) print $i}' || true)
223
+ if [ -n "$MATCH" ]; then
224
+ SPECIFIC_OWNERS="$SPECIFIC_OWNERS $MATCH"
225
+ break
226
+ fi
227
+ FILE="$DIR"
228
+ done
229
+ done
230
+ fi
231
+
232
+ if [ -z "$SPECIFIC_OWNERS" ]; then
233
+ OWNERS="$DEFAULT_OWNER"
234
+ else
235
+ OWNERS="$SPECIFIC_OWNERS"
236
+ fi
237
+
238
+ if [ -n "$OWNERS" ]; then
239
+ UNIQUE_OWNERS=$(echo "$OWNERS" | tr ' ' '\n' | grep -v '^$' | sort -u | tr '\n' ' ' | xargs)
240
+ else
241
+ UNIQUE_OWNERS=""
242
+ fi
243
+ echo "Final owners: $UNIQUE_OWNERS"
244
+ echo "owners=$UNIQUE_OWNERS" >> $GITHUB_OUTPUT