bigfix-remote-session-relevance 0.2.0__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 (245) hide show
  1. bigfix_remote_session_relevance-0.2.0/.editorconfig +21 -0
  2. bigfix_remote_session_relevance-0.2.0/.editorconfig-checker.json +20 -0
  3. bigfix_remote_session_relevance-0.2.0/.github/dependabot.yml +46 -0
  4. bigfix_remote_session_relevance-0.2.0/.github/workflows/pre-commit.yaml +122 -0
  5. bigfix_remote_session_relevance-0.2.0/.github/workflows/tag_and_release.yaml +228 -0
  6. bigfix_remote_session_relevance-0.2.0/.github/workflows/test.yaml +57 -0
  7. bigfix_remote_session_relevance-0.2.0/.gitignore +226 -0
  8. bigfix_remote_session_relevance-0.2.0/.pre-commit-config.yaml +290 -0
  9. bigfix_remote_session_relevance-0.2.0/.python-version +1 -0
  10. bigfix_remote_session_relevance-0.2.0/.yamllint.yaml +13 -0
  11. bigfix_remote_session_relevance-0.2.0/AGENTS.md +71 -0
  12. bigfix_remote_session_relevance-0.2.0/CLAUDE.md +1 -0
  13. bigfix_remote_session_relevance-0.2.0/DESIGN.md +291 -0
  14. bigfix_remote_session_relevance-0.2.0/LICENSE +21 -0
  15. bigfix_remote_session_relevance-0.2.0/PKG-INFO +173 -0
  16. bigfix_remote_session_relevance-0.2.0/README.md +120 -0
  17. bigfix_remote_session_relevance-0.2.0/_typos.toml +3 -0
  18. bigfix_remote_session_relevance-0.2.0/pyproject.toml +129 -0
  19. bigfix_remote_session_relevance-0.2.0/pyrightconfig.json +15 -0
  20. bigfix_remote_session_relevance-0.2.0/remote_session_connections.example.toml +62 -0
  21. bigfix_remote_session_relevance-0.2.0/scripts/capture_fixtures.py +123 -0
  22. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/__init__.py +80 -0
  23. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/backends/__init__.py +1 -0
  24. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/backends/_parsing.py +223 -0
  25. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/backends/base.py +463 -0
  26. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/backends/explorer.py +90 -0
  27. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/backends/explorer_extras.py +57 -0
  28. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/backends/registry.py +33 -0
  29. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/backends/rest.py +112 -0
  30. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/backends/saas.py +368 -0
  31. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/backends/webreports.py +331 -0
  32. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/cli.py +380 -0
  33. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/client.py +355 -0
  34. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/config.py +545 -0
  35. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/deployment.py +52 -0
  36. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/exceptions.py +76 -0
  37. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/py.typed +0 -0
  38. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/redact.py +37 -0
  39. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/render.py +59 -0
  40. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/result.py +219 -0
  41. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/results.py +81 -0
  42. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/server_address.py +132 -0
  43. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/setup_wizard.py +303 -0
  44. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/sync.py +112 -0
  45. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/trust.py +274 -0
  46. bigfix_remote_session_relevance-0.2.0/src/bigfix_remote_session_relevance/value_types.py +128 -0
  47. bigfix_remote_session_relevance-0.2.0/tests/conftest.py +260 -0
  48. bigfix_remote_session_relevance-0.2.0/tests/fixtures/README.md +20 -0
  49. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/bad_password.body +1 -0
  50. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/bad_password.meta.json +1 -0
  51. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/boolean.body +1 -0
  52. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/boolean.meta.json +1 -0
  53. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/deployment_id.body +1 -0
  54. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/deployment_id.meta.json +1 -0
  55. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/empty_plural.body +1 -0
  56. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/empty_plural.meta.json +1 -0
  57. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/error_type.body +1 -0
  58. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/error_type.meta.json +1 -0
  59. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/error_unknown.body +1 -0
  60. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/error_unknown.meta.json +1 -0
  61. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/extras_filter_bad_type.body +1 -0
  62. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/extras_filter_bad_type.meta.json +1 -0
  63. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/extras_filter_computers.body +1 -0
  64. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/extras_filter_computers.meta.json +1 -0
  65. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/extras_keys.body +1 -0
  66. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/extras_keys.meta.json +1 -0
  67. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/float.body +1 -0
  68. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/float.meta.json +1 -0
  69. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/gather_url_hash_check.body +1 -0
  70. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/gather_url_hash_check.meta.json +1 -0
  71. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/nested_tuple.body +1 -0
  72. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/nested_tuple.meta.json +1 -0
  73. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/permission_401.body +1 -0
  74. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/permission_401.meta.json +1 -0
  75. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/plural_integers.body +1 -0
  76. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/plural_integers.meta.json +1 -0
  77. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/plural_strings.body +1 -0
  78. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/plural_strings.meta.json +1 -0
  79. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/plural_tuples.body +1 -0
  80. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/plural_tuples.meta.json +1 -0
  81. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/singular_integer.body +1 -0
  82. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/singular_integer.meta.json +1 -0
  83. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/singular_string.body +1 -0
  84. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/singular_string.meta.json +1 -0
  85. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/starting_405.body +1 -0
  86. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/starting_405.meta.json +1 -0
  87. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/status_starting.body +1 -0
  88. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/status_starting.meta.json +1 -0
  89. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/time.body +1 -0
  90. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/time.meta.json +1 -0
  91. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/tuple.body +1 -0
  92. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/tuple.meta.json +1 -0
  93. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/unavailable_401.body +1 -0
  94. bigfix_remote_session_relevance-0.2.0/tests/fixtures/explorer/captured/unavailable_401.meta.json +1 -0
  95. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/bad_password.body +1 -0
  96. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/bad_password.meta.json +1 -0
  97. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/boolean.body +1 -0
  98. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/boolean.meta.json +1 -0
  99. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/deployment_id.body +1 -0
  100. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/deployment_id.meta.json +1 -0
  101. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/empty_plural.body +1 -0
  102. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/empty_plural.meta.json +1 -0
  103. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/error_type.body +1 -0
  104. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/error_type.meta.json +1 -0
  105. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/error_unknown.body +1 -0
  106. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/error_unknown.meta.json +1 -0
  107. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/float.body +1 -0
  108. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/float.meta.json +1 -0
  109. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/forwarded_filter_bad_type.body +1 -0
  110. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/forwarded_filter_bad_type.meta.json +1 -0
  111. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/forwarded_filter_computers.body +1 -0
  112. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/forwarded_filter_computers.meta.json +1 -0
  113. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/forwarded_keys.body +1 -0
  114. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/forwarded_keys.meta.json +1 -0
  115. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/gather_url_hash_check.body +1 -0
  116. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/gather_url_hash_check.meta.json +1 -0
  117. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/keys_forwarded.body +1 -0
  118. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/keys_forwarded.meta.json +1 -0
  119. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/nested_tuple.body +1 -0
  120. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/nested_tuple.meta.json +1 -0
  121. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/plural_integers.body +1 -0
  122. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/plural_integers.meta.json +1 -0
  123. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/plural_strings.body +1 -0
  124. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/plural_strings.meta.json +1 -0
  125. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/plural_tuples.body +1 -0
  126. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/plural_tuples.meta.json +1 -0
  127. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/plural_tuples__xml.body +19 -0
  128. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/plural_tuples__xml.meta.json +1 -0
  129. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/singular_integer.body +1 -0
  130. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/singular_integer.meta.json +1 -0
  131. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/singular_string.body +1 -0
  132. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/singular_string.meta.json +1 -0
  133. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/time.body +1 -0
  134. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/time.meta.json +1 -0
  135. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/tuple.body +1 -0
  136. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/tuple.meta.json +1 -0
  137. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__bad_password.body +1 -0
  138. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__bad_password.meta.json +1 -0
  139. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__boolean.body +1 -0
  140. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__boolean.meta.json +1 -0
  141. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__deployment_id.body +1 -0
  142. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__deployment_id.meta.json +1 -0
  143. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__empty_plural.body +1 -0
  144. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__empty_plural.meta.json +1 -0
  145. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__error_type.body +1 -0
  146. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__error_type.meta.json +1 -0
  147. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__error_unknown.body +1 -0
  148. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__error_unknown.meta.json +1 -0
  149. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__float.body +1 -0
  150. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__float.meta.json +1 -0
  151. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__gather_url_hash_check.body +1 -0
  152. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__gather_url_hash_check.meta.json +1 -0
  153. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__nested_tuple.body +1 -0
  154. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__nested_tuple.meta.json +1 -0
  155. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__plural_integers.body +1 -0
  156. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__plural_integers.meta.json +1 -0
  157. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__plural_strings.body +1 -0
  158. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__plural_strings.meta.json +1 -0
  159. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__plural_tuples.body +1 -0
  160. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__plural_tuples.meta.json +1 -0
  161. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__singular_integer.body +1 -0
  162. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__singular_integer.meta.json +1 -0
  163. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__singular_string.body +1 -0
  164. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__singular_string.meta.json +1 -0
  165. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__time.body +1 -0
  166. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__time.meta.json +1 -0
  167. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__tuple.body +1 -0
  168. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/captured/via_explorer__tuple.meta.json +1 -0
  169. bigfix_remote_session_relevance-0.2.0/tests/fixtures/rest/doc_plural_strings.json +11 -0
  170. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/captured/deployment_id.json +1 -0
  171. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/captured/empty_plural.json +1 -0
  172. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/captured/error_unknown.json +1 -0
  173. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/captured/nested_tuple.json +1 -0
  174. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/captured/plural_tuples.json +1 -0
  175. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/captured/singular_integer.json +1 -0
  176. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/captured/singular_string.json +1 -0
  177. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/captured/special_chars.json +1 -0
  178. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/captured/time.json +1 -0
  179. bigfix_remote_session_relevance-0.2.0/tests/fixtures/saas/shape_login_ok.json +1 -0
  180. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/bad_password.body +9 -0
  181. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/bad_password.meta.json +1 -0
  182. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/boolean.body +20 -0
  183. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/boolean.meta.json +1 -0
  184. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/boolean__plain.body +8 -0
  185. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/boolean__plain.meta.json +1 -0
  186. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/deployment_id.body +20 -0
  187. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/deployment_id.meta.json +1 -0
  188. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/empty_plural.body +18 -0
  189. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/empty_plural.meta.json +1 -0
  190. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/error_type.body +16 -0
  191. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/error_type.meta.json +1 -0
  192. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/error_unknown.body +16 -0
  193. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/error_unknown.meta.json +1 -0
  194. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/error_unknown__plain.body +9 -0
  195. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/error_unknown__plain.meta.json +1 -0
  196. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/float.body +16 -0
  197. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/float.meta.json +1 -0
  198. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/gather_url_hash_check.body +20 -0
  199. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/gather_url_hash_check.meta.json +1 -0
  200. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/nested_tuple.body +26 -0
  201. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/nested_tuple.meta.json +1 -0
  202. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/plural_integers.body +22 -0
  203. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/plural_integers.meta.json +1 -0
  204. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/plural_strings.body +21 -0
  205. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/plural_strings.meta.json +1 -0
  206. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/plural_strings__plain.body +9 -0
  207. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/plural_strings__plain.meta.json +1 -0
  208. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/plural_tuples.body +27 -0
  209. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/plural_tuples.meta.json +1 -0
  210. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/singular_integer.body +20 -0
  211. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/singular_integer.meta.json +1 -0
  212. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/singular_string.body +20 -0
  213. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/singular_string.meta.json +1 -0
  214. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/time.body +20 -0
  215. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/time.meta.json +1 -0
  216. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/tuple.body +24 -0
  217. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/tuple.meta.json +1 -0
  218. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/tuple__plain.body +8 -0
  219. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/captured/tuple__plain.meta.json +1 -0
  220. bigfix_remote_session_relevance-0.2.0/tests/fixtures/webreports/doc_structured_integers.xml +21 -0
  221. bigfix_remote_session_relevance-0.2.0/tests/integration/test_live.py +106 -0
  222. bigfix_remote_session_relevance-0.2.0/tests/unit/test_backend_base.py +148 -0
  223. bigfix_remote_session_relevance-0.2.0/tests/unit/test_backend_contract.py +129 -0
  224. bigfix_remote_session_relevance-0.2.0/tests/unit/test_backend_explorer.py +55 -0
  225. bigfix_remote_session_relevance-0.2.0/tests/unit/test_backend_rest.py +285 -0
  226. bigfix_remote_session_relevance-0.2.0/tests/unit/test_backend_saas.py +519 -0
  227. bigfix_remote_session_relevance-0.2.0/tests/unit/test_backend_webreports.py +264 -0
  228. bigfix_remote_session_relevance-0.2.0/tests/unit/test_captured_fixtures.py +303 -0
  229. bigfix_remote_session_relevance-0.2.0/tests/unit/test_cli.py +265 -0
  230. bigfix_remote_session_relevance-0.2.0/tests/unit/test_client.py +436 -0
  231. bigfix_remote_session_relevance-0.2.0/tests/unit/test_config.py +395 -0
  232. bigfix_remote_session_relevance-0.2.0/tests/unit/test_deployment.py +85 -0
  233. bigfix_remote_session_relevance-0.2.0/tests/unit/test_explorer_extras.py +101 -0
  234. bigfix_remote_session_relevance-0.2.0/tests/unit/test_redact.py +42 -0
  235. bigfix_remote_session_relevance-0.2.0/tests/unit/test_registry.py +57 -0
  236. bigfix_remote_session_relevance-0.2.0/tests/unit/test_render.py +76 -0
  237. bigfix_remote_session_relevance-0.2.0/tests/unit/test_result.py +211 -0
  238. bigfix_remote_session_relevance-0.2.0/tests/unit/test_results.py +65 -0
  239. bigfix_remote_session_relevance-0.2.0/tests/unit/test_server_address.py +119 -0
  240. bigfix_remote_session_relevance-0.2.0/tests/unit/test_setup_wizard.py +440 -0
  241. bigfix_remote_session_relevance-0.2.0/tests/unit/test_sync.py +79 -0
  242. bigfix_remote_session_relevance-0.2.0/tests/unit/test_trust.py +219 -0
  243. bigfix_remote_session_relevance-0.2.0/tests/unit/test_trust_prompts.py +34 -0
  244. bigfix_remote_session_relevance-0.2.0/tests/unit/test_value_types.py +81 -0
  245. bigfix_remote_session_relevance-0.2.0/uv.lock +777 -0
@@ -0,0 +1,21 @@
1
+ # Check http://editorconfig.org for more information
2
+ # This is the main config file for this project:
3
+ root = true
4
+
5
+ [*]
6
+ charset = utf-8
7
+ trim_trailing_whitespace = true
8
+ indent_style = space
9
+ insert_final_newline = true
10
+
11
+ [*.py]
12
+ indent_size = 4
13
+
14
+ [*.{bes,bes.mustache}]
15
+ # bes files are XML, but the `actionscript` tag text must use crlf
16
+ end_of_line = crlf
17
+ indent_style = tab
18
+ indent_size = 3
19
+
20
+ [*.{bat,cmd}]
21
+ end_of_line = crlf
@@ -0,0 +1,20 @@
1
+ {
2
+ "$comment": [
3
+ "Config for the editorconfig-checker hook in .pre-commit-config.yaml.",
4
+ "Run locally: `uvx --from editorconfig-checker ec`.",
5
+ "Scoping belongs in .editorconfig itself wherever it can be expressed",
6
+ "there, so rules and their exceptions stay in one place. Only what",
7
+ "EditorConfig cannot express belongs here."
8
+ ],
9
+ "Disable": {
10
+ "IndentSize": true
11
+ },
12
+ "$comment_Disable": [
13
+ "IndentSize checks that left-padding is a multiple of indent_size, which",
14
+ "flags ruff-format's own docstring and comment prose continuations (the",
15
+ "hanging-indent continuation lines in __init__.py, ssh.py and others).",
16
+ "ruff-format already fully governs Python indentation, so this check has",
17
+ "nothing to add and 19 false positives to contribute. indent_style,",
18
+ "end_of_line, trailing whitespace and final newline all stay on."
19
+ ]
20
+ }
@@ -0,0 +1,46 @@
1
+ # Dependency-update alerts, closing the "no automated vulnerability alerting
2
+ # path" gap in docs/security-review.md.
3
+ #
4
+ # Requires Dependabot to be enabled on the GHES instance - this file is inert,
5
+ # not an error, if it is not. Check Security > Dependabot settings.
6
+ #
7
+ # The 7-day cooldown is the point, not a courtesy: a release published minutes
8
+ # ago is the likeliest to be a compromised one. It matches `exclude-newer` in
9
+ # pyproject.toml and is zizmor's minimum.
10
+ version: 2
11
+ updates:
12
+ # "uv", not "pip": uv.lock is what the release wheel is built from
13
+ # (uv sync --locked), and "pip" would read pyproject.toml without updating
14
+ # the lock. Fall back to "pip" if this instance rejects the newer ecosystem.
15
+ - package-ecosystem: "uv"
16
+ directory: "/"
17
+ schedule:
18
+ interval: "weekly"
19
+ cooldown:
20
+ default-days: 7
21
+ open-pull-requests-limit: 5
22
+ labels:
23
+ - "dependencies"
24
+
25
+ - package-ecosystem: "github-actions"
26
+ directory: "/"
27
+ schedule:
28
+ interval: "weekly"
29
+ cooldown:
30
+ default-days: 7
31
+ open-pull-requests-limit: 5
32
+ labels:
33
+ - "dependencies"
34
+
35
+ # Scans .pre-commit-config.yaml and updates each hook's `rev:` (SHA-pinned
36
+ # revs get their version comment updated too, same as the github-actions
37
+ # entries above). No `cooldown` here: as of 2026-03, GitHub does not support
38
+ # the cooldown option for this ecosystem, so these PRs land without the
39
+ # 7-day delay the other two ecosystems get - review before merging.
40
+ - package-ecosystem: "pre-commit"
41
+ directory: "/"
42
+ schedule:
43
+ interval: "weekly"
44
+ open-pull-requests-limit: 5
45
+ labels:
46
+ - "dependencies"
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: pre-commit
3
+
4
+ on:
5
+ pull_request:
6
+ push:
7
+ branches:
8
+ - main
9
+ workflow_dispatch:
10
+
11
+ # read-only by default; the cross-repo checkout uses secrets.CROSSREPO_PAT
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ group: pre-commit-${{ github.ref }}
17
+ cancel-in-progress: true
18
+
19
+ jobs:
20
+ pre-commit:
21
+ runs-on: ubuntu-latest
22
+ # no-commit-to-branch guards a developer's local `git commit`; it has nothing
23
+ # to check on a runner. On a push to main, actions/checkout leaves HEAD on
24
+ # the main branch, so the hook fails the whole run on a merged PR. (On a
25
+ # pull_request event HEAD is detached at the merge ref, where it passes -
26
+ # which is why this only shows up after the merge.) SKIP is read by
27
+ # pre-commit itself, so it applies to both steps below.
28
+ #
29
+ # GH_TOKEN puts zizmor in online mode (offline is the default without it):
30
+ # it can then fetch the referenced actions themselves for the audits that
31
+ # need that - see the comment above the zizmor hook in
32
+ # .pre-commit-config.yaml. The runner's own GITHUB_TOKEN is enough for a
33
+ # public repo; this is read-only per the `permissions:` block above and
34
+ # never touches git credentials (actions/checkout above already sets
35
+ # persist-credentials: false).
36
+ env:
37
+ SKIP: no-commit-to-branch
38
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39
+ steps:
40
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
41
+ with:
42
+ # requited to grab the history of the PR for pre-commit
43
+ fetch-depth: 0
44
+ persist-credentials: false
45
+
46
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
47
+ with:
48
+ python-version: "3.12"
49
+
50
+ # single source of truth for the uv version: the `rev` of the
51
+ # astral-sh/uv-pre-commit repo in .pre-commit-config.yaml, which
52
+ # `pre-commit autoupdate` already keeps current. Read with awk rather
53
+ # than a yaml parser so it needs nothing installed first. `rev` is
54
+ # SHA-pinned (Dependabot's pre-commit ecosystem keeps the trailing
55
+ # `# X.Y.Z` comment in sync when it bumps the SHA - same convention as
56
+ # the actions/* pins above), so the version comes from that comment;
57
+ # fall back to the bare `rev` value for a tag-pinned rev with no
58
+ # comment.
59
+ - name: read uv version from .pre-commit-config.yaml
60
+ run: |
61
+ UV_VERSION="$(awk '
62
+ /^[[:space:]]*-[[:space:]]*repo:.*astral-sh\/uv-pre-commit[[:space:]]*$/ { found = 1; next }
63
+ found && $1 == "rev:" {
64
+ if (match($0, /#[ \t]*(frozen:[ \t]*)?[vV]?[0-9]+(\.[0-9]+)*/)) {
65
+ ver = substr($0, RSTART, RLENGTH)
66
+ sub(/^#[ \t]*(frozen:[ \t]*)?[vV]?/, "", ver)
67
+ } else {
68
+ ver = $2
69
+ gsub(/["'\'']/, "", ver)
70
+ sub(/^[vV]/, "", ver)
71
+ }
72
+ print ver
73
+ exit
74
+ }
75
+ ' .pre-commit-config.yaml)"
76
+ if [ -z "$UV_VERSION" ]; then
77
+ echo "::error::could not read the astral-sh/uv-pre-commit version from .pre-commit-config.yaml"
78
+ exit 1
79
+ fi
80
+ echo "UV_VERSION=$UV_VERSION" >> "$GITHUB_ENV"
81
+ echo "uv version: $UV_VERSION"
82
+
83
+ # the local `uv-lock-check` / `uv-build-wheel` hooks are language: system
84
+ # and run at the manual stage, which this workflow always requests. They
85
+ # look for `uv` on PATH first and only fall back to this repo's .venv,
86
+ # which does not exist on a runner - so uv has to be installed here or
87
+ # both hooks fail.
88
+ - name: install uv (needed by the local pre-commit hooks)
89
+ run: python -m pip install "uv==${UV_VERSION}"
90
+
91
+ - name: pre-commit local action test
92
+ if: github.event_name != 'workflow_dispatch'
93
+ uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
94
+ with:
95
+ extra_args: >-
96
+ --color=always
97
+ --from-ref ${{ github.event.pull_request.base.sha || github.event.before }}
98
+ --to-ref ${{ github.event.pull_request.head.sha || github.sha }}
99
+ --hook-stage manual
100
+
101
+ # manual dispatch: run every hook (including the manual-stage ones -
102
+ # validate-pyproject, the pytest wrapper, the check-useless-excludes/
103
+ # check-hooks-apply meta hooks) against the full tree, not just the
104
+ # diff range a PR/push would use
105
+ - name: pre-commit local action test (manual dispatch)
106
+ if: github.event_name == 'workflow_dispatch'
107
+ uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
108
+ with:
109
+ extra_args: --color=always --all-files --hook-stage manual
110
+
111
+ # `restore-keys` above means a config change restores the previous cache
112
+ # and then saves it back under the new key - so every hook rev bump would
113
+ # otherwise leave its old environment in the cache forever (the pytest
114
+ # hook's fastmcp install is the fat one). gc deletes exactly the
115
+ # environments no live config references. Last step in the job on purpose:
116
+ # actions/cache saves in its post step, which runs after this, so what
117
+ # gets uploaded is the pruned store. No `if:` - the default success()
118
+ # matches the cache action's own `post-if: success()`, so this runs in
119
+ # precisely the cases where a save follows. `pre-commit` is on PATH from
120
+ # the shared action's `python -m pip install pre-commit`.
121
+ - name: prune unused hook environments before the cache is saved
122
+ run: pre-commit gc
@@ -0,0 +1,228 @@
1
+ ---
2
+ # Tags and releases on a version bump. Nothing here bumps the version: the flow
3
+ # is to change `[project] version` in pyproject.toml in a PR, merge it to main,
4
+ # and this workflow does the rest (tag, build, checksums, GitHub Release, and -
5
+ # once deliberately enabled, see the publish step - PyPI).
6
+ name: Tag and Release
7
+
8
+ on:
9
+ push:
10
+ branches:
11
+ - main
12
+ paths:
13
+ - "pyproject.toml"
14
+ - "uv.lock"
15
+ - "src/**"
16
+ - ".github/workflows/tag_and_release.yaml"
17
+ - ".github/workflows/test.yaml"
18
+ # a re-run path for when a release run failed after the version was already
19
+ # merged; the tag check below still makes it a no-op if the tag exists
20
+ workflow_dispatch:
21
+
22
+ permissions:
23
+ contents: read
24
+
25
+ concurrency:
26
+ # deliberately no cancel-in-progress: never kill a release mid-flight
27
+ group: release-${{ github.ref }}
28
+
29
+ jobs:
30
+ # Decides whether there is anything to do, so the expensive jobs below can be
31
+ # skipped outright. A push that touches src/** without bumping the version
32
+ # gets a green, near-instant run and no release.
33
+ version:
34
+ name: Check for an untagged version
35
+ runs-on: ubuntu-latest
36
+ # fork guard: a fork that pushes to its own main should not try to release
37
+ if: github.repository == 'jgstew/bigfix-remote-session-relevance'
38
+ outputs:
39
+ version: ${{ steps.getversion.outputs.version }}
40
+ release_needed: ${{ steps.tagged.outputs.release_needed }}
41
+ steps:
42
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
43
+ with:
44
+ # full history + tags: the tag check below needs every existing tag
45
+ fetch-depth: 0
46
+ fetch-tags: true
47
+ persist-credentials: false
48
+
49
+ # `[project] version` in pyproject.toml is the single source of truth.
50
+ # tomllib is stdlib on the 3.11+ this package requires, and the runner's
51
+ # preinstalled python is new enough, so no setup-python step is needed.
52
+ - name: Read version from pyproject.toml
53
+ id: getversion
54
+ run: |
55
+ version="$(python3 -c 'import pathlib, tomllib; print(tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"])')"
56
+ if ! printf '%s' "$version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+([.-]?[0-9A-Za-z.]+)?$'; then
57
+ echo "::error::unexpected version string in pyproject.toml: '$version'"
58
+ exit 1
59
+ fi
60
+ echo "version=$version" >> "$GITHUB_OUTPUT"
61
+ echo "version: $version"
62
+
63
+ # Release only if this version has no tag yet. This is what makes the
64
+ # workflow idempotent and safe to re-run.
65
+ - name: Check whether v<version> is already tagged
66
+ id: tagged
67
+ env:
68
+ VERSION: ${{ steps.getversion.outputs.version }}
69
+ run: |
70
+ if git show-ref --tags --verify --quiet -- "refs/tags/v${VERSION}"; then
71
+ echo "release_needed=false" >> "$GITHUB_OUTPUT"
72
+ echo "v${VERSION} is already tagged - nothing to release"
73
+ else
74
+ echo "release_needed=true" >> "$GITHUB_OUTPUT"
75
+ echo "v${VERSION} has no tag yet - will release"
76
+ fi
77
+
78
+ # The gate. Reusing the test workflow means the release is blocked by the
79
+ # exact same job that guards PRs, with no third-party wait-for-checks action
80
+ # and no polling. Lint/type-check are owned by pre-commit.yaml and are not
81
+ # waited on here - branch protection on main is what keeps those green.
82
+ test:
83
+ name: Test
84
+ needs: version
85
+ if: needs.version.outputs.release_needed == 'true'
86
+ uses: ./.github/workflows/test.yaml # zizmor: ignore[self-repository] -- ./ is the documented local reusable-workflow form
87
+
88
+ release:
89
+ name: Tag and Release
90
+ needs: [version, test]
91
+ runs-on: ubuntu-latest
92
+ # Deliberately gates the whole release - tag, GitHub release, and PyPI
93
+ # upload - not just the publish step, so an environment protection rule
94
+ # (required reviewer, wait timer, branch restriction) stops a release
95
+ # before the tag is cut rather than after. The name must match the
96
+ # `Environment name` field of the PyPI trusted publisher exactly: PyPI
97
+ # checks the `environment` claim in the OIDC token, and a mismatch fails
98
+ # the publish. Create it under Settings > Environments; an environment
99
+ # with no protection rules is valid and simply records the deployment.
100
+ environment: pypi
101
+ permissions:
102
+ # contents: write - create the tag and the release, and upload assets.
103
+ # id-token: write - OIDC for the PyPI trusted-publishing step at the end
104
+ # of this job. Both live here rather than in a separate publish job so
105
+ # the built dist/ does not have to be handed between jobs through
106
+ # upload-artifact/download-artifact.
107
+ contents: write
108
+ id-token: write
109
+ steps:
110
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
111
+ with:
112
+ persist-credentials: false
113
+
114
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
115
+ with:
116
+ python-version: "3.13"
117
+
118
+ # same awk-from-.pre-commit-config.yaml source of truth as
119
+ # .github/workflows/test.yaml and pre-commit.yaml
120
+ - name: read uv version from .pre-commit-config.yaml
121
+ run: |
122
+ UV_VERSION="$(awk '
123
+ /^[[:space:]]*-[[:space:]]*repo:.*astral-sh\/uv-pre-commit[[:space:]]*$/ { found = 1; next }
124
+ found && $1 == "rev:" {
125
+ if (match($0, /#[ \t]*(frozen:[ \t]*)?[vV]?[0-9]+(\.[0-9]+)*/)) {
126
+ ver = substr($0, RSTART, RLENGTH)
127
+ sub(/^#[ \t]*(frozen:[ \t]*)?[vV]?/, "", ver)
128
+ } else {
129
+ ver = $2
130
+ gsub(/["'\'']/, "", ver)
131
+ sub(/^[vV]/, "", ver)
132
+ }
133
+ print ver
134
+ exit
135
+ }
136
+ ' .pre-commit-config.yaml)"
137
+ if [ -z "$UV_VERSION" ]; then
138
+ echo "::error::could not read the astral-sh/uv-pre-commit version from .pre-commit-config.yaml"
139
+ exit 1
140
+ fi
141
+ echo "UV_VERSION=$UV_VERSION" >> "$GITHUB_ENV"
142
+ echo "uv version: $UV_VERSION"
143
+
144
+ - name: install uv
145
+ run: python -m pip install "uv==${UV_VERSION}"
146
+
147
+ - name: uv build (wheel + sdist)
148
+ run: uv build
149
+
150
+ # `sha256sum -c SHA256SUMS.txt`-verifiable, and with no dist/ prefix in
151
+ # it, so it checks out wherever the assets are downloaded to. Globs are
152
+ # listed explicitly rather than `./*` so the output file can never end up
153
+ # listing itself.
154
+ - name: Compute SHA-256 checksums
155
+ working-directory: dist
156
+ run: |
157
+ sha256sum ./*.whl ./*.tar.gz > SHA256SUMS.txt
158
+ cat SHA256SUMS.txt
159
+
160
+ # Release notes: GitHub's own generated notes (same content the Releases
161
+ # UI would produce) with the checksums appended, so the hashes are
162
+ # readable in the release body as well as downloadable as an asset. The
163
+ # notes are built here instead of passing --generate-notes to `gh release
164
+ # create` so the appended block is not at the mercy of how that flag
165
+ # combines with --notes.
166
+ - name: Build release notes
167
+ env:
168
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
169
+ VERSION: ${{ needs.version.outputs.version }}
170
+ run: |
171
+ notes_file="${RUNNER_TEMP}/release-notes.md"
172
+ if ! gh api "repos/${GITHUB_REPOSITORY}/releases/generate-notes" \
173
+ --method POST \
174
+ -f "tag_name=v${VERSION}" \
175
+ -f "target_commitish=${GITHUB_SHA}" \
176
+ --jq '.body' > "$notes_file"; then
177
+ echo "::warning::could not generate release notes; falling back to a plain body"
178
+ printf 'Release v%s\n' "${VERSION}" > "$notes_file"
179
+ fi
180
+ # SC2016 fires on the backticks below, but they are markdown code
181
+ # spans destined for the release body, not command substitutions --
182
+ # single quotes are what keeps them literal. The suggested fix
183
+ # (double quotes) would mean escaping every one of them for no gain.
184
+ # Scoped to this group so the rest of the script keeps the check.
185
+ # shellcheck disable=SC2016
186
+ {
187
+ printf '\n## SHA-256\n\n'
188
+ printf 'Verify with `sha256sum -c SHA256SUMS.txt`:\n\n'
189
+ printf '```\n'
190
+ cat dist/SHA256SUMS.txt
191
+ printf '```\n'
192
+ } >> "$notes_file"
193
+ echo "NOTES_FILE=$notes_file" >> "$GITHUB_ENV"
194
+ cat "$notes_file"
195
+
196
+ # `gh release create --target` creates the tag itself, so this needs no
197
+ # git push and the checkout above can stay credential-less. Using the gh
198
+ # CLI (preinstalled on the runner) also means one less third-party action
199
+ # to pin and keep updated.
200
+ - name: Create the GitHub release
201
+ env:
202
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
203
+ VERSION: ${{ needs.version.outputs.version }}
204
+ run: |
205
+ gh release create "v${VERSION}" \
206
+ --target "${GITHUB_SHA}" \
207
+ --title "v${VERSION}" \
208
+ --notes-file "${NOTES_FILE}" \
209
+ dist/*.whl dist/*.tar.gz dist/SHA256SUMS.txt
210
+
211
+ # Inert until all of these are true, so nothing can publish by accident:
212
+ # 1. a PyPI trusted publisher exists for this repo with workflow name
213
+ # `tag_and_release.yaml` and environment name `pypi`, matching the
214
+ # `environment:` above (https://docs.pypi.org/trusted-publishers/)
215
+ # 2. the repository variable PYPI_PUBLISH is set to `true`
216
+ # (Settings > Secrets and variables > Actions > Variables)
217
+ # 3. whatever protection rules the `pypi` environment carries have been
218
+ # satisfied - those gate this entire job, tagging included
219
+ # `uv publish` speaks OIDC natively given the id-token: write permission
220
+ # above, so there is no long-lived API token to store and no
221
+ # pypa/gh-action-pypi-publish pin to maintain. The release is already
222
+ # created at this point: a failure here leaves the GitHub release intact
223
+ # and is re-run by hand, not by re-running the whole workflow.
224
+ - name: Publish to PyPI (trusted publishing)
225
+ if: vars.PYPI_PUBLISH == 'true'
226
+ # the explicit globs keep SHA256SUMS.txt (which lives in dist/ too) out
227
+ # of the upload; uv publish would otherwise take everything in dist/
228
+ run: uv publish --trusted-publishing always dist/*.whl dist/*.tar.gz
@@ -0,0 +1,57 @@
1
+ name: test
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+ # lets tag_and_release.yaml gate the release on this same job via `uses:`
9
+ workflow_call:
10
+
11
+ concurrency:
12
+ group: ${{ github.workflow }}-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ test:
20
+ name: py${{ matrix.python-version }} on ${{ matrix.os }}
21
+ runs-on: ${{ matrix.os }}
22
+ strategy:
23
+ fail-fast: false
24
+ matrix:
25
+ os: [ubuntu-latest]
26
+ python-version: ["3.11", "3.12", "3.15"]
27
+ include:
28
+ - os: macos-latest
29
+ python-version: "3.12"
30
+ - os: windows-latest
31
+ python-version: "3.12"
32
+
33
+ steps:
34
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
35
+ with:
36
+ persist-credentials: false
37
+
38
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
39
+ with:
40
+ enable-cache: true
41
+
42
+ # --frozen resolves from the committed lockfile. That matters because
43
+ # [tool.uv] exclude-newer is a rolling 7-day window: re-resolving here
44
+ # would drift from what was locked.
45
+ - name: Install
46
+ run: uv sync --frozen --python ${{ matrix.python-version }}
47
+
48
+ - name: Lint
49
+ run: uv run ruff check .
50
+
51
+ - name: Type-check
52
+ run: uv run mypy src
53
+
54
+ # Tests needing a real BigFix server or local openssl are marked and
55
+ # auto-skip here (see tests/conftest.py).
56
+ - name: Test
57
+ run: uv run pytest -q -rs