pytest-selective 0.2.0__tar.gz → 0.3.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.2.0 → pytest_selective-0.3.0}/.github/test-lanes.json +5 -6
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/workflows/ci.yml +58 -15
- pytest_selective-0.3.0/.github/workflows/docs.yml +30 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/workflows/observe-ci.yml +2 -1
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/workflows/public-actions.yml +23 -1
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/workflows/release.yml +2 -1
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.gitignore +4 -0
- pytest_selective-0.3.0/.readthedocs.yaml +11 -0
- pytest_selective-0.3.0/.release-please-manifest.json +3 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/AGENTS.md +13 -2
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/CHANGELOG.md +23 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/CONTRIBUTING.md +35 -6
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/PKG-INFO +17 -13
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/README.md +15 -11
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/RELEASING.md +11 -4
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/action.yml +2 -2
- pytest_selective-0.3.0/actions/README.md +13 -0
- {pytest_selective-0.2.0/.github → pytest_selective-0.3.0}/actions/plan-lanes/action.yml +2 -2
- {pytest_selective-0.2.0/.github → pytest_selective-0.3.0}/actions/pytest-expansion/action.yml +1 -1
- {pytest_selective-0.2.0/.github → pytest_selective-0.3.0}/actions/test-impact/action.yml +2 -2
- pytest_selective-0.3.0/docs/actions.md +45 -0
- pytest_selective-0.3.0/docs/assets/banner.png +0 -0
- pytest_selective-0.3.0/docs/assets/banner.svg +28 -0
- pytest_selective-0.3.0/docs/assets/brand.json +13 -0
- pytest_selective-0.3.0/docs/assets/icon.png +0 -0
- pytest_selective-0.3.0/docs/assets/logo.svg +10 -0
- pytest_selective-0.3.0/docs/assets/raster-sources.json +9 -0
- pytest_selective-0.3.0/docs/assets/social-preview.png +0 -0
- pytest_selective-0.3.0/docs/assets/social-preview.svg +30 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22.md +1 -1
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/ci-toolkit.md +4 -2
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/ci.md +37 -8
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/comparison-pytest-impacted.md +4 -4
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/configuration.md +5 -3
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/evidence.md +3 -1
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/tutorial.md +37 -1
- pytest_selective-0.3.0/docs/tutorials/skip-unrelated-ci.md +140 -0
- pytest_selective-0.3.0/docs/work-in-progress/tickets/actions-directory-test-plan.md +10 -0
- pytest_selective-0.3.0/docs/work-in-progress/tickets/move-action-implementations-test-plan.md +10 -0
- pytest_selective-0.3.0/documentation/assets/routing-comparison.svg +1 -0
- pytest_selective-0.3.0/documentation/check_site.py +77 -0
- pytest_selective-0.3.0/documentation/ecosystem.md +31 -0
- pytest_selective-0.3.0/documentation/hooks.py +76 -0
- pytest_selective-0.3.0/documentation/index.md +72 -0
- pytest_selective-0.3.0/documentation/overrides/main.html +14 -0
- pytest_selective-0.3.0/documentation/publishing.md +107 -0
- pytest_selective-0.3.0/documentation/requirements.in +2 -0
- pytest_selective-0.3.0/documentation/requirements.txt +562 -0
- pytest_selective-0.3.0/mkdocs.yml +106 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/pyproject.toml +2 -2
- pytest_selective-0.3.0/scripts/ci_file_config.py +20 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/public_actions.py +4 -6
- pytest_selective-0.3.0/scripts/render_brand.py +140 -0
- pytest_selective-0.3.0/scripts/run_ci_tests.py +40 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/tutorial.py +3 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/skills/pytest-selective/SKILL.md +11 -5
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/skills/pytest-selective/references/adoption.md +4 -3
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/ci.py +14 -3
- pytest_selective-0.3.0/tests/test_ci_admission.py +64 -0
- pytest_selective-0.3.0/tests/test_ci_test_execution.py +71 -0
- pytest_selective-0.3.0/tests/test_public_actions.py +34 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/test_pytest_expansion.py +4 -1
- pytest_selective-0.3.0/tests/test_repository_ci.py +147 -0
- pytest_selective-0.3.0/tests/test_repository_hygiene.py.gv-dependency.yaml +4 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/test_tutorial.py +2 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_ci.py +86 -1
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_impact_explanation.py +2 -2
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_impact_graph.py +9 -9
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_pytest_plugin.py +3 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_working_tree.py +3 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/uv.lock +1 -1
- pytest_selective-0.2.0/.release-please-manifest.json +0 -3
- pytest_selective-0.2.0/docs/actions.md +0 -42
- pytest_selective-0.2.0/docs/pytest-impacted.md +0 -69
- pytest_selective-0.2.0/plan-lanes/action.yml +0 -33
- pytest_selective-0.2.0/pytest-expansion/action.yml +0 -35
- pytest_selective-0.2.0/test-impact/action.yml +0 -106
- pytest_selective-0.2.0/tests/test_public_actions.py +0 -30
- pytest_selective-0.2.0/tests/test_repository_ci.py +0 -48
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.gitattributes +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/dependabot.yml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/workflows/pr-title.yml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/workflows/release-please.yml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.github/workflows/windows-performance.yml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/.pre-commit-config.yaml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/CLAUDE.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/LICENSE +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/PROVENANCE.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/agentsync.toml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/README.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/agents.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22-due-ci.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22-due-docs-ci.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22-due-docs-widget.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22-due-widget.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22-input-replays.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22-obligation-docs.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22-obligation.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22-routing.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-22-selective-docs.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-23-windows-saleor/obligation-baseline.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.11.xml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.14.xml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-after.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.11.xml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.14.xml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-control.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-23-windows-saleor/selective-earlier.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/2026-10-23-windows-saleor.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/benchmarks/windows-runtime.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/local-development.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/pytest-hygiene.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/selection-health.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/work-in-progress/tickets/codex-selector-correctness-performance-test-plan.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/work-in-progress/tickets/codex-windows-git-performance-test-plan.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/work-in-progress/tickets/impacted-improvements-test-plan.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/docs/work-in-progress/tickets/public-action-onboarding-test-plan.md +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/release-please-config.json +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/benchmark_graph.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/benchmark_parsing.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/benchmark_rust.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/check_docs.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/check_metadata.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/compare_impacted.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/measure_ci_runs.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/scripts/smoke_distribution.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/skills/pytest-selective/agents/openai.yaml +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/__init__.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/__main__.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/ast_imports.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/hygiene.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_audit.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_audit_plugin.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_cli.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_declarations.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_explanation.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_first_party.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_graph.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_models.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_name_scope.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/impact_selection.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/input_policy.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/local.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/parse_batch.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/plugin.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/py.typed +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/pytest_expansion.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/pytest_plugins.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/pytest_sharding.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/test_inventory.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/typecheck_scope.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/src/pytest_selective/working_tree.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/__init__.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/test_ci_measurements.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/test_distribution_metadata.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/test_hygiene.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/test_repository_hygiene.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/__init__.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/git_repo.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_ast_imports.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_git_repo.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_global_inputs.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_impact_audit.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_impact_first_party.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_impact_name_scope.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_parse_batch.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_portability.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_pytest_plugins.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_pytest_sharding.py +0 -0
- {pytest_selective-0.2.0 → pytest_selective-0.3.0}/tests/testing/test_typecheck_scope.py +0 -0
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
],
|
|
19
19
|
"inputs": [
|
|
20
20
|
"src/**",
|
|
21
|
-
"
|
|
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
|
-
"
|
|
36
|
+
"actions/**",
|
|
37
37
|
"action.yml",
|
|
38
|
-
"*/action.yml",
|
|
39
38
|
"examples/**",
|
|
40
39
|
".github/workflows/public-actions.yml"
|
|
41
40
|
]
|
|
@@ -17,31 +17,56 @@ 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.paths.outputs.files }}
|
|
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
30
|
base: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
29
|
-
full: ${{ github.run_attempt > 1 || github.event_name
|
|
31
|
+
full: ${{ github.run_attempt > 1 || contains(fromJSON('["workflow_dispatch","workflow_call","schedule","release"]'), github.event_name) || contains(github.event.pull_request.labels.*.name, 'test:full') }}
|
|
32
|
+
- name: Share the repository graph and execution inputs with file selection
|
|
33
|
+
env:
|
|
34
|
+
PYTHONPATH: src
|
|
35
|
+
run: |
|
|
36
|
+
uv run --no-project --python 3.14 --with pydantic==2.13.4 --with pyyaml==6.0.3 \
|
|
37
|
+
python scripts/ci_file_config.py "$RUNNER_TEMP/test-impact.json"
|
|
38
|
+
- id: files
|
|
39
|
+
uses: ./
|
|
40
|
+
with:
|
|
41
|
+
config: ${{ runner.temp }}/test-impact.json
|
|
42
|
+
base: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
43
|
+
full-roots: tests
|
|
44
|
+
full: ${{ github.run_attempt > 1 || contains(fromJSON('["workflow_dispatch","workflow_call","schedule","release"]'), github.event_name) || contains(github.event.pull_request.labels.*.name, 'test:full') }}
|
|
45
|
+
- id: paths
|
|
46
|
+
name: Forward exact selected paths without shell splitting
|
|
47
|
+
env:
|
|
48
|
+
MODE: ${{ steps.files.outputs.mode }}
|
|
49
|
+
run: |
|
|
50
|
+
python - <<'PY'
|
|
51
|
+
import json, os
|
|
52
|
+
from pathlib import Path
|
|
53
|
+
files = json.loads(Path('test-impact-report.json').read_text())['selected'] if os.environ['MODE'] == 'scoped' else []
|
|
54
|
+
with open(os.environ['GITHUB_OUTPUT'], 'a') as output:
|
|
55
|
+
output.write('files=' + json.dumps(files) + '\n')
|
|
56
|
+
PY
|
|
30
57
|
quality:
|
|
31
58
|
runs-on: ubuntu-latest
|
|
32
59
|
steps:
|
|
33
60
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
34
|
-
- uses: gigaverse-app/ci-esta
|
|
61
|
+
- uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
|
|
35
62
|
with:
|
|
36
63
|
python-version: '3.14'
|
|
37
64
|
- run: uv run --locked pre-commit run --all-files
|
|
38
65
|
- name: Check aggregate gate against the execution lanes
|
|
39
66
|
run: >-
|
|
40
67
|
uv run --no-project --python 3.14
|
|
41
|
-
--with "ci-esta>=
|
|
68
|
+
--with "ci-esta>=1.1.0,<2.0.0"
|
|
42
69
|
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
70
|
- name: Validate GitHub Actions
|
|
46
71
|
run: docker run --rm -v "$PWD:/repo" -w /repo rhysd/actionlint:1.7.7 -color
|
|
47
72
|
tests:
|
|
@@ -57,20 +82,26 @@ jobs:
|
|
|
57
82
|
runs-on: ${{ matrix.os }}
|
|
58
83
|
steps:
|
|
59
84
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
60
|
-
- uses: gigaverse-app/ci-esta
|
|
85
|
+
- uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
|
|
61
86
|
with:
|
|
62
87
|
python-version: ${{ matrix.python }}
|
|
63
88
|
- name: Use native Git for Windows
|
|
64
|
-
uses: gigaverse-app/ci-esta
|
|
89
|
+
uses: gigaverse-app/ci-esta/actions/native-windows-git@v1
|
|
65
90
|
- name: Record coverage runtime
|
|
66
91
|
run: uv run --locked python -m coverage --version
|
|
67
|
-
-
|
|
92
|
+
- name: Execute the shared affected-file plan
|
|
93
|
+
run: uv run --locked python scripts/run_ci_tests.py -q -n 4 --durations=20 --junitxml=test-timings.xml
|
|
68
94
|
env:
|
|
95
|
+
CI_PLANNER_RESULT: ${{ needs.select-tests.result }}
|
|
96
|
+
CI_TEST_MODE: ${{ needs.select-tests.outputs.mode }}
|
|
97
|
+
CI_TEST_FILES: ${{ needs.select-tests.outputs.files }}
|
|
98
|
+
CI_COVERAGE: 'true'
|
|
69
99
|
# Keep temporary Git repositories beside the checkout on the work disk.
|
|
70
100
|
TMP: ${{ runner.temp }}
|
|
71
101
|
TEMP: ${{ runner.temp }}
|
|
72
102
|
TMPDIR: ${{ runner.temp }}
|
|
73
|
-
- uses: gigaverse-app/ci-esta
|
|
103
|
+
- uses: gigaverse-app/ci-esta/actions/learn-test-timings@v1
|
|
104
|
+
if: ${{ hashFiles('test-timings.xml') != '' }}
|
|
74
105
|
with:
|
|
75
106
|
junit-pattern: test-timings.xml
|
|
76
107
|
artifact-name: test-timings-${{ matrix.python }}-${{ matrix.os }}
|
|
@@ -89,22 +120,34 @@ jobs:
|
|
|
89
120
|
runs-on: ubuntu-latest
|
|
90
121
|
steps:
|
|
91
122
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
92
|
-
- uses: gigaverse-app/ci-esta
|
|
123
|
+
- uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
|
|
93
124
|
with:
|
|
94
125
|
python-version: '3.11'
|
|
95
126
|
- run: uv pip install 'pytest==8.0.0'
|
|
96
|
-
-
|
|
127
|
+
- name: Execute the same file plan on minimum pytest
|
|
128
|
+
run: uv run --no-sync python scripts/run_ci_tests.py -q -n 4 --durations=20
|
|
129
|
+
env:
|
|
130
|
+
CI_PLANNER_RESULT: ${{ needs.select-tests.result }}
|
|
131
|
+
CI_TEST_MODE: ${{ needs.select-tests.outputs.mode }}
|
|
132
|
+
CI_TEST_FILES: ${{ needs.select-tests.outputs.files }}
|
|
97
133
|
distributions:
|
|
134
|
+
needs: select-tests
|
|
135
|
+
# README changes still need build/metadata checks; planner failure must not skip them.
|
|
136
|
+
if: ${{ !cancelled() }}
|
|
98
137
|
runs-on: ubuntu-latest
|
|
99
138
|
steps:
|
|
100
139
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
101
|
-
- uses: gigaverse-app/ci-esta
|
|
140
|
+
- uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
|
|
102
141
|
with:
|
|
103
142
|
python-version: '3.14'
|
|
104
143
|
- run: uv build
|
|
105
144
|
- run: uv run --locked twine check --strict dist/*
|
|
106
145
|
- run: uv run --locked python scripts/check_metadata.py
|
|
107
|
-
-
|
|
146
|
+
- name: Smoke installed distributions when runtime inputs change
|
|
147
|
+
if: >-
|
|
148
|
+
${{ needs.select-tests.result != 'success' ||
|
|
149
|
+
fromJSON(needs.select-tests.outputs.lanes).tests }}
|
|
150
|
+
run: uv run --locked python scripts/smoke_distribution.py
|
|
108
151
|
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
109
152
|
with:
|
|
110
153
|
name: distributions
|
|
@@ -117,7 +160,7 @@ jobs:
|
|
|
117
160
|
if: ${{ !cancelled() }}
|
|
118
161
|
runs-on: ubuntu-latest
|
|
119
162
|
steps:
|
|
120
|
-
- uses: gigaverse-app/ci-esta
|
|
163
|
+
- uses: gigaverse-app/ci-esta/actions/validation-gate@v1
|
|
121
164
|
with:
|
|
122
165
|
needs: ${{ toJSON(needs) }}
|
|
123
166
|
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@
|
|
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,26 @@ 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
|
+
base: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
23
|
+
full: ${{ github.run_attempt > 1 || contains(fromJSON('["workflow_dispatch","workflow_call","schedule","release"]'), github.event_name) || contains(github.event.pull_request.labels.*.name, 'test:full') }}
|
|
24
|
+
artifact-name: public-action-selection
|
|
10
25
|
public-actions:
|
|
26
|
+
needs: select-tests
|
|
27
|
+
if: >-
|
|
28
|
+
${{ !cancelled() && (needs.select-tests.result != 'success' ||
|
|
29
|
+
fromJSON(needs.select-tests.outputs.lanes).tests) }}
|
|
11
30
|
runs-on: ubuntu-latest
|
|
12
31
|
steps:
|
|
13
32
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
@@ -37,7 +56,7 @@ jobs:
|
|
|
37
56
|
run: |
|
|
38
57
|
test "$MODE" = full
|
|
39
58
|
test -n "$ROOTS"
|
|
40
|
-
- uses: ./plan-lanes
|
|
59
|
+
- uses: ./actions/plan-lanes
|
|
41
60
|
id: lanes
|
|
42
61
|
with:
|
|
43
62
|
config: .github/test-lanes.json
|
|
@@ -52,3 +71,6 @@ jobs:
|
|
|
52
71
|
import json, os
|
|
53
72
|
assert json.loads(os.environ['LANES']) == {'tests': True}
|
|
54
73
|
PY
|
|
74
|
+
- name: Require successful planning after fallback execution
|
|
75
|
+
if: ${{ !cancelled() && needs.select-tests.result != 'success' }}
|
|
76
|
+
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
|
-
|
|
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
|
|
@@ -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
|
-
-
|
|
18
|
-
`.github/test-lanes.json` when adding execution inputs; preserve full
|
|
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,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.0](https://github.com/gigaverse-app/pytest-selective/compare/v0.2.0...v0.3.0) (2026-10-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* **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.
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* **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))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug fixes
|
|
16
|
+
|
|
17
|
+
* **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))
|
|
18
|
+
* **ci:** select all runtime tests by declared dependencies ([9673e50](https://github.com/gigaverse-app/pytest-selective/commit/9673e50dd8a709db9347d2e325da242aca96cece))
|
|
19
|
+
* **docs:** refresh cached artwork when branding changes ([5726530](https://github.com/gigaverse-app/pytest-selective/commit/5726530a445099e7cf24a1a7a89016fed0270308))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Refactoring
|
|
23
|
+
|
|
24
|
+
* **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))
|
|
25
|
+
|
|
3
26
|
## [0.2.0](https://github.com/gigaverse-app/pytest-selective/compare/v0.1.1...v0.2.0) (2026-10-23)
|
|
4
27
|
|
|
5
28
|
|
|
@@ -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/
|
|
58
|
-
while skipping the six-platform pytest matrix and minimum-pytest lane.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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.
|
|
3
|
+
Version: 0.3.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://
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
**Run affected Python tests. See why they matter.**
|
|
32
|
+

|
|
35
33
|
|
|
34
|
+
# pytest-selective
|
|
36
35
|
[](https://github.com/gigaverse-app/pytest-selective/actions/workflows/ci.yml)
|
|
37
36
|
[](https://pypi.org/project/pytest-selective/)
|
|
38
37
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/pyproject.toml)
|
|
@@ -40,6 +39,11 @@ Description-Content-Type: text/markdown
|
|
|
40
39
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/.pre-commit-config.yaml)
|
|
41
40
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/LICENSE)
|
|
42
41
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/agents.md)
|
|
42
|
+
[](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
|
|
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) ·
|
|
@@ -70,8 +75,8 @@ and slack. [See the source runs and method](https://github.com/gigaverse-app/ci-
|
|
|
70
75
|
| --- | --- | --- |
|
|
71
76
|
| 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
77
|
| 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@
|
|
74
|
-
| Keep whole-suite coverage or conformance checks | `gigaverse-app/pytest-selective/plan-lanes@
|
|
78
|
+
| Plan affected files in GitHub Actions | `gigaverse-app/pytest-selective@v1` | Plans before installing your application |
|
|
79
|
+
| Keep whole-suite coverage or conformance checks | `gigaverse-app/pytest-selective/actions/plan-lanes@v1` | Entire unaffected jobs, including their services and setup |
|
|
75
80
|
| 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
81
|
| Keep selection narrow as the project grows | Explanations, startup-floor budgets, expansion and isolation guards | Makes broad new fixture/import dependencies visible |
|
|
77
82
|
|
|
@@ -81,10 +86,9 @@ collects normally; the pre-collection runner and CI planner can avoid that cost.
|
|
|
81
86
|
Keep full checkpoints and use complete lanes when partial suites cannot satisfy
|
|
82
87
|
your coverage contract.
|
|
83
88
|
|
|
84
|
-
**Public-path availability:**
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
it includes these paths. Existing `.github/actions/...` paths remain supported.
|
|
89
|
+
**Public-path availability:** version 1 provides the root action and
|
|
90
|
+
`actions/NAME` paths. Use the moving `@v1` tag for compatible updates.
|
|
91
|
+
Older immutable releases retain their original layouts.
|
|
88
92
|
[Public action API](docs/actions.md).
|
|
89
93
|
|
|
90
94
|
## Have your agent set it up
|
|
@@ -262,7 +266,7 @@ and evidence checks.
|
|
|
262
266
|
inspectable JSON plans, runtime dependency audits, and planning before application
|
|
263
267
|
startup. Both use static dependency analysis; choose
|
|
264
268
|
based on your workflow, and validate selection against your own suite.
|
|
265
|
-
See the [
|
|
269
|
+
See the [comparison with pytest-impacted](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/comparison-pytest-impacted.md)
|
|
266
270
|
for portability and Git-resolution improvements adopted from that comparison.
|
|
267
271
|
|
|
268
272
|
## Contribute
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
**Run affected Python tests. See why they matter.**
|
|
1
|
+

|
|
4
2
|
|
|
3
|
+
# pytest-selective
|
|
5
4
|
[](https://github.com/gigaverse-app/pytest-selective/actions/workflows/ci.yml)
|
|
6
5
|
[](https://pypi.org/project/pytest-selective/)
|
|
7
6
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/pyproject.toml)
|
|
@@ -9,6 +8,11 @@
|
|
|
9
8
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/.pre-commit-config.yaml)
|
|
10
9
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/LICENSE)
|
|
11
10
|
[](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/agents.md)
|
|
11
|
+
[](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
|
|
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) ·
|
|
@@ -39,8 +44,8 @@ and slack. [See the source runs and method](https://github.com/gigaverse-app/ci-
|
|
|
39
44
|
| --- | --- | --- |
|
|
40
45
|
| 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
46
|
| 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@
|
|
43
|
-
| Keep whole-suite coverage or conformance checks | `gigaverse-app/pytest-selective/plan-lanes@
|
|
47
|
+
| Plan affected files in GitHub Actions | `gigaverse-app/pytest-selective@v1` | Plans before installing your application |
|
|
48
|
+
| Keep whole-suite coverage or conformance checks | `gigaverse-app/pytest-selective/actions/plan-lanes@v1` | Entire unaffected jobs, including their services and setup |
|
|
44
49
|
| 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
50
|
| Keep selection narrow as the project grows | Explanations, startup-floor budgets, expansion and isolation guards | Makes broad new fixture/import dependencies visible |
|
|
46
51
|
|
|
@@ -50,10 +55,9 @@ collects normally; the pre-collection runner and CI planner can avoid that cost.
|
|
|
50
55
|
Keep full checkpoints and use complete lanes when partial suites cannot satisfy
|
|
51
56
|
your coverage contract.
|
|
52
57
|
|
|
53
|
-
**Public-path availability:**
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
it includes these paths. Existing `.github/actions/...` paths remain supported.
|
|
58
|
+
**Public-path availability:** version 1 provides the root action and
|
|
59
|
+
`actions/NAME` paths. Use the moving `@v1` tag for compatible updates.
|
|
60
|
+
Older immutable releases retain their original layouts.
|
|
57
61
|
[Public action API](docs/actions.md).
|
|
58
62
|
|
|
59
63
|
## Have your agent set it up
|
|
@@ -231,7 +235,7 @@ and evidence checks.
|
|
|
231
235
|
inspectable JSON plans, runtime dependency audits, and planning before application
|
|
232
236
|
startup. Both use static dependency analysis; choose
|
|
233
237
|
based on your workflow, and validate selection against your own suite.
|
|
234
|
-
See the [
|
|
238
|
+
See the [comparison with pytest-impacted](https://github.com/gigaverse-app/pytest-selective/blob/main/docs/comparison-pytest-impacted.md)
|
|
235
239
|
for portability and Git-resolution improvements adopted from that comparison.
|
|
236
240
|
|
|
237
241
|
## 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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Generated by scripts/public_actions.py; edit the canonical
|
|
1
|
+
# Generated by scripts/public_actions.py; edit the canonical actions metadata.
|
|
2
2
|
name: Cached test impact selection
|
|
3
3
|
description: Select affected Python test files from both Git trees, falling back to all configured roots.
|
|
4
4
|
inputs:
|
|
@@ -86,7 +86,7 @@ runs:
|
|
|
86
86
|
using: composite
|
|
87
87
|
steps:
|
|
88
88
|
- id: action
|
|
89
|
-
uses:
|
|
89
|
+
uses: $/actions/test-impact
|
|
90
90
|
with:
|
|
91
91
|
warm-only: ${{ inputs.warm-only }}
|
|
92
92
|
config: ${{ inputs.config }}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# pytest-selective actions
|
|
2
|
+
|
|
3
|
+
Use `gigaverse-app/pytest-selective/actions/NAME@REF` for individual actions, such as
|
|
4
|
+
`gigaverse-app/pytest-selective/actions/plan-lanes@main`.
|
|
5
|
+
The root `gigaverse-app/pytest-selective@REF` action plans affected test files.
|
|
6
|
+
|
|
7
|
+
See the [action reference and version availability](../docs/actions.md) for
|
|
8
|
+
inputs, outputs and compatible pins, or start with the
|
|
9
|
+
[complete CI recipe](../docs/ci.md).
|
|
10
|
+
|
|
11
|
+
Each directory contains the actual implementation and its helpers. Only the
|
|
12
|
+
root default action is generated; refresh it with
|
|
13
|
+
`uv run python scripts/public_actions.py` after changing test-impact's metadata.
|
|
@@ -8,7 +8,7 @@ inputs:
|
|
|
8
8
|
description: Base commit containing the complete change set.
|
|
9
9
|
required: true
|
|
10
10
|
full:
|
|
11
|
-
description: Run every lane for
|
|
11
|
+
description: Run every lane for an explicit full-test checkpoint; ordinary PRs and pushes use selection.
|
|
12
12
|
default: 'false'
|
|
13
13
|
artifact-name:
|
|
14
14
|
description: >
|
|
@@ -39,7 +39,7 @@ runs:
|
|
|
39
39
|
SELECTIVE_BASE: ${{ inputs.base }}
|
|
40
40
|
SELECTIVE_FULL: ${{ inputs.full }}
|
|
41
41
|
run: |
|
|
42
|
-
export PYTHONPATH="$SELECTIVE_ACTION
|
|
42
|
+
export PYTHONPATH="$SELECTIVE_ACTION/../../src${PYTHONPATH:+:$PYTHONPATH}"
|
|
43
43
|
args=(--config "$SELECTIVE_CONFIG" --base "$SELECTIVE_BASE" --github-output "$GITHUB_OUTPUT")
|
|
44
44
|
if [ "$SELECTIVE_FULL" = true ]; then args+=(--full); fi
|
|
45
45
|
uv run --no-project --python 3.14 --with pydantic==2.13.4 --with pyyaml==6.0.3 \
|