pytest-selective 0.2.0__tar.gz → 0.4.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 (176) hide show
  1. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/test-lanes.json +5 -6
  2. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/workflows/ci.yml +43 -16
  3. pytest_selective-0.4.0/.github/workflows/docs.yml +30 -0
  4. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/workflows/observe-ci.yml +2 -1
  5. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/workflows/public-actions.yml +21 -1
  6. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/workflows/release.yml +2 -1
  7. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.gitignore +4 -0
  8. pytest_selective-0.4.0/.readthedocs.yaml +11 -0
  9. pytest_selective-0.4.0/.release-please-manifest.json +3 -0
  10. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/AGENTS.md +13 -2
  11. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/CHANGELOG.md +30 -0
  12. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/CONTRIBUTING.md +35 -6
  13. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/PKG-INFO +21 -14
  14. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/README.md +19 -12
  15. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/RELEASING.md +11 -4
  16. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/action.yml +9 -5
  17. pytest_selective-0.4.0/actions/README.md +13 -0
  18. {pytest_selective-0.2.0/.github → pytest_selective-0.4.0}/actions/plan-lanes/action.yml +5 -5
  19. {pytest_selective-0.2.0/.github → pytest_selective-0.4.0}/actions/pytest-expansion/action.yml +1 -1
  20. {pytest_selective-0.2.0/.github → pytest_selective-0.4.0}/actions/test-impact/action.yml +10 -6
  21. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/README.md +1 -0
  22. pytest_selective-0.4.0/docs/actions.md +45 -0
  23. pytest_selective-0.4.0/docs/assets/banner.png +0 -0
  24. pytest_selective-0.4.0/docs/assets/banner.svg +28 -0
  25. pytest_selective-0.4.0/docs/assets/brand.json +13 -0
  26. pytest_selective-0.4.0/docs/assets/icon.png +0 -0
  27. pytest_selective-0.4.0/docs/assets/logo.svg +10 -0
  28. pytest_selective-0.4.0/docs/assets/raster-sources.json +9 -0
  29. pytest_selective-0.4.0/docs/assets/social-preview.png +0 -0
  30. pytest_selective-0.4.0/docs/assets/social-preview.svg +30 -0
  31. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22.md +1 -1
  32. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/ci-toolkit.md +4 -2
  33. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/ci.md +66 -19
  34. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/comparison-pytest-impacted.md +4 -4
  35. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/configuration.md +8 -3
  36. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/evidence.md +3 -1
  37. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/selection-health.md +2 -1
  38. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/tutorial.md +40 -1
  39. pytest_selective-0.4.0/docs/tutorials/adoption-checklist.md +244 -0
  40. pytest_selective-0.4.0/docs/tutorials/sidecar-dependencies.md +270 -0
  41. pytest_selective-0.4.0/docs/tutorials/skip-unrelated-ci.md +138 -0
  42. pytest_selective-0.4.0/docs/work-in-progress/tickets/actions-directory-test-plan.md +10 -0
  43. pytest_selective-0.4.0/docs/work-in-progress/tickets/move-action-implementations-test-plan.md +10 -0
  44. pytest_selective-0.4.0/documentation/assets/routing-comparison.svg +1 -0
  45. pytest_selective-0.4.0/documentation/check_site.py +77 -0
  46. pytest_selective-0.4.0/documentation/ecosystem.md +31 -0
  47. pytest_selective-0.4.0/documentation/hooks.py +76 -0
  48. pytest_selective-0.4.0/documentation/index.md +72 -0
  49. pytest_selective-0.4.0/documentation/overrides/main.html +14 -0
  50. pytest_selective-0.4.0/documentation/publishing.md +107 -0
  51. pytest_selective-0.4.0/documentation/requirements.in +2 -0
  52. pytest_selective-0.4.0/documentation/requirements.txt +562 -0
  53. pytest_selective-0.4.0/mkdocs.yml +112 -0
  54. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/pyproject.toml +2 -2
  55. pytest_selective-0.4.0/scripts/ci_file_config.py +20 -0
  56. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/public_actions.py +4 -6
  57. pytest_selective-0.4.0/scripts/render_brand.py +140 -0
  58. pytest_selective-0.4.0/scripts/run_ci_tests.py +40 -0
  59. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/tutorial.py +3 -0
  60. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/skills/pytest-selective/SKILL.md +16 -5
  61. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/skills/pytest-selective/references/adoption.md +8 -3
  62. pytest_selective-0.4.0/src/pytest_selective/checkpoint.py +44 -0
  63. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/ci.py +16 -4
  64. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_cli.py +7 -1
  65. pytest_selective-0.4.0/tests/test_checkpoint_policy.py +106 -0
  66. pytest_selective-0.4.0/tests/test_ci_admission.py +64 -0
  67. pytest_selective-0.4.0/tests/test_ci_test_execution.py +71 -0
  68. pytest_selective-0.4.0/tests/test_public_actions.py +34 -0
  69. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/test_pytest_expansion.py +4 -1
  70. pytest_selective-0.4.0/tests/test_repository_ci.py +147 -0
  71. pytest_selective-0.4.0/tests/test_repository_hygiene.py.gv-dependency.yaml +4 -0
  72. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/test_tutorial.py +2 -0
  73. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_ci.py +86 -1
  74. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_impact_explanation.py +2 -2
  75. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_impact_graph.py +9 -9
  76. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_pytest_plugin.py +3 -0
  77. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_working_tree.py +3 -0
  78. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/uv.lock +1 -1
  79. pytest_selective-0.2.0/.release-please-manifest.json +0 -3
  80. pytest_selective-0.2.0/docs/actions.md +0 -42
  81. pytest_selective-0.2.0/docs/pytest-impacted.md +0 -69
  82. pytest_selective-0.2.0/plan-lanes/action.yml +0 -33
  83. pytest_selective-0.2.0/pytest-expansion/action.yml +0 -35
  84. pytest_selective-0.2.0/test-impact/action.yml +0 -106
  85. pytest_selective-0.2.0/tests/test_public_actions.py +0 -30
  86. pytest_selective-0.2.0/tests/test_repository_ci.py +0 -48
  87. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.gitattributes +0 -0
  88. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  89. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  90. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/dependabot.yml +0 -0
  91. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/workflows/pr-title.yml +0 -0
  92. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/workflows/release-please.yml +0 -0
  93. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.github/workflows/windows-performance.yml +0 -0
  94. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/.pre-commit-config.yaml +0 -0
  95. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/CLAUDE.md +0 -0
  96. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/LICENSE +0 -0
  97. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/PROVENANCE.md +0 -0
  98. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/agentsync.toml +0 -0
  99. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/agents.md +0 -0
  100. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22-due-ci.json +0 -0
  101. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22-due-docs-ci.json +0 -0
  102. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22-due-docs-widget.json +0 -0
  103. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22-due-widget.json +0 -0
  104. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22-input-replays.json +0 -0
  105. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22-obligation-docs.json +0 -0
  106. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22-obligation.json +0 -0
  107. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22-routing.md +0 -0
  108. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-22-selective-docs.json +0 -0
  109. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-23-windows-saleor/obligation-baseline.json +0 -0
  110. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.11.xml +0 -0
  111. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.14.xml +0 -0
  112. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-after.json +0 -0
  113. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.11.xml +0 -0
  114. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.14.xml +0 -0
  115. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-control.json +0 -0
  116. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-earlier.json +0 -0
  117. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/2026-10-23-windows-saleor.md +0 -0
  118. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/benchmarks/windows-runtime.md +0 -0
  119. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/local-development.md +0 -0
  120. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/pytest-hygiene.md +0 -0
  121. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/work-in-progress/tickets/codex-selector-correctness-performance-test-plan.md +0 -0
  122. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/work-in-progress/tickets/codex-windows-git-performance-test-plan.md +0 -0
  123. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/work-in-progress/tickets/impacted-improvements-test-plan.md +0 -0
  124. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/docs/work-in-progress/tickets/public-action-onboarding-test-plan.md +0 -0
  125. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/release-please-config.json +0 -0
  126. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/benchmark_graph.py +0 -0
  127. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/benchmark_parsing.py +0 -0
  128. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/benchmark_rust.py +0 -0
  129. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/check_docs.py +0 -0
  130. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/check_metadata.py +0 -0
  131. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/compare_impacted.py +0 -0
  132. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/measure_ci_runs.py +0 -0
  133. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/scripts/smoke_distribution.py +0 -0
  134. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/skills/pytest-selective/agents/openai.yaml +0 -0
  135. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/__init__.py +0 -0
  136. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/__main__.py +0 -0
  137. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/ast_imports.py +0 -0
  138. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/hygiene.py +0 -0
  139. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_audit.py +0 -0
  140. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_audit_plugin.py +0 -0
  141. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_declarations.py +0 -0
  142. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_explanation.py +0 -0
  143. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_first_party.py +0 -0
  144. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_graph.py +0 -0
  145. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_models.py +0 -0
  146. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_name_scope.py +0 -0
  147. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/impact_selection.py +0 -0
  148. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/input_policy.py +0 -0
  149. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/local.py +0 -0
  150. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/parse_batch.py +0 -0
  151. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/plugin.py +0 -0
  152. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/py.typed +0 -0
  153. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/pytest_expansion.py +0 -0
  154. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/pytest_plugins.py +0 -0
  155. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/pytest_sharding.py +0 -0
  156. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/test_inventory.py +0 -0
  157. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/typecheck_scope.py +0 -0
  158. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/src/pytest_selective/working_tree.py +0 -0
  159. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/__init__.py +0 -0
  160. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/test_ci_measurements.py +0 -0
  161. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/test_distribution_metadata.py +0 -0
  162. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/test_hygiene.py +0 -0
  163. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/test_repository_hygiene.py +0 -0
  164. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/__init__.py +0 -0
  165. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/git_repo.py +0 -0
  166. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_ast_imports.py +0 -0
  167. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_git_repo.py +0 -0
  168. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_global_inputs.py +0 -0
  169. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_impact_audit.py +0 -0
  170. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_impact_first_party.py +0 -0
  171. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_impact_name_scope.py +0 -0
  172. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_parse_batch.py +0 -0
  173. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_portability.py +0 -0
  174. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_pytest_plugins.py +0 -0
  175. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_pytest_sharding.py +0 -0
  176. {pytest_selective-0.2.0 → pytest_selective-0.4.0}/tests/testing/test_typecheck_scope.py +0 -0
@@ -18,14 +18,14 @@
18
18
  ],
19
19
  "inputs": [
20
20
  "src/**",
21
- "scripts/**",
22
- "tests/**",
23
- ".pre-commit-config.yaml",
24
- ".python-version"
21
+ "tests/**"
25
22
  ]
26
23
  }
27
24
  },
28
25
  "global_inputs": [
26
+ "scripts/**",
27
+ ".pre-commit-config.yaml",
28
+ ".python-version",
29
29
  "**/pyproject.toml",
30
30
  "pyproject.toml",
31
31
  "**/uv.lock",
@@ -33,9 +33,8 @@
33
33
  ".github/test-lanes.json",
34
34
  ".github/workflows/ci.yml",
35
35
  ".github/workflows/release.yml",
36
- ".github/actions/**",
36
+ "actions/**",
37
37
  "action.yml",
38
- "*/action.yml",
39
38
  "examples/**",
40
39
  ".github/workflows/public-actions.yml"
41
40
  ]
@@ -17,31 +17,40 @@ jobs:
17
17
  runs-on: ubuntu-latest
18
18
  outputs:
19
19
  lanes: ${{ steps.plan.outputs.lanes }}
20
+ mode: ${{ steps.files.outputs.mode }}
21
+ files: ${{ steps.files.outputs.test_roots_json }}
20
22
  steps:
21
23
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22
24
  with:
23
25
  fetch-depth: 0
24
26
  - id: plan
25
- uses: ./plan-lanes
27
+ uses: ./actions/plan-lanes
26
28
  with:
27
29
  config: .github/test-lanes.json
28
- base: ${{ github.event.pull_request.base.sha || github.event.before }}
29
- full: ${{ github.run_attempt > 1 || github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'test:full') }}
30
+ - name: Share the repository graph and execution inputs with file selection
31
+ env:
32
+ PYTHONPATH: src
33
+ run: |
34
+ uv run --no-project --python 3.14 --with pydantic==2.13.4 --with pyyaml==6.0.3 \
35
+ python scripts/ci_file_config.py "$RUNNER_TEMP/test-impact.json"
36
+ - id: files
37
+ uses: ./
38
+ with:
39
+ config: ${{ runner.temp }}/test-impact.json
40
+ full-roots: tests
30
41
  quality:
31
42
  runs-on: ubuntu-latest
32
43
  steps:
33
44
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
34
- - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
45
+ - uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
35
46
  with:
36
47
  python-version: '3.14'
37
48
  - run: uv run --locked pre-commit run --all-files
38
49
  - name: Check aggregate gate against the execution lanes
39
50
  run: >-
40
51
  uv run --no-project --python 3.14
41
- --with "ci-esta>=0.1.0,<0.2.0"
52
+ --with "ci-esta>=1.1.0,<2.0.0"
42
53
  ci-esta check-workflow --workflow .github/workflows/ci.yml --lanes .github/test-lanes.json
43
- - name: Validate routing even when the platform matrix is skipped
44
- run: uv run --locked pytest -q tests/test_repository_ci.py
45
54
  - name: Validate GitHub Actions
46
55
  run: docker run --rm -v "$PWD:/repo" -w /repo rhysd/actionlint:1.7.7 -color
47
56
  tests:
@@ -57,20 +66,26 @@ jobs:
57
66
  runs-on: ${{ matrix.os }}
58
67
  steps:
59
68
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
60
- - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
69
+ - uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
61
70
  with:
62
71
  python-version: ${{ matrix.python }}
63
72
  - name: Use native Git for Windows
64
- uses: gigaverse-app/ci-esta/.github/actions/native-windows-git@v0.1
73
+ uses: gigaverse-app/ci-esta/actions/native-windows-git@v1
65
74
  - name: Record coverage runtime
66
75
  run: uv run --locked python -m coverage --version
67
- - run: uv run --locked pytest -q -n 4 --durations=20 --junitxml=test-timings.xml --cov --cov-report=term-missing --cov-report=xml
76
+ - name: Execute the shared affected-file plan
77
+ run: uv run --locked python scripts/run_ci_tests.py -q -n 4 --durations=20 --junitxml=test-timings.xml
68
78
  env:
79
+ CI_PLANNER_RESULT: ${{ needs.select-tests.result }}
80
+ CI_TEST_MODE: ${{ needs.select-tests.outputs.mode }}
81
+ CI_TEST_FILES: ${{ needs.select-tests.outputs.files }}
82
+ CI_COVERAGE: 'true'
69
83
  # Keep temporary Git repositories beside the checkout on the work disk.
70
84
  TMP: ${{ runner.temp }}
71
85
  TEMP: ${{ runner.temp }}
72
86
  TMPDIR: ${{ runner.temp }}
73
- - uses: gigaverse-app/ci-esta/.github/actions/learn-test-timings@v0.1
87
+ - uses: gigaverse-app/ci-esta/actions/learn-test-timings@v1
88
+ if: ${{ hashFiles('test-timings.xml') != '' }}
74
89
  with:
75
90
  junit-pattern: test-timings.xml
76
91
  artifact-name: test-timings-${{ matrix.python }}-${{ matrix.os }}
@@ -89,22 +104,34 @@ jobs:
89
104
  runs-on: ubuntu-latest
90
105
  steps:
91
106
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
92
- - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
107
+ - uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
93
108
  with:
94
109
  python-version: '3.11'
95
110
  - run: uv pip install 'pytest==8.0.0'
96
- - run: uv run --no-sync pytest -q -n 4 --durations=20
111
+ - name: Execute the same file plan on minimum pytest
112
+ run: uv run --no-sync python scripts/run_ci_tests.py -q -n 4 --durations=20
113
+ env:
114
+ CI_PLANNER_RESULT: ${{ needs.select-tests.result }}
115
+ CI_TEST_MODE: ${{ needs.select-tests.outputs.mode }}
116
+ CI_TEST_FILES: ${{ needs.select-tests.outputs.files }}
97
117
  distributions:
118
+ needs: select-tests
119
+ # README changes still need build/metadata checks; planner failure must not skip them.
120
+ if: ${{ !cancelled() }}
98
121
  runs-on: ubuntu-latest
99
122
  steps:
100
123
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
101
- - uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
124
+ - uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
102
125
  with:
103
126
  python-version: '3.14'
104
127
  - run: uv build
105
128
  - run: uv run --locked twine check --strict dist/*
106
129
  - run: uv run --locked python scripts/check_metadata.py
107
- - run: uv run --locked python scripts/smoke_distribution.py
130
+ - name: Smoke installed distributions when runtime inputs change
131
+ if: >-
132
+ ${{ needs.select-tests.result != 'success' ||
133
+ fromJSON(needs.select-tests.outputs.lanes).tests }}
134
+ run: uv run --locked python scripts/smoke_distribution.py
108
135
  - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
109
136
  with:
110
137
  name: distributions
@@ -117,7 +144,7 @@ jobs:
117
144
  if: ${{ !cancelled() }}
118
145
  runs-on: ubuntu-latest
119
146
  steps:
120
- - uses: gigaverse-app/ci-esta/.github/actions/validation-gate@v0.1
147
+ - uses: gigaverse-app/ci-esta/actions/validation-gate@v1
121
148
  with:
122
149
  needs: ${{ toJSON(needs) }}
123
150
  lanes: ${{ needs.select-tests.outputs.lanes || '{}' }}
@@ -0,0 +1,30 @@
1
+ name: Documentation
2
+ on:
3
+ pull_request:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+ permissions:
8
+ contents: read
9
+ concurrency:
10
+ group: docs-${{ github.event.pull_request.number || github.ref }}
11
+ cancel-in-progress: true
12
+ jobs:
13
+ docs:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
17
+ - uses: actions/setup-python@v6
18
+ with:
19
+ python-version: '3.13'
20
+ cache: pip
21
+ cache-dependency-path: documentation/requirements.txt
22
+ - run: python -m pip install -r documentation/requirements.txt
23
+ - run: python scripts/render_brand.py --check
24
+ - run: python -m mkdocs build --strict
25
+ - run: python documentation/check_site.py
26
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
27
+ with:
28
+ name: documentation-site
29
+ path: site/
30
+ if-no-files-found: error
@@ -13,7 +13,7 @@ permissions:
13
13
 
14
14
  jobs:
15
15
  report:
16
- uses: gigaverse-app/ci-esta/.github/workflows/report.yml@v0.3.0
16
+ uses: gigaverse-app/ci-esta/.github/workflows/report.yml@v1
17
17
  with:
18
18
  run-id: ${{ github.event.workflow_run.id }}
19
19
  run-attempt: ${{ github.event.workflow_run.run_attempt }}
@@ -22,3 +22,4 @@ jobs:
22
22
  post-sticky: true
23
23
  required-gates-json: '[{"kind":"actions_job","job_name":"Validation gate"}]'
24
24
  analyze-critical-path: true
25
+ test-selection-artifact: test-impact-explanation
@@ -7,7 +7,24 @@ on:
7
7
  permissions:
8
8
  contents: read
9
9
  jobs:
10
+ select-tests:
11
+ runs-on: ubuntu-latest
12
+ outputs:
13
+ lanes: ${{ steps.select.outputs.lanes }}
14
+ steps:
15
+ - uses: actions/checkout@v7
16
+ with:
17
+ fetch-depth: 0
18
+ - id: select
19
+ uses: ./actions/plan-lanes
20
+ with:
21
+ config: .github/test-lanes.json
22
+ artifact-name: public-action-selection
10
23
  public-actions:
24
+ needs: select-tests
25
+ if: >-
26
+ ${{ !cancelled() && (needs.select-tests.result != 'success' ||
27
+ fromJSON(needs.select-tests.outputs.lanes).tests) }}
11
28
  runs-on: ubuntu-latest
12
29
  steps:
13
30
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
@@ -37,7 +54,7 @@ jobs:
37
54
  run: |
38
55
  test "$MODE" = full
39
56
  test -n "$ROOTS"
40
- - uses: ./plan-lanes
57
+ - uses: ./actions/plan-lanes
41
58
  id: lanes
42
59
  with:
43
60
  config: .github/test-lanes.json
@@ -52,3 +69,6 @@ jobs:
52
69
  import json, os
53
70
  assert json.loads(os.environ['LANES']) == {'tests': True}
54
71
  PY
72
+ - name: Require successful planning after fallback execution
73
+ if: ${{ !cancelled() && needs.select-tests.result != 'success' }}
74
+ run: exit 1
@@ -54,7 +54,8 @@ jobs:
54
54
  if [[ ! "$RELEASE_TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
55
55
  exit 0
56
56
  fi
57
- alias="v${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
57
+ # The Actions API has its own major, independent of the Python package.
58
+ alias="v1"
58
59
  if gh api "repos/$GH_REPO/git/ref/tags/$alias" --silent; then
59
60
  gh api --method PATCH "repos/$GH_REPO/git/refs/tags/$alias" \
60
61
  -f sha="$RELEASE_SHA" -F force=true --silent
@@ -11,3 +11,7 @@ dist/
11
11
  coverage.xml
12
12
  htmlcov/
13
13
  tutorial-report.json
14
+
15
+ # Built documentation
16
+ /site/
17
+ /.venv-docs/
@@ -0,0 +1,11 @@
1
+ version: 2
2
+ build:
3
+ os: ubuntu-24.04
4
+ tools:
5
+ python: "3.13"
6
+ python:
7
+ install:
8
+ - requirements: documentation/requirements.txt
9
+ mkdocs:
10
+ configuration: mkdocs.yml
11
+ fail_on_warning: true
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.4.0"
3
+ }
@@ -14,8 +14,8 @@ on pytest-selective itself.
14
14
  - Planning supports committed revisions and explicit working-tree snapshots. Preserve full execution on
15
15
  operational uncertainty and diagnostics for invalid declarations. An empty
16
16
  selection is not an empty pytest argument list.
17
- - Keep consumer routing regressions in the always-running quality job. Update
18
- `.github/test-lanes.json` when adding execution inputs; preserve full main/manual
17
+ - Select consumer routing regressions by their declared execution/configuration inputs. Update
18
+ `.github/test-lanes.json` when adding execution inputs; preserve explicit full/manual
19
19
  checkpoints and the `test:full` override.
20
20
  - The README's performance numbers are scenario-specific observations. Keep
21
21
  claims linked to [raw evidence](docs/benchmarks/2026-10-22-routing.md); distinguish
@@ -56,3 +56,14 @@ npx --yes @dallay/agentsync@1.52.3 status
56
56
  ```
57
57
 
58
58
  Keep the symlink tracked in Git. See CONTRIBUTING.md for platform setup.
59
+
60
+ ## Documentation-only CI
61
+
62
+ Documentation-only PRs execute zero tests unless a test or lane explicitly
63
+ declares that documentation as an input. This includes CI contract tests,
64
+ installed-wheel smoke and public-action smoke. Metadata/link/build checks may
65
+ still validate documentation without running runtime tests. Declare execution
66
+ workflows, selector configuration, helpers, locks and non-import inputs; missing
67
+ history or failed planning must execute the full affected lanes and fail the
68
+ required planning gate. Ordinary PRs and pushes use selection; manual/release/scheduled/full overrides
69
+ remain complete checkpoints.
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.0](https://github.com/gigaverse-app/pytest-selective/compare/v0.3.0...v0.4.0) (2026-10-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * **actions:** simplify selection adoption with shared defaults ([#63](https://github.com/gigaverse-app/pytest-selective/issues/63)) ([85e082d](https://github.com/gigaverse-app/pytest-selective/commit/85e082dfdbcf2f8c02ac3de38613c818cb749807))
9
+
10
+ ## [0.3.0](https://github.com/gigaverse-app/pytest-selective/compare/v0.2.0...v0.3.0) (2026-10-23)
11
+
12
+
13
+ ### ⚠ BREAKING CHANGES
14
+
15
+ * **actions:** named action callers upgrading from older layouts must replace `.github/actions/NAME` or `NAME` with `actions/NAME` and select a revision containing that path.
16
+
17
+ ### Features
18
+
19
+ * **actions:** group public entry points under actions directory ([#44](https://github.com/gigaverse-app/pytest-selective/issues/44)) ([236aefc](https://github.com/gigaverse-app/pytest-selective/commit/236aefc83d9f0ee1696a5ffa29fc83cbcc4a53dc))
20
+
21
+
22
+ ### Bug fixes
23
+
24
+ * **ci:** dogfood dependency-based test selection ([#57](https://github.com/gigaverse-app/pytest-selective/issues/57)) ([76afb69](https://github.com/gigaverse-app/pytest-selective/commit/76afb69cea84681bd661ec2bfff7be857b434129))
25
+ * **ci:** select all runtime tests by declared dependencies ([9673e50](https://github.com/gigaverse-app/pytest-selective/commit/9673e50dd8a709db9347d2e325da242aca96cece))
26
+ * **docs:** refresh cached artwork when branding changes ([5726530](https://github.com/gigaverse-app/pytest-selective/commit/5726530a445099e7cf24a1a7a89016fed0270308))
27
+
28
+
29
+ ### Refactoring
30
+
31
+ * **actions:** move implementations into the public actions directory ([#46](https://github.com/gigaverse-app/pytest-selective/issues/46)) ([bd5aae3](https://github.com/gigaverse-app/pytest-selective/commit/bd5aae32176ae83b121d2353f40b562642184cd8))
32
+
3
33
  ## [0.2.0](https://github.com/gigaverse-app/pytest-selective/compare/v0.1.1...v0.2.0) (2026-10-23)
4
34
 
5
35
 
@@ -54,14 +54,32 @@ limitations. The pull request template provides a short checklist. See
54
54
  ## CI lane selection
55
55
 
56
56
  This repository uses its own `plan-lanes` action. Documentation-only PRs keep
57
- quality checks (including Markdown links) and distribution build/install checks,
58
- while skipping the six-platform pytest matrix and minimum-pytest lane. Source,
59
- tests, scripts, dependency/pytest policy and workflow changes run the complete
60
- matrix. Main, manual/called runs and the `test:full` label run it in full; a
61
- failed planner also runs all tests. Repository routing controls exercise the
62
- committed config against real Git trees, including full and missing-history
57
+ quality checks (including Markdown links) and distribution build/metadata checks,
58
+ while skipping the six-platform pytest matrix and minimum-pytest lane. Within an
59
+ admitted lane, the repository's public file-selection action selects affected
60
+ test files once; the platform matrix and minimum-pytest job execute that same
61
+ plan. CI-esta receives both lane and file explanations, learns JUnit timings,
62
+ and validates the aggregate gate. Source and test edits follow dependencies;
63
+ scripts, dependency/pytest policy and execution workflow changes retain full
64
+ validation. Manual/called/release runs and the `test:full` label run it in full; a
65
+ failed planner also runs all tests. Installed-distribution smoke checks use the
66
+ same runtime-input decision; README-only changes skip those checks while still
67
+ verifying the README embedded in both release archives. Repository routing
68
+ controls exercise the committed config against real Git trees, including full and missing-history
63
69
  controls. Add new non-import execution inputs to `.github/test-lanes.json`.
64
70
 
71
+ File planning derives its graph from that same lane config and merges its declared
72
+ global execution inputs with the graph's environment inputs. Declare subprocess
73
+ and non-import dependencies at their readers. Full plans collect whole-suite
74
+ coverage; scoped plans produce JUnit timing evidence without presenting partial
75
+ coverage as a whole-suite result. The small execution wrapper only consumes the
76
+ public action's JSON file list: it does not implement another selector.
77
+ The outer pytest process disables the selective plugin to avoid a second planner
78
+ and a hidden dependency of every test on plugin startup. Plugin integration tests
79
+ still load it normally in subprocesses and declare that dependency explicitly.
80
+ Missing or failed planning runs complete roots, and an empty successful plan never starts
81
+ pytest. The aggregate gate still fails when planning fails.
82
+
65
83
  ## Conventional Commits
66
84
 
67
85
  Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
@@ -123,3 +141,14 @@ the Linux filesystem. See the
123
141
  [Windows setup guide](https://dallay.github.io/agentsync/guides/windows-symlink-setup/).
124
142
  If AgentSync backs up an existing `CLAUDE.md`, review and preserve any unique
125
143
  guidance in `AGENTS.md`; do not commit the backup as another instruction source.
144
+
145
+ ## Documentation-only CI
146
+
147
+ Documentation-only PRs execute zero tests unless a test or lane explicitly
148
+ declares that documentation as an input. This includes CI contract tests,
149
+ installed-wheel smoke and public-action smoke. Metadata/link/build checks may
150
+ still validate documentation without running runtime tests. Declare execution
151
+ workflows, selector configuration, helpers, locks and non-import inputs; missing
152
+ history or failed planning must execute the full affected lanes and fail the
153
+ required planning gate. Ordinary PRs and pushes use selection; manual/release/scheduled/full overrides
154
+ remain complete checkpoints.
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pytest-selective
3
- Version: 0.2.0
3
+ Version: 0.4.0
4
4
  Summary: Explainable Python test impact analysis: select affected pytest files from Git changes
5
5
  Project-URL: Homepage, https://github.com/gigaverse-app/pytest-selective
6
- Project-URL: Documentation, https://github.com/gigaverse-app/pytest-selective/blob/main/docs/README.md
6
+ Project-URL: Documentation, https://pytest-selective.readthedocs.io/en/latest/
7
7
  Project-URL: Repository, https://github.com/gigaverse-app/pytest-selective
8
8
  Project-URL: Issues, https://github.com/gigaverse-app/pytest-selective/issues
9
9
  Project-URL: Changelog, https://github.com/gigaverse-app/pytest-selective/blob/main/CHANGELOG.md
@@ -29,10 +29,9 @@ Provides-Extra: audit
29
29
  Requires-Dist: pytest>=8; extra == 'audit'
30
30
  Description-Content-Type: text/markdown
31
31
 
32
- # pytest-selective
33
-
34
- **Run affected Python tests. See why they matter.**
32
+ ![pytest-selective: Run affected Python tests. See why they matter.](https://raw.githubusercontent.com/gigaverse-app/pytest-selective/main/docs/assets/banner.png?v=17de2a0b7412)
35
33
 
34
+ # pytest-selective
36
35
  [![CI](https://github.com/gigaverse-app/pytest-selective/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/gigaverse-app/pytest-selective/actions/workflows/ci.yml)
37
36
  [![PyPI](https://img.shields.io/pypi/v/pytest-selective)](https://pypi.org/project/pytest-selective/)
38
37
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white)](https://github.com/gigaverse-app/pytest-selective/blob/main/pyproject.toml)
@@ -40,6 +39,11 @@ Description-Content-Type: text/markdown
40
39
  [![Ruff](https://img.shields.io/badge/code%20style-Ruff-D7FF64?logo=ruff&logoColor=black)](https://github.com/gigaverse-app/pytest-selective/blob/main/.pre-commit-config.yaml)
41
40
  [![Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/gigaverse-app/pytest-selective/blob/main/LICENSE)
42
41
  [![Agent skill](https://img.shields.io/badge/Agent_Skill-ready-2563EB)](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/agents.md)
42
+ [![Documentation](https://readthedocs.org/projects/pytest-selective/badge/?version=latest)](https://pytest-selective.readthedocs.io/en/latest/)
43
+
44
+ **Run affected Python tests. See why they matter.**
45
+
46
+ [Read the documentation](https://pytest-selective.readthedocs.io/en/latest/) · [Related tools](https://pytest-selective.readthedocs.io/en/latest/ecosystem/)
43
47
 
44
48
  pytest-selective is a **Python test impact analysis** tool for incremental testing
45
49
  with pytest. It follows dependencies through both sides of a Git change, selects
@@ -47,7 +51,8 @@ the affected test files, and explains the result. Use it directly as a pytest
47
51
  plugin, or plan before collection and service startup with the CLI and CI actions.
48
52
 
49
53
  Built from the selector used in Gigaverse's backend, AI, and shared Python
50
- infrastructure. The API may change before 1.0.
54
+ infrastructure. Use the moving `@v1` Actions tag. The Python package has its own
55
+ version and compatible dependency range.
51
56
  [Provenance and extraction scope](https://github.com/gigaverse-app/pytest-selective/blob/main/PROVENANCE.md).
52
57
 
53
58
  [Quick tutorial](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/tutorial.md) ·
@@ -66,12 +71,15 @@ and slack. [See the source runs and method](https://github.com/gigaverse-app/ci-
66
71
 
67
72
  ## Choose how to use it
68
73
 
74
+ Follow the [adoption tutorial and checklist](docs/tutorials/adoption-checklist.md)
75
+ for local execution, CI routing, dependency audits, timing feedback and measured rollout.
76
+
69
77
  | You want to… | Use | What it saves |
70
78
  | --- | --- | --- |
71
79
  | Test local edits with your existing pytest command | `uv add --dev pytest-selective`, then `uv run pytest --selective` | Unaffected test execution; staged, unstaged and untracked changes are included |
72
80
  | Avoid expensive collection and application imports | `pytest-selective run --config .github/test-impact.json -- -q` | Collection/imports for unaffected files as well as execution |
73
- | Plan affected files in GitHub Actions | `gigaverse-app/pytest-selective@main` | Plans before installing your application |
74
- | Keep whole-suite coverage or conformance checks | `gigaverse-app/pytest-selective/plan-lanes@main` | Entire unaffected jobs, including their services and setup |
81
+ | Plan affected files in GitHub Actions | `gigaverse-app/pytest-selective@v1` | Plans before installing your application |
82
+ | Keep whole-suite coverage or conformance checks | `gigaverse-app/pytest-selective/actions/plan-lanes@v1` | Entire unaffected jobs, including their services and setup |
75
83
  | Check assumptions about JSON, templates and other runtime inputs | Optional file-read recorder and dependency audit | Exposes observed reads missing from the declared graph |
76
84
  | Keep selection narrow as the project grows | Explanations, startup-floor budgets, expansion and isolation guards | Makes broad new fixture/import dependencies visible |
77
85
 
@@ -81,10 +89,9 @@ collects normally; the pre-collection runner and CI planner can avoid that cost.
81
89
  Keep full checkpoints and use complete lanes when partial suites cannot satisfy
82
90
  your coverage contract.
83
91
 
84
- **Public-path availability:** root and short action paths are new on `main`;
85
- existing `v0.1` releases predate them. Evaluate with `@main`, or pin a reviewed
86
- commit containing the public `action.yml`. Adopt a compatible release tag after
87
- it includes these paths. Existing `.github/actions/...` paths remain supported.
92
+ **Public-path availability:** version 1 provides the root action and
93
+ `actions/NAME` paths. Use the moving `@v1` tag for compatible updates.
94
+ Older immutable releases retain their original layouts.
88
95
  [Public action API](docs/actions.md).
89
96
 
90
97
  ## Have your agent set it up
@@ -227,7 +234,7 @@ skip pytest, because invoking pytest without paths runs the whole suite.
227
234
  | A transitive dependency | Import chains and package initialization |
228
235
  | A deleted or renamed module | Dependencies in both the base and head trees |
229
236
  | Fixtures or startup code | Ancestor conftests and configured global modules |
230
- | Templates, schemas, or data files | Reader-owned declarations and YAML sidecars |
237
+ | Templates, schemas, or data files | [Reader-owned declarations and YAML sidecars](docs/tutorials/sidecar-dependencies.md) |
231
238
  | A surprisingly large selection | Dependency paths, startup-floor and blast-radius explanations |
232
239
  | A large CI suite | Cached parsing, graph reuse, and duration-based shard planning |
233
240
  | Undeclared runtime reads | An opt-in pytest recorder and audit command |
@@ -262,7 +269,7 @@ and evidence checks.
262
269
  inspectable JSON plans, runtime dependency audits, and planning before application
263
270
  startup. Both use static dependency analysis; choose
264
271
  based on your workflow, and validate selection against your own suite.
265
- See the [lessons from pytest-impacted](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/pytest-impacted.md)
272
+ See the [comparison with pytest-impacted](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/comparison-pytest-impacted.md)
266
273
  for portability and Git-resolution improvements adopted from that comparison.
267
274
 
268
275
  ## Contribute
@@ -1,7 +1,6 @@
1
- # pytest-selective
2
-
3
- **Run affected Python tests. See why they matter.**
1
+ ![pytest-selective: Run affected Python tests. See why they matter.](https://raw.githubusercontent.com/gigaverse-app/pytest-selective/main/docs/assets/banner.png?v=17de2a0b7412)
4
2
 
3
+ # pytest-selective
5
4
  [![CI](https://github.com/gigaverse-app/pytest-selective/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/gigaverse-app/pytest-selective/actions/workflows/ci.yml)
6
5
  [![PyPI](https://img.shields.io/pypi/v/pytest-selective)](https://pypi.org/project/pytest-selective/)
7
6
  [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white)](https://github.com/gigaverse-app/pytest-selective/blob/main/pyproject.toml)
@@ -9,6 +8,11 @@
9
8
  [![Ruff](https://img.shields.io/badge/code%20style-Ruff-D7FF64?logo=ruff&logoColor=black)](https://github.com/gigaverse-app/pytest-selective/blob/main/.pre-commit-config.yaml)
10
9
  [![Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/gigaverse-app/pytest-selective/blob/main/LICENSE)
11
10
  [![Agent skill](https://img.shields.io/badge/Agent_Skill-ready-2563EB)](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/agents.md)
11
+ [![Documentation](https://readthedocs.org/projects/pytest-selective/badge/?version=latest)](https://pytest-selective.readthedocs.io/en/latest/)
12
+
13
+ **Run affected Python tests. See why they matter.**
14
+
15
+ [Read the documentation](https://pytest-selective.readthedocs.io/en/latest/) · [Related tools](https://pytest-selective.readthedocs.io/en/latest/ecosystem/)
12
16
 
13
17
  pytest-selective is a **Python test impact analysis** tool for incremental testing
14
18
  with pytest. It follows dependencies through both sides of a Git change, selects
@@ -16,7 +20,8 @@ the affected test files, and explains the result. Use it directly as a pytest
16
20
  plugin, or plan before collection and service startup with the CLI and CI actions.
17
21
 
18
22
  Built from the selector used in Gigaverse's backend, AI, and shared Python
19
- infrastructure. The API may change before 1.0.
23
+ infrastructure. Use the moving `@v1` Actions tag. The Python package has its own
24
+ version and compatible dependency range.
20
25
  [Provenance and extraction scope](https://github.com/gigaverse-app/pytest-selective/blob/main/PROVENANCE.md).
21
26
 
22
27
  [Quick tutorial](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/tutorial.md) ·
@@ -35,12 +40,15 @@ and slack. [See the source runs and method](https://github.com/gigaverse-app/ci-
35
40
 
36
41
  ## Choose how to use it
37
42
 
43
+ Follow the [adoption tutorial and checklist](docs/tutorials/adoption-checklist.md)
44
+ for local execution, CI routing, dependency audits, timing feedback and measured rollout.
45
+
38
46
  | You want to… | Use | What it saves |
39
47
  | --- | --- | --- |
40
48
  | Test local edits with your existing pytest command | `uv add --dev pytest-selective`, then `uv run pytest --selective` | Unaffected test execution; staged, unstaged and untracked changes are included |
41
49
  | Avoid expensive collection and application imports | `pytest-selective run --config .github/test-impact.json -- -q` | Collection/imports for unaffected files as well as execution |
42
- | Plan affected files in GitHub Actions | `gigaverse-app/pytest-selective@main` | Plans before installing your application |
43
- | Keep whole-suite coverage or conformance checks | `gigaverse-app/pytest-selective/plan-lanes@main` | Entire unaffected jobs, including their services and setup |
50
+ | Plan affected files in GitHub Actions | `gigaverse-app/pytest-selective@v1` | Plans before installing your application |
51
+ | Keep whole-suite coverage or conformance checks | `gigaverse-app/pytest-selective/actions/plan-lanes@v1` | Entire unaffected jobs, including their services and setup |
44
52
  | Check assumptions about JSON, templates and other runtime inputs | Optional file-read recorder and dependency audit | Exposes observed reads missing from the declared graph |
45
53
  | Keep selection narrow as the project grows | Explanations, startup-floor budgets, expansion and isolation guards | Makes broad new fixture/import dependencies visible |
46
54
 
@@ -50,10 +58,9 @@ collects normally; the pre-collection runner and CI planner can avoid that cost.
50
58
  Keep full checkpoints and use complete lanes when partial suites cannot satisfy
51
59
  your coverage contract.
52
60
 
53
- **Public-path availability:** root and short action paths are new on `main`;
54
- existing `v0.1` releases predate them. Evaluate with `@main`, or pin a reviewed
55
- commit containing the public `action.yml`. Adopt a compatible release tag after
56
- it includes these paths. Existing `.github/actions/...` paths remain supported.
61
+ **Public-path availability:** version 1 provides the root action and
62
+ `actions/NAME` paths. Use the moving `@v1` tag for compatible updates.
63
+ Older immutable releases retain their original layouts.
57
64
  [Public action API](docs/actions.md).
58
65
 
59
66
  ## Have your agent set it up
@@ -196,7 +203,7 @@ skip pytest, because invoking pytest without paths runs the whole suite.
196
203
  | A transitive dependency | Import chains and package initialization |
197
204
  | A deleted or renamed module | Dependencies in both the base and head trees |
198
205
  | Fixtures or startup code | Ancestor conftests and configured global modules |
199
- | Templates, schemas, or data files | Reader-owned declarations and YAML sidecars |
206
+ | Templates, schemas, or data files | [Reader-owned declarations and YAML sidecars](docs/tutorials/sidecar-dependencies.md) |
200
207
  | A surprisingly large selection | Dependency paths, startup-floor and blast-radius explanations |
201
208
  | A large CI suite | Cached parsing, graph reuse, and duration-based shard planning |
202
209
  | Undeclared runtime reads | An opt-in pytest recorder and audit command |
@@ -231,7 +238,7 @@ and evidence checks.
231
238
  inspectable JSON plans, runtime dependency audits, and planning before application
232
239
  startup. Both use static dependency analysis; choose
233
240
  based on your workflow, and validate selection against your own suite.
234
- See the [lessons from pytest-impacted](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/pytest-impacted.md)
241
+ See the [comparison with pytest-impacted](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/comparison-pytest-impacted.md)
235
242
  for portability and Git-resolution improvements adopted from that comparison.
236
243
 
237
244
  ## Contribute
@@ -43,10 +43,17 @@ check out or build source with that permission.
43
43
  `pytest-selective --help` and run the tutorial using that installation.
44
44
 
45
45
  After a normal release publishes successfully, the workflow advances the
46
- compatible Actions tag (for example, `v0.1` for `v0.1.0`). Consumers can use
47
- `@v0.1` to receive patch releases. Package requirements use compatible ranges
48
- such as `pytest-selective>=0.1.0,<0.2.0`; lockfiles retain resolved versions and
49
- artifact hashes. Prereleases do not advance the Actions tag.
46
+ Actions tag `v1`. The Actions API version is independent of the Python package
47
+ version: publishing Python `0.x.y` does not prevent updating Actions `v1`.
48
+ Consumers deliberately use `actions/NAME@v1` as a moving target. Change the
49
+ Actions major only when deliberately establishing a new Actions API line.
50
+ Package requirements use their own compatible ranges, such as
51
+ `pytest-selective>=0.2,<0.3`; lockfiles retain resolved versions and artifact
52
+ hashes. Prereleases do not advance the Actions tag.
53
+
54
+ For an Actions-only publication, advance `v1` to the exact reviewed main commit
55
+ after its complete CI passes. This updates the Git tag without creating a GitHub
56
+ release or invoking PyPI publication. Do not move immutable package release tags.
50
57
 
51
58
  Manual dispatch is available for a version-matching **tag**, not a branch. The
52
59
  workflow intentionally does not skip existing uploads: investigate a partial