pytest-selective 0.1.0__tar.gz → 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.
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/dependabot.yml +4 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/test-lanes.json +5 -1
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/workflows/ci.yml +16 -11
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/workflows/observe-ci.yml +1 -1
- pytest_selective-0.2.0/.github/workflows/pr-title.yml +45 -0
- pytest_selective-0.2.0/.github/workflows/public-actions.yml +54 -0
- pytest_selective-0.2.0/.github/workflows/release-please.yml +54 -0
- pytest_selective-0.2.0/.release-please-manifest.json +3 -0
- pytest_selective-0.2.0/AGENTS.md +58 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/CHANGELOG.md +18 -0
- pytest_selective-0.2.0/CLAUDE.md +1 -0
- pytest_selective-0.2.0/CONTRIBUTING.md +125 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/PKG-INFO +65 -17
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/README.md +63 -16
- pytest_selective-0.2.0/RELEASING.md +114 -0
- pytest_selective-0.2.0/action.yml +106 -0
- pytest_selective-0.2.0/agentsync.toml +18 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/README.md +1 -0
- pytest_selective-0.2.0/docs/actions.md +42 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/agents.md +6 -12
- pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/obligation-baseline.json +6266 -0
- pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.11.xml +1 -0
- pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.14.xml +1 -0
- pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-after.json +2901 -0
- pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.11.xml +1 -0
- pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.14.xml +1 -0
- pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-control.json +2901 -0
- pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor/selective-earlier.json +2901 -0
- pytest_selective-0.2.0/docs/benchmarks/2026-10-23-windows-saleor.md +108 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/ci-toolkit.md +16 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/ci.md +25 -5
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/comparison-pytest-impacted.md +87 -10
- pytest_selective-0.2.0/docs/local-development.md +116 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/pytest-hygiene.md +2 -2
- pytest_selective-0.2.0/docs/selection-health.md +47 -0
- pytest_selective-0.2.0/docs/work-in-progress/tickets/codex-selector-correctness-performance-test-plan.md +16 -0
- pytest_selective-0.2.0/docs/work-in-progress/tickets/public-action-onboarding-test-plan.md +7 -0
- pytest_selective-0.2.0/plan-lanes/action.yml +33 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/pyproject.toml +5 -2
- pytest_selective-0.2.0/pytest-expansion/action.yml +35 -0
- pytest_selective-0.2.0/release-please-config.json +76 -0
- pytest_selective-0.2.0/scripts/benchmark_graph.py +67 -0
- pytest_selective-0.2.0/scripts/benchmark_rust.py +68 -0
- pytest_selective-0.2.0/scripts/public_actions.py +55 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/smoke_distribution.py +17 -2
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/tutorial.py +17 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/skills/pytest-selective/SKILL.md +22 -1
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/skills/pytest-selective/references/adoption.md +16 -2
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_graph.py +100 -60
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_models.py +8 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_selection.py +6 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/local.py +6 -2
- pytest_selective-0.2.0/src/pytest_selective/parse_batch.py +72 -0
- pytest_selective-0.2.0/src/pytest_selective/plugin.py +189 -0
- pytest_selective-0.2.0/src/pytest_selective/pytest_plugins.py +108 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/pytest_sharding.py +10 -0
- pytest_selective-0.2.0/test-impact/action.yml +106 -0
- pytest_selective-0.2.0/tests/test_public_actions.py +30 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_repository_ci.py +2 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/git_repo.py +3 -1
- pytest_selective-0.2.0/tests/testing/test_git_repo.py +24 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_graph.py +27 -0
- pytest_selective-0.2.0/tests/testing/test_parse_batch.py +43 -0
- pytest_selective-0.2.0/tests/testing/test_pytest_plugin.py +198 -0
- pytest_selective-0.2.0/tests/testing/test_pytest_plugins.py +168 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_working_tree.py +2 -2
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/uv.lock +3 -1
- pytest_selective-0.1.0/AGENTS.md +0 -23
- pytest_selective-0.1.0/CONTRIBUTING.md +0 -63
- pytest_selective-0.1.0/RELEASING.md +0 -63
- pytest_selective-0.1.0/docs/local-development.md +0 -51
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.gitattributes +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/actions/plan-lanes/action.yml +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/actions/pytest-expansion/action.yml +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/actions/test-impact/action.yml +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/workflows/release.yml +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.github/workflows/windows-performance.yml +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.gitignore +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/.pre-commit-config.yaml +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/LICENSE +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/PROVENANCE.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-due-ci.json +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-due-docs-ci.json +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-due-docs-widget.json +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-due-widget.json +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-input-replays.json +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-obligation-docs.json +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-obligation.json +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-routing.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22-selective-docs.json +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/2026-10-22.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/benchmarks/windows-runtime.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/configuration.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/evidence.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/pytest-impacted.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/tutorial.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/work-in-progress/tickets/codex-windows-git-performance-test-plan.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/docs/work-in-progress/tickets/impacted-improvements-test-plan.md +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/benchmark_parsing.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/check_docs.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/check_metadata.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/compare_impacted.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/scripts/measure_ci_runs.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/skills/pytest-selective/agents/openai.yaml +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/__init__.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/__main__.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/ast_imports.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/ci.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/hygiene.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_audit.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_audit_plugin.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_cli.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_declarations.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_explanation.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_first_party.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/impact_name_scope.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/input_policy.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/py.typed +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/pytest_expansion.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/test_inventory.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/typecheck_scope.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/src/pytest_selective/working_tree.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/__init__.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_ci_measurements.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_distribution_metadata.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_hygiene.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_pytest_expansion.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_repository_hygiene.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/test_tutorial.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/__init__.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_ast_imports.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_ci.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_global_inputs.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_audit.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_explanation.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_first_party.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_impact_name_scope.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_portability.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_pytest_sharding.py +0 -0
- {pytest_selective-0.1.0 → pytest_selective-0.2.0}/tests/testing/test_typecheck_scope.py +0 -0
|
@@ -2,6 +2,8 @@ version: 2
|
|
|
2
2
|
updates:
|
|
3
3
|
- package-ecosystem: github-actions
|
|
4
4
|
directory: /
|
|
5
|
+
commit-message:
|
|
6
|
+
prefix: ci
|
|
5
7
|
schedule:
|
|
6
8
|
interval: weekly
|
|
7
9
|
groups:
|
|
@@ -9,6 +11,8 @@ updates:
|
|
|
9
11
|
patterns: ["*"]
|
|
10
12
|
- package-ecosystem: uv
|
|
11
13
|
directory: /
|
|
14
|
+
commit-message:
|
|
15
|
+
prefix: build
|
|
12
16
|
schedule:
|
|
13
17
|
interval: weekly
|
|
14
18
|
groups:
|
|
@@ -3,7 +3,7 @@ on:
|
|
|
3
3
|
push:
|
|
4
4
|
branches: [main]
|
|
5
5
|
pull_request:
|
|
6
|
-
types: [opened, synchronize, reopened
|
|
6
|
+
types: [opened, synchronize, reopened]
|
|
7
7
|
workflow_dispatch:
|
|
8
8
|
workflow_call:
|
|
9
9
|
permissions:
|
|
@@ -22,23 +22,23 @@ jobs:
|
|
|
22
22
|
with:
|
|
23
23
|
fetch-depth: 0
|
|
24
24
|
- id: plan
|
|
25
|
-
uses:
|
|
25
|
+
uses: ./plan-lanes
|
|
26
26
|
with:
|
|
27
27
|
config: .github/test-lanes.json
|
|
28
28
|
base: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
29
|
-
full: ${{ github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'test:full') }}
|
|
29
|
+
full: ${{ github.run_attempt > 1 || github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'test:full') }}
|
|
30
30
|
quality:
|
|
31
31
|
runs-on: ubuntu-latest
|
|
32
32
|
steps:
|
|
33
33
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
34
|
-
- uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@
|
|
34
|
+
- uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
|
|
35
35
|
with:
|
|
36
36
|
python-version: '3.14'
|
|
37
37
|
- run: uv run --locked pre-commit run --all-files
|
|
38
38
|
- name: Check aggregate gate against the execution lanes
|
|
39
39
|
run: >-
|
|
40
40
|
uv run --no-project --python 3.14
|
|
41
|
-
--with "ci-esta
|
|
41
|
+
--with "ci-esta>=0.1.0,<0.2.0"
|
|
42
42
|
ci-esta check-workflow --workflow .github/workflows/ci.yml --lanes .github/test-lanes.json
|
|
43
43
|
- name: Validate routing even when the platform matrix is skipped
|
|
44
44
|
run: uv run --locked pytest -q tests/test_repository_ci.py
|
|
@@ -57,15 +57,20 @@ jobs:
|
|
|
57
57
|
runs-on: ${{ matrix.os }}
|
|
58
58
|
steps:
|
|
59
59
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
60
|
-
- uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@
|
|
60
|
+
- uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
|
|
61
61
|
with:
|
|
62
62
|
python-version: ${{ matrix.python }}
|
|
63
63
|
- name: Use native Git for Windows
|
|
64
|
-
uses: gigaverse-app/ci-esta/.github/actions/native-windows-git@
|
|
64
|
+
uses: gigaverse-app/ci-esta/.github/actions/native-windows-git@v0.1
|
|
65
65
|
- name: Record coverage runtime
|
|
66
66
|
run: uv run --locked python -m coverage --version
|
|
67
67
|
- run: uv run --locked pytest -q -n 4 --durations=20 --junitxml=test-timings.xml --cov --cov-report=term-missing --cov-report=xml
|
|
68
|
-
|
|
68
|
+
env:
|
|
69
|
+
# Keep temporary Git repositories beside the checkout on the work disk.
|
|
70
|
+
TMP: ${{ runner.temp }}
|
|
71
|
+
TEMP: ${{ runner.temp }}
|
|
72
|
+
TMPDIR: ${{ runner.temp }}
|
|
73
|
+
- uses: gigaverse-app/ci-esta/.github/actions/learn-test-timings@v0.1
|
|
69
74
|
with:
|
|
70
75
|
junit-pattern: test-timings.xml
|
|
71
76
|
artifact-name: test-timings-${{ matrix.python }}-${{ matrix.os }}
|
|
@@ -84,7 +89,7 @@ jobs:
|
|
|
84
89
|
runs-on: ubuntu-latest
|
|
85
90
|
steps:
|
|
86
91
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
87
|
-
- uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@
|
|
92
|
+
- uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
|
|
88
93
|
with:
|
|
89
94
|
python-version: '3.11'
|
|
90
95
|
- run: uv pip install 'pytest==8.0.0'
|
|
@@ -93,7 +98,7 @@ jobs:
|
|
|
93
98
|
runs-on: ubuntu-latest
|
|
94
99
|
steps:
|
|
95
100
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
96
|
-
- uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@
|
|
101
|
+
- uses: gigaverse-app/ci-esta/.github/actions/setup-cached-uv@v0.1
|
|
97
102
|
with:
|
|
98
103
|
python-version: '3.14'
|
|
99
104
|
- run: uv build
|
|
@@ -112,7 +117,7 @@ jobs:
|
|
|
112
117
|
if: ${{ !cancelled() }}
|
|
113
118
|
runs-on: ubuntu-latest
|
|
114
119
|
steps:
|
|
115
|
-
- uses: gigaverse-app/ci-esta/.github/actions/validation-gate@
|
|
120
|
+
- uses: gigaverse-app/ci-esta/.github/actions/validation-gate@v0.1
|
|
116
121
|
with:
|
|
117
122
|
needs: ${{ toJSON(needs) }}
|
|
118
123
|
lanes: ${{ needs.select-tests.outputs.lanes || '{}' }}
|
|
@@ -13,7 +13,7 @@ permissions:
|
|
|
13
13
|
|
|
14
14
|
jobs:
|
|
15
15
|
report:
|
|
16
|
-
uses: gigaverse-app/ci-esta/.github/workflows/report.yml@
|
|
16
|
+
uses: gigaverse-app/ci-esta/.github/workflows/report.yml@v0.3.0
|
|
17
17
|
with:
|
|
18
18
|
run-id: ${{ github.event.workflow_run.id }}
|
|
19
19
|
run-attempt: ${{ github.event.workflow_run.run_attempt }}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: PR title
|
|
2
|
+
|
|
3
|
+
# Squash merges use this checked title as the Conventional Commit header.
|
|
4
|
+
on:
|
|
5
|
+
pull_request_target:
|
|
6
|
+
types: [opened, edited, synchronize, reopened, ready_for_review]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
pull-requests: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
conventional-commit:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
timeout-minutes: 5
|
|
15
|
+
steps:
|
|
16
|
+
# Only reads PR metadata. Never check out or execute PR code in this workflow.
|
|
17
|
+
- uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
|
|
18
|
+
with:
|
|
19
|
+
types: |
|
|
20
|
+
feat
|
|
21
|
+
fix
|
|
22
|
+
perf
|
|
23
|
+
revert
|
|
24
|
+
docs
|
|
25
|
+
style
|
|
26
|
+
refactor
|
|
27
|
+
test
|
|
28
|
+
build
|
|
29
|
+
ci
|
|
30
|
+
chore
|
|
31
|
+
requireScope: false
|
|
32
|
+
env:
|
|
33
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
34
|
+
- name: Explain how to repair the title
|
|
35
|
+
if: failure()
|
|
36
|
+
run: |
|
|
37
|
+
cat >> "$GITHUB_STEP_SUMMARY" <<'EOF'
|
|
38
|
+
Rename the PR to `type(optional-scope): description`, for example
|
|
39
|
+
`fix(parser): handle empty input` or `docs: clarify installation`.
|
|
40
|
+
Use `!` before the colon for a breaking change, for example
|
|
41
|
+
`feat(api)!: remove the deprecated argument`.
|
|
42
|
+
Choose the type that describes the change; do not hide features or fixes under `chore:`.
|
|
43
|
+
Editing the PR title reruns this check. No commit rewrite or replacement PR is needed.
|
|
44
|
+
If the title is already valid, inspect the action log for an API or runner failure.
|
|
45
|
+
EOF
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Public action smoke
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
jobs:
|
|
10
|
+
public-actions:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
14
|
+
with:
|
|
15
|
+
fetch-depth: 0
|
|
16
|
+
- name: Use the reviewed repository graph
|
|
17
|
+
run: |
|
|
18
|
+
python - <<'PY'
|
|
19
|
+
import json
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
graph = json.loads(Path('.github/test-lanes.json').read_text())['graph']
|
|
22
|
+
Path('smoke-impact.json').write_text(json.dumps(graph))
|
|
23
|
+
PY
|
|
24
|
+
- uses: ./
|
|
25
|
+
id: impact
|
|
26
|
+
with:
|
|
27
|
+
config: smoke-impact.json
|
|
28
|
+
base: ${{ github.sha }}
|
|
29
|
+
full: 'true'
|
|
30
|
+
full-roots: tests
|
|
31
|
+
max-shards: '2'
|
|
32
|
+
explanation-artifact: ''
|
|
33
|
+
- name: Verify forwarded file-plan outputs
|
|
34
|
+
env:
|
|
35
|
+
MODE: ${{ steps.impact.outputs.mode }}
|
|
36
|
+
ROOTS: ${{ steps.impact.outputs.test_roots }}
|
|
37
|
+
run: |
|
|
38
|
+
test "$MODE" = full
|
|
39
|
+
test -n "$ROOTS"
|
|
40
|
+
- uses: ./plan-lanes
|
|
41
|
+
id: lanes
|
|
42
|
+
with:
|
|
43
|
+
config: .github/test-lanes.json
|
|
44
|
+
base: ${{ github.sha }}
|
|
45
|
+
full: 'true'
|
|
46
|
+
artifact-name: ''
|
|
47
|
+
- name: Verify forwarded lane outputs
|
|
48
|
+
env:
|
|
49
|
+
LANES: ${{ steps.lanes.outputs.lanes }}
|
|
50
|
+
run: |
|
|
51
|
+
python - <<'PY'
|
|
52
|
+
import json, os
|
|
53
|
+
assert json.loads(os.environ['LANES']) == {'tests': True}
|
|
54
|
+
PY
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Release Please
|
|
2
|
+
|
|
3
|
+
# Release PRs accumulate changes; merging one is the publishing decision.
|
|
4
|
+
on:
|
|
5
|
+
workflow_run:
|
|
6
|
+
workflows: [CI]
|
|
7
|
+
branches: [main]
|
|
8
|
+
types: [completed]
|
|
9
|
+
|
|
10
|
+
permissions: {}
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: release-please
|
|
14
|
+
cancel-in-progress: false
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
release-please:
|
|
18
|
+
if: >-
|
|
19
|
+
github.event.workflow_run.event == 'push'
|
|
20
|
+
&& github.event.workflow_run.conclusion == 'success'
|
|
21
|
+
&& github.event.workflow_run.head_repository.full_name == github.repository
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
environment: release-automation
|
|
24
|
+
timeout-minutes: 10
|
|
25
|
+
permissions:
|
|
26
|
+
contents: write
|
|
27
|
+
pull-requests: write
|
|
28
|
+
steps:
|
|
29
|
+
- name: Only process the tested main head
|
|
30
|
+
id: current
|
|
31
|
+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
|
|
32
|
+
with:
|
|
33
|
+
script: |
|
|
34
|
+
const {data: branch} = await github.rest.repos.getBranch({...context.repo, branch: 'main'});
|
|
35
|
+
core.setOutput('matches', branch.commit.sha === context.payload.workflow_run.head_sha);
|
|
36
|
+
- name: Require release bot authentication
|
|
37
|
+
if: steps.current.outputs.matches == 'true'
|
|
38
|
+
env:
|
|
39
|
+
HAS_RELEASE_TOKEN: ${{ secrets.GV_CI_CROSS_REPO_TOKEN != '' }}
|
|
40
|
+
run: |
|
|
41
|
+
if [[ "$HAS_RELEASE_TOKEN" != "true" ]]; then
|
|
42
|
+
echo "::error::Share the organization GV_CI_CROSS_REPO_TOKEN secret with this repository."
|
|
43
|
+
exit 1
|
|
44
|
+
fi
|
|
45
|
+
- name: Prepare release PR or publish its GitHub release
|
|
46
|
+
if: steps.current.outputs.matches == 'true'
|
|
47
|
+
uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
|
|
48
|
+
with:
|
|
49
|
+
# This credential triggers CI on release PRs and Publish on releases.
|
|
50
|
+
# GITHUB_TOKEN would suppress those follow-up workflow events.
|
|
51
|
+
token: ${{ secrets.GV_CI_CROSS_REPO_TOKEN }}
|
|
52
|
+
target-branch: main
|
|
53
|
+
config-file: release-please-config.json
|
|
54
|
+
manifest-file: .release-please-manifest.json
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Working on pytest-selective
|
|
2
|
+
|
|
3
|
+
For adopting the tool in another repository, use
|
|
4
|
+
[the portable skill](skills/pytest-selective/SKILL.md). This file describes work
|
|
5
|
+
on pytest-selective itself.
|
|
6
|
+
|
|
7
|
+
- Read [CONTRIBUTING.md](CONTRIBUTING.md) for setup and validation. Use the locked
|
|
8
|
+
environment: `uv sync --locked`, `uv run pre-commit run --all-files`,
|
|
9
|
+
`uv run pytest -q -n 4`. For packaging changes also build, run strict Twine,
|
|
10
|
+
`scripts/check_metadata.py` and `scripts/smoke_distribution.py`.
|
|
11
|
+
- Reproduce selection bugs using real temporary Git repositories and existing
|
|
12
|
+
`tests/testing/git_repo.py` helpers. Cover base and head trees, deleted inputs,
|
|
13
|
+
explicit declarations and the relevant fallback. Do not mock away selection.
|
|
14
|
+
- Planning supports committed revisions and explicit working-tree snapshots. Preserve full execution on
|
|
15
|
+
operational uncertainty and diagnostics for invalid declarations. An empty
|
|
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
|
|
19
|
+
checkpoints and the `test:full` override.
|
|
20
|
+
- The README's performance numbers are scenario-specific observations. Keep
|
|
21
|
+
claims linked to [raw evidence](docs/benchmarks/2026-10-22-routing.md); distinguish
|
|
22
|
+
runner-seconds, elapsed time and billing. Skill/example edits need usable links
|
|
23
|
+
and verified commands, not tests that merely assert prose wording.
|
|
24
|
+
|
|
25
|
+
## Commits and pull requests
|
|
26
|
+
|
|
27
|
+
- Use Conventional Commits for commits you create and PR titles:
|
|
28
|
+
`type(optional-scope): description`, for example
|
|
29
|
+
`fix(parser): handle empty input`.
|
|
30
|
+
- Allowed types: `feat`, `fix`, `perf`, `revert`, `docs`, `style`,
|
|
31
|
+
`refactor`, `test`, `build`, `ci`, and `chore`. Choose the type for the
|
|
32
|
+
actual change. Mark breaking changes with `!` before the colon and explain
|
|
33
|
+
the migration in the PR body.
|
|
34
|
+
- Repair an invalid PR title in place. Preserve useful work; do not close or
|
|
35
|
+
replace the PR, or rewrite existing commits just to satisfy the title check.
|
|
36
|
+
- Squash merges use the checked PR title. Keep any `BREAKING CHANGE:` details
|
|
37
|
+
in the body. Follow [CONTRIBUTING.md](CONTRIBUTING.md) and
|
|
38
|
+
[RELEASING.md](RELEASING.md).
|
|
39
|
+
|
|
40
|
+
## Releases
|
|
41
|
+
|
|
42
|
+
Release Please derives versions and changelogs from Conventional Commits. Let
|
|
43
|
+
it prepare the release PR; do not hand-edit versions for ordinary changes.
|
|
44
|
+
Merging a release PR authorizes PyPI publication after CI. Follow RELEASING.md.
|
|
45
|
+
|
|
46
|
+
## Shared agent instructions
|
|
47
|
+
|
|
48
|
+
Edit this root `AGENTS.md` as the single source for Codex and Claude.
|
|
49
|
+
`CLAUDE.md` is an AgentSync-managed relative symlink to this file, not a
|
|
50
|
+
separate instruction document. The configuration is
|
|
51
|
+
[agentsync.toml](agentsync.toml). To restore and verify the link:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx --yes @dallay/agentsync@1.52.3 apply
|
|
55
|
+
npx --yes @dallay/agentsync@1.52.3 status
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Keep the symlink tracked in Git. See CONTRIBUTING.md for platform setup.
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.0](https://github.com/gigaverse-app/pytest-selective/compare/v0.1.1...v0.2.0) (2026-10-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add public action entry points and task-focused onboarding ([#41](https://github.com/gigaverse-app/pytest-selective/issues/41)) ([94da1e6](https://github.com/gigaverse-app/pytest-selective/commit/94da1e6d4088d9ded93ce491dc88993ac140e0ea))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug fixes
|
|
12
|
+
|
|
13
|
+
* **selection:** preserve plugin sessions and accelerate graph construction ([#42](https://github.com/gigaverse-app/pytest-selective/issues/42)) ([2994c88](https://github.com/gigaverse-app/pytest-selective/commit/2994c887d916a965b78f5ff8d48476abed705e37))
|
|
14
|
+
|
|
15
|
+
## 0.1.1 (2026-10-23)
|
|
16
|
+
|
|
17
|
+
- Register a native pytest plugin: `pytest --selective`, ini defaults, optional existing impact JSON, an exact comparison base, and `--no-selective` for full execution.
|
|
18
|
+
- Reuse the existing working-tree snapshots and dependency planner; share one plan with xdist workers and preserve unknown collectors, doctests, normal pytest filtering and failure statuses.
|
|
19
|
+
- Install pytest as a runtime dependency; retain the audit extra and all CLI/CI interfaces.
|
|
20
|
+
|
|
3
21
|
## 0.1.0 (2026-10-23)
|
|
4
22
|
|
|
5
23
|
First PyPI release.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Contributing to pytest-selective
|
|
2
|
+
|
|
3
|
+
Use Python 3.11+, Git 2.24+, and uv. The planner operates on immutable Git trees;
|
|
4
|
+
tests should exercise real temporary repositories through the existing helpers
|
|
5
|
+
in `tests/testing/git_repo.py`.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync --locked
|
|
9
|
+
uv run pre-commit install
|
|
10
|
+
uv run pre-commit run --all-files
|
|
11
|
+
uv run pytest -q --cov --cov-report=term-missing
|
|
12
|
+
uv run python scripts/tutorial.py
|
|
13
|
+
uv build
|
|
14
|
+
uv run twine check --strict dist/*
|
|
15
|
+
uv run python scripts/smoke_distribution.py
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Ruff lint and formatting use the versions in `uv.lock`, both locally and in CI.
|
|
19
|
+
Hooks fix repairable lint and formatting issues; review and stage their edits.
|
|
20
|
+
The Markdown hook checks local file links. It does not check external URLs or
|
|
21
|
+
heading anchors. Tests run separately so normal commits stay quick.
|
|
22
|
+
|
|
23
|
+
## Preserve selection safety
|
|
24
|
+
|
|
25
|
+
For a bug, first add a failing regression using an actual Git change. Assert the
|
|
26
|
+
selected paths and observable outcome. Include base and head behavior, invalid
|
|
27
|
+
inputs, and fallback handling when relevant. Prefer existing helpers over mocks
|
|
28
|
+
of Git or the selector. Do not weaken selection or add broad ignores to hide a
|
|
29
|
+
failure. Keep root conftests small: every importer inherits their dependencies.
|
|
30
|
+
|
|
31
|
+
Changes to collection policy, runtime auditing, or the composite action need tests
|
|
32
|
+
at that boundary. Update the tutorial when the public command contract changes.
|
|
33
|
+
Keep performance claims tied to reproducible measurements and their limitations.
|
|
34
|
+
|
|
35
|
+
## CI and dependency maintenance
|
|
36
|
+
|
|
37
|
+
CI tests Python 3.11 and 3.14 on Linux, Windows, and macOS. A separate job checks
|
|
38
|
+
pytest 8.0.0 on Python 3.11, the plugin's lower bound. It also checks hooks, builds both distribution
|
|
39
|
+
formats, validates PyPI metadata, and installs each distribution in an isolated
|
|
40
|
+
environment on both Python versions. Evidence artifacts carry coverage and tutorial output on every platform and Python version.
|
|
41
|
+
|
|
42
|
+
Use `uv lock --upgrade-package NAME` for a targeted dependency update and run the
|
|
43
|
+
affected checks. Dependabot proposes weekly uv and GitHub Actions updates.
|
|
44
|
+
Actions are pinned to commits. Review their release notes before updating pins.
|
|
45
|
+
|
|
46
|
+
## Pull requests
|
|
47
|
+
|
|
48
|
+
Explain the user-visible problem and the resulting behavior. Include the exact
|
|
49
|
+
validation commands, measured evidence where applicable, and any remaining
|
|
50
|
+
limitations. The pull request template provides a short checklist. See
|
|
51
|
+
[RELEASING.md](RELEASING.md) for package publication.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## CI lane selection
|
|
55
|
+
|
|
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
|
|
63
|
+
controls. Add new non-import execution inputs to `.github/test-lanes.json`.
|
|
64
|
+
|
|
65
|
+
## Conventional Commits
|
|
66
|
+
|
|
67
|
+
Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
|
|
68
|
+
for commits you create and PR titles (the squash commit that lands on `main`):
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
fix(parser): handle empty input
|
|
72
|
+
feat: add a new output format
|
|
73
|
+
feat(api)!: remove the deprecated argument
|
|
74
|
+
docs: clarify installation
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Allowed types are `feat`, `fix`, `perf`, `revert`, `docs`, `style`,
|
|
78
|
+
`refactor`, `test`, `build`, `ci`, and `chore`. Scope is optional.
|
|
79
|
+
Use `!` before the colon for breaking changes and explain the migration in the
|
|
80
|
+
PR body. Choose the type for the actual change, since release tooling uses it.
|
|
81
|
+
|
|
82
|
+
The `conventional-commit` check uses
|
|
83
|
+
[amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request).
|
|
84
|
+
It reads PR metadata, including for forks, without checking out contributor code.
|
|
85
|
+
If it fails on a title, rename the PR; the edited event reruns the check.
|
|
86
|
+
Keep the existing PR and commits. Work-in-progress commits need not be rewritten.
|
|
87
|
+
|
|
88
|
+
Use **Squash and merge**, with the PR title as the commit title. Check the final
|
|
89
|
+
message before merging, including single-commit PRs, and preserve any
|
|
90
|
+
`BREAKING CHANGE:` explanation in the body. The repository's squash defaults
|
|
91
|
+
support this, but a maintainer can still edit the final message.
|
|
92
|
+
Release Please turns these commits into a release PR containing the version,
|
|
93
|
+
changelog, and lockfile update. Merging that PR authorizes PyPI publication after
|
|
94
|
+
CI. See [RELEASING.md](RELEASING.md) for the version rules and publishing.
|
|
95
|
+
|
|
96
|
+
## Shared instructions for Codex and Claude
|
|
97
|
+
|
|
98
|
+
[AGENTS.md](AGENTS.md) is the canonical repository guidance. Codex reads it
|
|
99
|
+
directly; Claude reads the tracked `CLAUDE.md -> AGENTS.md` symlink. Edit
|
|
100
|
+
`AGENTS.md` once, including commit-policy changes, so both tools receive the
|
|
101
|
+
same instructions.
|
|
102
|
+
|
|
103
|
+
[dallay/agentsync](https://github.com/dallay/agentsync) manages that link through
|
|
104
|
+
[agentsync.toml](agentsync.toml). After cloning, or to repair a
|
|
105
|
+
missing or stale link, run these commands from the repository root with Node.js
|
|
106
|
+
18+ and npm installed:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx --yes @dallay/agentsync@1.52.3 apply
|
|
110
|
+
npx --yes @dallay/agentsync@1.52.3 status
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The CLI version is pinned for reproducible setup. Review and update both commands
|
|
114
|
+
when upgrading AgentSync. The configuration disables managed gitignore changes
|
|
115
|
+
because we intentionally commit the relative link, following AgentSync's
|
|
116
|
+
[committed-destination workflow](https://dallay.github.io/agentsync/guides/gitignore-team-workflows/).
|
|
117
|
+
Ordinary instruction edits propagate immediately through the link.
|
|
118
|
+
|
|
119
|
+
On native Windows, enable Developer Mode and Git symlink support
|
|
120
|
+
(`git config core.symlinks true`), then run `apply` to repair a checkout that
|
|
121
|
+
materialized the link as plain text. Alternatively, use WSL for a checkout in
|
|
122
|
+
the Linux filesystem. See the
|
|
123
|
+
[Windows setup guide](https://dallay.github.io/agentsync/guides/windows-symlink-setup/).
|
|
124
|
+
If AgentSync backs up an existing `CLAUDE.md`, review and preserve any unique
|
|
125
|
+
guidance in `AGENTS.md`; do not commit the backup as another instruction source.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pytest-selective
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.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
6
|
Project-URL: Documentation, https://github.com/gigaverse-app/pytest-selective/blob/main/docs/README.md
|
|
@@ -23,6 +23,7 @@ Classifier: Topic :: Software Development :: Testing
|
|
|
23
23
|
Classifier: Typing :: Typed
|
|
24
24
|
Requires-Python: >=3.11
|
|
25
25
|
Requires-Dist: pydantic<3,>=2.11
|
|
26
|
+
Requires-Dist: pytest>=8
|
|
26
27
|
Requires-Dist: pyyaml<7,>=6
|
|
27
28
|
Provides-Extra: audit
|
|
28
29
|
Requires-Dist: pytest>=8; extra == 'audit'
|
|
@@ -33,21 +34,17 @@ Description-Content-Type: text/markdown
|
|
|
33
34
|
**Run affected Python tests. See why they matter.**
|
|
34
35
|
|
|
35
36
|
[](https://github.com/gigaverse-app/pytest-selective/actions/workflows/ci.yml)
|
|
37
|
+
[](https://pypi.org/project/pytest-selective/)
|
|
36
38
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/pyproject.toml)
|
|
37
39
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/src/pytest_selective/py.typed)
|
|
38
40
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/.pre-commit-config.yaml)
|
|
39
41
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/LICENSE)
|
|
40
42
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/agents.md)
|
|
41
43
|
|
|
42
|
-
**Our README CI used 92.3% less runner time: 627s → 48s.** Elapsed time fell
|
|
43
|
-
from 211s to 26s, with docs, routing and package checks preserved. One successful
|
|
44
|
-
same-revision pair, not a universal speedup.
|
|
45
|
-
[Inspect the runs and raw evidence](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/benchmarks/2026-10-22-routing.md).
|
|
46
|
-
|
|
47
44
|
pytest-selective is a **Python test impact analysis** tool for incremental testing
|
|
48
45
|
with pytest. It follows dependencies through both sides of a Git change, selects
|
|
49
|
-
the affected test files, and explains the result.
|
|
50
|
-
|
|
46
|
+
the affected test files, and explains the result. Use it directly as a pytest
|
|
47
|
+
plugin, or plan before collection and service startup with the CLI and CI actions.
|
|
51
48
|
|
|
52
49
|
Built from the selector used in Gigaverse's backend, AI, and shared Python
|
|
53
50
|
infrastructure. The API may change before 1.0.
|
|
@@ -67,6 +64,29 @@ used **49 instead of 105 runner-seconds (53.3% less)** while keeping quality,
|
|
|
67
64
|
routing and package checks. Its reports now compute dependency critical paths
|
|
68
65
|
and slack. [See the source runs and method](https://github.com/gigaverse-app/ci-esta/blob/main/docs/benchmarks/2026-10-23-toolkit.md).
|
|
69
66
|
|
|
67
|
+
## Choose how to use it
|
|
68
|
+
|
|
69
|
+
| You want to… | Use | What it saves |
|
|
70
|
+
| --- | --- | --- |
|
|
71
|
+
| 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
|
+
| 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 |
|
|
75
|
+
| 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
|
+
| Keep selection narrow as the project grows | Explanations, startup-floor budgets, expansion and isolation guards | Makes broad new fixture/import dependencies visible |
|
|
77
|
+
|
|
78
|
+
Start with [local pytest](docs/local-development.md), [the complete CI recipe](docs/ci.md),
|
|
79
|
+
or [dependency audits and hygiene](docs/selection-health.md). The native plugin
|
|
80
|
+
collects normally; the pre-collection runner and CI planner can avoid that cost.
|
|
81
|
+
Keep full checkpoints and use complete lanes when partial suites cannot satisfy
|
|
82
|
+
your coverage contract.
|
|
83
|
+
|
|
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.
|
|
88
|
+
[Public action API](docs/actions.md).
|
|
89
|
+
|
|
70
90
|
## Have your agent set it up
|
|
71
91
|
|
|
72
92
|
Paste this into your coding agent in the Python project you want to improve:
|
|
@@ -128,7 +148,27 @@ including Due's widget benchmark, which selection skips entirely.
|
|
|
128
148
|
|
|
129
149
|
## Try it in two minutes
|
|
130
150
|
|
|
131
|
-
|
|
151
|
+
Install the plugin in your test environment, then use ordinary pytest:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
uv add --dev pytest-selective
|
|
155
|
+
uv run pytest --selective
|
|
156
|
+
uv run pytest --selective --selective-base origin/main -n auto
|
|
157
|
+
uv run pytest --no-selective
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Selection is opt-in. The default compares HEAD with staged, unstaged and
|
|
161
|
+
nonignored untracked files. `--selective-base` compares against the exact ref
|
|
162
|
+
you supply, including local edits. The plugin reuses the CLI's dependency graph,
|
|
163
|
+
deselects unaffected collected tests, and keeps doctests and unknown collectors.
|
|
164
|
+
Normal test paths, node IDs, `-k` and `-m` still apply. Missing history runs the
|
|
165
|
+
complete requested suite. [Plugin configuration and limits](docs/local-development.md).
|
|
166
|
+
|
|
167
|
+
For pre-collection selection, use `pytest-selective run`; for CI jobs with
|
|
168
|
+
expensive setup or whole-suite evidence requirements, use lane selection.
|
|
169
|
+
|
|
170
|
+
Requires **Python 3.11+ and Git 2.24+**. The examples use uv; the native plugin
|
|
171
|
+
also works in your existing pytest environment. Use a planner Python version at
|
|
132
172
|
least as new as your source syntax; the CI action uses Python 3.14. Your test
|
|
133
173
|
runtime can use a different Python version when planning runs separately.
|
|
134
174
|
The optional audit recorder requires Python 3.11+ in the test environment.
|
|
@@ -152,13 +192,20 @@ hold. It uses a temporary repository and leaves your checkout untouched.
|
|
|
152
192
|
|
|
153
193
|
## Install in your project
|
|
154
194
|
|
|
155
|
-
|
|
195
|
+
Install from PyPI using Python 3.11+:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
pip install "pytest-selective>=0.1.0,<0.2.0"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
For source development, GitHub installation is also available:
|
|
156
202
|
|
|
157
203
|
```bash
|
|
158
204
|
pip install "pytest-selective @ git+https://github.com/gigaverse-app/pytest-selective.git"
|
|
159
205
|
```
|
|
160
206
|
|
|
161
|
-
|
|
207
|
+
Use compatible package ranges; lockfiles retain exact resolved artifacts.
|
|
208
|
+
For action-path availability and release pins, see [the action API](docs/actions.md). Then follow the
|
|
162
209
|
[configuration walkthrough](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/configuration.md)
|
|
163
210
|
to declare module roots, test roots, collection-policy fingerprints, and non-Python inputs.
|
|
164
211
|
|
|
@@ -168,7 +215,8 @@ pytest-selective affected --config .github/test-impact.json \
|
|
|
168
215
|
--explanation-output explanation.json
|
|
169
216
|
```
|
|
170
217
|
|
|
171
|
-
|
|
218
|
+
`affected` reads **committed Git trees** by default. Use `affected --working-tree`
|
|
219
|
+
or `pytest-selective run` to include uncommitted edits.
|
|
172
220
|
The report distinguishes `scoped`, `full`, and `none`; an empty selection must
|
|
173
221
|
skip pytest, because invoking pytest without paths runs the whole suite.
|
|
174
222
|
|
|
@@ -185,7 +233,7 @@ skip pytest, because invoking pytest without paths runs the whole suite.
|
|
|
185
233
|
| Undeclared runtime reads | An opt-in pytest recorder and audit command |
|
|
186
234
|
|
|
187
235
|
The CLI emits JSON for your runner. The
|
|
188
|
-
[composite action](https://github.com/gigaverse-app/pytest-selective/blob/main
|
|
236
|
+
[composite action](https://github.com/gigaverse-app/pytest-selective/blob/main/test-impact/action.yml)
|
|
189
237
|
adds caching and falls back to complete test roots on operational planning
|
|
190
238
|
failures. Invalid dependency declarations fail with a diagnostic that must be fixed.
|
|
191
239
|
|
|
@@ -210,9 +258,9 @@ and evidence checks.
|
|
|
210
258
|
## Choose the right tool
|
|
211
259
|
|
|
212
260
|
[pytest-impacted](https://github.com/promptromp/pytest-impacted) offers a pytest-native
|
|
213
|
-
`--impacted` workflow, including working-tree changes. pytest-selective
|
|
214
|
-
|
|
215
|
-
|
|
261
|
+
`--impacted` workflow, including working-tree changes. pytest-selective supports the same local edit/test loop and also offers
|
|
262
|
+
inspectable JSON plans, runtime dependency audits, and planning before application
|
|
263
|
+
startup. Both use static dependency analysis; choose
|
|
216
264
|
based on your workflow, and validate selection against your own suite.
|
|
217
265
|
See the [lessons from pytest-impacted](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/pytest-impacted.md)
|
|
218
266
|
for portability and Git-resolution improvements adopted from that comparison.
|
|
@@ -246,7 +294,7 @@ optional; pytest-selective does not depend on it.</sub>
|
|
|
246
294
|
|
|
247
295
|
See the [CI toolkit integration](docs/ci-toolkit.md) for lane selection, validated
|
|
248
296
|
environment caches, required gates and real dependency critical-path reports.
|
|
249
|
-
|
|
297
|
+
## Optimize the work that still has to run
|
|
250
298
|
|
|
251
299
|
Selection and execution solve different parts of slow CI. Once selection keeps
|
|
252
300
|
the required tests, use [CI-esta's critical-path report](https://github.com/gigaverse-app/ci-esta/blob/main/docs/critical-path-optimizations.md)
|