pytest-selective 0.4.1__tar.gz → 0.4.2__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.4.2/.dry-lint/baseline.json +80 -0
- pytest_selective-0.4.2/.dry-lint/progress.json +7 -0
- pytest_selective-0.4.2/.dry-lint.toml +6 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/workflows/ci.yml +10 -7
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/workflows/docs.yml +3 -3
- pytest_selective-0.4.2/.github/workflows/dry-lint-audit.yml +91 -0
- pytest_selective-0.4.2/.github/workflows/dry-lint-judge.yml +30 -0
- pytest_selective-0.4.2/.github/workflows/dry-lint.yml +41 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/workflows/pr-title.yml +1 -1
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/workflows/public-actions.yml +1 -1
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/workflows/release-please.yml +2 -2
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/workflows/release.yml +4 -4
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/workflows/windows-performance.yml +11 -7
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.gitignore +3 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.pre-commit-config.yaml +12 -0
- pytest_selective-0.4.2/.release-please-manifest.json +3 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/AGENTS.md +5 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/CHANGELOG.md +7 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/CONTRIBUTING.md +69 -1
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/PKG-INFO +11 -1
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/README.md +10 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/actions/plan-lanes/action.yml +2 -2
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/actions/test-impact/action.yml +4 -4
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/configuration.md +11 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/local-development.md +5 -0
- pytest_selective-0.4.2/docs/work-in-progress/tickets/ratchet-duplicates-zero-test-plan.md +18 -0
- pytest_selective-0.4.2/documentation/requirements.in +2 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/documentation/requirements.txt +5 -5
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/pyproject.toml +1 -1
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/ast_imports.py +26 -2
- pytest_selective-0.4.2/src/pytest_selective/git_operations.py +49 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/hygiene.py +3 -10
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_audit_plugin.py +1 -6
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_first_party.py +4 -11
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_graph.py +18 -43
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_name_scope.py +1 -5
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/pytest_expansion.py +21 -70
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/typecheck_scope.py +4 -7
- pytest_selective-0.4.2/src/pytest_selective/working_tree.py +41 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_hygiene.py +8 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_portability.py +3 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_typecheck_scope.py +20 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_working_tree.py +78 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/uv.lock +155 -151
- pytest_selective-0.4.1/.release-please-manifest.json +0 -3
- pytest_selective-0.4.1/documentation/requirements.in +0 -2
- pytest_selective-0.4.1/src/pytest_selective/working_tree.py +0 -43
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.gitattributes +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/dependabot.yml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/test-lanes.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.github/workflows/observe-ci.yml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/.readthedocs.yaml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/CLAUDE.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/LICENSE +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/PROVENANCE.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/RELEASING.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/action.yml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/actions/README.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/actions/pytest-expansion/action.yml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/agentsync.toml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/README.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/actions.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/agents.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/assets/banner.png +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/assets/banner.svg +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/assets/brand.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/assets/icon.png +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/assets/logo.svg +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/assets/raster-sources.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/assets/social-preview.png +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/assets/social-preview.svg +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22-due-ci.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22-due-docs-ci.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22-due-docs-widget.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22-due-widget.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22-input-replays.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22-obligation-docs.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22-obligation.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22-routing.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22-selective-docs.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-22.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-23-windows-saleor/obligation-baseline.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.11.xml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-23-windows-saleor/selective-after-3.14.xml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-23-windows-saleor/selective-after.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.11.xml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-23-windows-saleor/selective-control-3.14.xml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-23-windows-saleor/selective-control.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-23-windows-saleor/selective-earlier.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/2026-10-23-windows-saleor.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/benchmarks/windows-runtime.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/ci-toolkit.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/ci.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/comparison-pytest-impacted.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/evidence.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/pytest-hygiene.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/selection-health.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/tutorial.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/tutorials/adoption-checklist.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/tutorials/sidecar-dependencies.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/tutorials/skip-unrelated-ci.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/work-in-progress/tickets/actions-directory-test-plan.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/work-in-progress/tickets/codex-selector-correctness-performance-test-plan.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/work-in-progress/tickets/codex-windows-git-performance-test-plan.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/work-in-progress/tickets/impacted-improvements-test-plan.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/work-in-progress/tickets/move-action-implementations-test-plan.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/work-in-progress/tickets/public-action-onboarding-test-plan.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/docs/work-in-progress/tickets/rerun-selection-test-plan.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/documentation/assets/routing-comparison.svg +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/documentation/check_site.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/documentation/ecosystem.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/documentation/hooks.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/documentation/index.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/documentation/overrides/main.html +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/documentation/publishing.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/mkdocs.yml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/release-please-config.json +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/benchmark_graph.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/benchmark_parsing.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/benchmark_rust.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/check_docs.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/check_metadata.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/ci_file_config.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/compare_impacted.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/measure_ci_runs.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/public_actions.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/render_brand.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/run_ci_tests.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/smoke_distribution.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/scripts/tutorial.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/skills/pytest-selective/SKILL.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/skills/pytest-selective/agents/openai.yaml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/skills/pytest-selective/references/adoption.md +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/__init__.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/__main__.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/checkpoint.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/ci.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_audit.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_cli.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_declarations.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_explanation.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_models.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/impact_selection.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/input_policy.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/local.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/parse_batch.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/plugin.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/py.typed +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/pytest_plugins.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/pytest_sharding.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/src/pytest_selective/test_inventory.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/__init__.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_checkpoint_policy.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_ci_admission.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_ci_measurements.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_ci_test_execution.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_distribution_metadata.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_public_actions.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_pytest_expansion.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_repository_ci.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_repository_hygiene.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_repository_hygiene.py.gv-dependency.yaml +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/test_tutorial.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/__init__.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/git_repo.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_ast_imports.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_ci.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_git_repo.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_global_inputs.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_impact_audit.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_impact_explanation.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_impact_first_party.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_impact_graph.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_impact_name_scope.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_parse_batch.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_pytest_plugin.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_pytest_plugins.py +0 -0
- {pytest_selective-0.4.1 → pytest_selective-0.4.2}/tests/testing/test_pytest_sharding.py +0 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": 1,
|
|
3
|
+
"contract": "fbf56a4a852e47539b956057d11e9f3ee56a986bbb3b26ac209dc491d4b45f6e",
|
|
4
|
+
"started_at": "fee809549a83ddfb432cb6599ea57ae73efbe66a",
|
|
5
|
+
"checked_at": "031cafd1748babfecff2ef2629a0320715d8fe9c",
|
|
6
|
+
"entries": [
|
|
7
|
+
{
|
|
8
|
+
"hashes": {
|
|
9
|
+
"src/pytest_selective/hygiene.py::discover_test_modules": "49e17f87bfe24aeb",
|
|
10
|
+
"src/pytest_selective/test_inventory.py::discover_test_files": "567e0cacf263d340"
|
|
11
|
+
},
|
|
12
|
+
"context_hash": "",
|
|
13
|
+
"state": "cleaned"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"hashes": {
|
|
17
|
+
"src/pytest_selective/impact_graph.py::within": "5417d89a2cedc5ea",
|
|
18
|
+
"src/pytest_selective/typecheck_scope.py::_under": "221f42a33c38887c"
|
|
19
|
+
},
|
|
20
|
+
"context_hash": "",
|
|
21
|
+
"state": "cleaned"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"hashes": {
|
|
25
|
+
"src/pytest_selective/impact_audit_plugin.py::_git": "be715e103f83b281",
|
|
26
|
+
"src/pytest_selective/impact_graph.py::git": "a53bf9a83105b354"
|
|
27
|
+
},
|
|
28
|
+
"context_hash": "",
|
|
29
|
+
"state": "cleaned"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"hashes": {
|
|
33
|
+
"src/pytest_selective/impact_audit_plugin.py::_git": "be715e103f83b281",
|
|
34
|
+
"src/pytest_selective/pytest_expansion.py::git": "42cac77499ad42b1"
|
|
35
|
+
},
|
|
36
|
+
"context_hash": "",
|
|
37
|
+
"state": "cleaned"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"hashes": {
|
|
41
|
+
"src/pytest_selective/impact_first_party.py::_module_name": "c214530cc8698c18",
|
|
42
|
+
"src/pytest_selective/pytest_expansion.py::SourceTree.module_name": "633b2e80dfaac9e6"
|
|
43
|
+
},
|
|
44
|
+
"context_hash": "",
|
|
45
|
+
"state": "cleaned"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"hashes": {
|
|
49
|
+
"src/pytest_selective/impact_graph.py::git": "a53bf9a83105b354",
|
|
50
|
+
"src/pytest_selective/pytest_expansion.py::git": "42cac77499ad42b1"
|
|
51
|
+
},
|
|
52
|
+
"context_hash": "",
|
|
53
|
+
"state": "cleaned"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"hashes": {
|
|
57
|
+
"src/pytest_selective/impact_graph.py::git_environment": "1b32a738ac740022",
|
|
58
|
+
"src/pytest_selective/pytest_expansion.py::git_environment": "df7139fadaa213a9"
|
|
59
|
+
},
|
|
60
|
+
"context_hash": "",
|
|
61
|
+
"state": "cleaned"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"hashes": {
|
|
65
|
+
"src/pytest_selective/impact_name_scope.py::_casefold": "9ecabff1de943de2",
|
|
66
|
+
"src/pytest_selective/impact_graph.py::ModuleIndex.resolve": "a1089dfe99f751cd"
|
|
67
|
+
},
|
|
68
|
+
"context_hash": "",
|
|
69
|
+
"state": "cleaned"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"hashes": {
|
|
73
|
+
"src/pytest_selective/impact_name_scope.py::_casefold": "9ecabff1de943de2",
|
|
74
|
+
"src/pytest_selective/impact_graph.py::ModuleIndex.__init__": "84c3976fe798fb7e"
|
|
75
|
+
},
|
|
76
|
+
"context_hash": "",
|
|
77
|
+
"state": "cleaned"
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
@@ -20,7 +20,7 @@ jobs:
|
|
|
20
20
|
mode: ${{ steps.files.outputs.mode }}
|
|
21
21
|
files: ${{ steps.files.outputs.test_roots_json }}
|
|
22
22
|
steps:
|
|
23
|
-
- uses: actions/checkout@
|
|
23
|
+
- uses: actions/checkout@v7
|
|
24
24
|
with:
|
|
25
25
|
fetch-depth: 0
|
|
26
26
|
- id: plan
|
|
@@ -41,11 +41,14 @@ jobs:
|
|
|
41
41
|
quality:
|
|
42
42
|
runs-on: ubuntu-latest
|
|
43
43
|
steps:
|
|
44
|
-
- uses: actions/checkout@
|
|
44
|
+
- uses: actions/checkout@v7
|
|
45
45
|
- uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
|
|
46
46
|
with:
|
|
47
47
|
python-version: '3.14'
|
|
48
|
+
# Semantic judging owns its credentials and fork boundary in the required dry-lint job.
|
|
48
49
|
- run: uv run --locked pre-commit run --all-files
|
|
50
|
+
env:
|
|
51
|
+
SKIP: dry-lint
|
|
49
52
|
- name: Check aggregate gate against the execution lanes
|
|
50
53
|
run: >-
|
|
51
54
|
uv run --no-project --python 3.14
|
|
@@ -65,7 +68,7 @@ jobs:
|
|
|
65
68
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
66
69
|
runs-on: ${{ matrix.os }}
|
|
67
70
|
steps:
|
|
68
|
-
- uses: actions/checkout@
|
|
71
|
+
- uses: actions/checkout@v7
|
|
69
72
|
- uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
|
|
70
73
|
with:
|
|
71
74
|
python-version: ${{ matrix.python }}
|
|
@@ -90,7 +93,7 @@ jobs:
|
|
|
90
93
|
junit-pattern: test-timings.xml
|
|
91
94
|
artifact-name: test-timings-${{ matrix.python }}-${{ matrix.os }}
|
|
92
95
|
- run: uv run --locked python scripts/tutorial.py --output tutorial-report.json
|
|
93
|
-
- uses: actions/upload-artifact@
|
|
96
|
+
- uses: actions/upload-artifact@v7
|
|
94
97
|
with:
|
|
95
98
|
name: evidence-${{ matrix.os }}-${{ matrix.python }}
|
|
96
99
|
path: |
|
|
@@ -103,7 +106,7 @@ jobs:
|
|
|
103
106
|
fromJSON(needs.select-tests.outputs.lanes).tests) }}
|
|
104
107
|
runs-on: ubuntu-latest
|
|
105
108
|
steps:
|
|
106
|
-
- uses: actions/checkout@
|
|
109
|
+
- uses: actions/checkout@v7
|
|
107
110
|
- uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
|
|
108
111
|
with:
|
|
109
112
|
python-version: '3.11'
|
|
@@ -120,7 +123,7 @@ jobs:
|
|
|
120
123
|
if: ${{ !cancelled() }}
|
|
121
124
|
runs-on: ubuntu-latest
|
|
122
125
|
steps:
|
|
123
|
-
- uses: actions/checkout@
|
|
126
|
+
- uses: actions/checkout@v7
|
|
124
127
|
- uses: gigaverse-app/ci-esta/actions/setup-cached-uv@v1
|
|
125
128
|
with:
|
|
126
129
|
python-version: '3.14'
|
|
@@ -132,7 +135,7 @@ jobs:
|
|
|
132
135
|
${{ needs.select-tests.result != 'success' ||
|
|
133
136
|
fromJSON(needs.select-tests.outputs.lanes).tests }}
|
|
134
137
|
run: uv run --locked python scripts/smoke_distribution.py
|
|
135
|
-
- uses: actions/upload-artifact@
|
|
138
|
+
- uses: actions/upload-artifact@v7
|
|
136
139
|
with:
|
|
137
140
|
name: distributions
|
|
138
141
|
path: dist/*
|
|
@@ -13,8 +13,8 @@ jobs:
|
|
|
13
13
|
docs:
|
|
14
14
|
runs-on: ubuntu-latest
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
17
|
-
- uses: actions/setup-python@
|
|
16
|
+
- uses: actions/checkout@v7
|
|
17
|
+
- uses: actions/setup-python@v7
|
|
18
18
|
with:
|
|
19
19
|
python-version: '3.13'
|
|
20
20
|
cache: pip
|
|
@@ -23,7 +23,7 @@ jobs:
|
|
|
23
23
|
- run: python scripts/render_brand.py --check
|
|
24
24
|
- run: python -m mkdocs build --strict
|
|
25
25
|
- run: python documentation/check_site.py
|
|
26
|
-
- uses: actions/upload-artifact@
|
|
26
|
+
- uses: actions/upload-artifact@v7
|
|
27
27
|
with:
|
|
28
28
|
name: documentation-site
|
|
29
29
|
path: site/
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: dry-lint audit
|
|
2
|
+
# Audits the whole repository against the accepted backlog, then ratchets it: pairs that were refactored away or
|
|
3
|
+
# judged separate are recorded as cleaned in .dry-lint/baseline.json, progress.json and the README block, through a
|
|
4
|
+
# pull request that runs the ordinary checks. The baseline only ever shrinks; a new blocking pair fails the audit
|
|
5
|
+
# and no ratchet pull request is opened. Run it by hand after merging a cleanup to record the progress at once.
|
|
6
|
+
on:
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: '23 6 * * 1'
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
workflow_call:
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
concurrency:
|
|
14
|
+
group: dry-lint-audit
|
|
15
|
+
cancel-in-progress: false
|
|
16
|
+
jobs:
|
|
17
|
+
audit:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v7
|
|
21
|
+
with:
|
|
22
|
+
persist-credentials: false
|
|
23
|
+
- uses: gigaverse-app/dry-lint@v1
|
|
24
|
+
with:
|
|
25
|
+
mode: sweep
|
|
26
|
+
base: HEAD
|
|
27
|
+
python-version: '3.13'
|
|
28
|
+
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
29
|
+
plugins: anthropic==2.4.0
|
|
30
|
+
baseline: .dry-lint/baseline.json
|
|
31
|
+
require-complete: 'true'
|
|
32
|
+
budget-usd: '5'
|
|
33
|
+
- name: Retain the audit for human or agent review
|
|
34
|
+
if: always()
|
|
35
|
+
uses: actions/upload-artifact@v7
|
|
36
|
+
with:
|
|
37
|
+
name: dry-lint-audit
|
|
38
|
+
path: |
|
|
39
|
+
${{ runner.temp }}/dry-lint/report.json
|
|
40
|
+
${{ runner.temp }}/dry-lint/comment.md
|
|
41
|
+
retention-days: 30
|
|
42
|
+
if-no-files-found: warn
|
|
43
|
+
- name: Require ratchet PR authentication
|
|
44
|
+
env:
|
|
45
|
+
HAS_RATCHET_TOKEN: ${{ secrets.GV_CI_CROSS_REPO_TOKEN != '' }}
|
|
46
|
+
run: |
|
|
47
|
+
if [[ "$HAS_RATCHET_TOKEN" != "true" ]]; then
|
|
48
|
+
echo "::error::Configure the adopter-owned GV_CI_CROSS_REPO_TOKEN with contents and pull-request write access."
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
# The Action's sweep mode only audits. The CLI records the ratchet, reusing the verdicts the audit just stored,
|
|
52
|
+
# and the exact CLI environment installed by the Action. No second install or judge-version drift.
|
|
53
|
+
- name: Record cleaned pairs
|
|
54
|
+
env:
|
|
55
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
56
|
+
run: |
|
|
57
|
+
dry-lint sweep --update --store "$RUNNER_TEMP/dry-lint/verdicts" --budget-usd 5 \
|
|
58
|
+
--readme README.md --repository "$GITHUB_REPOSITORY" --branch main
|
|
59
|
+
# One standing branch: a later run updates the open ratchet PR instead of stacking another. The adopter-owned
|
|
60
|
+
# credential makes the PR run ordinary CI, including the required dry-lint check that refuses any widening.
|
|
61
|
+
- uses: peter-evans/create-pull-request@v8
|
|
62
|
+
with:
|
|
63
|
+
token: ${{ secrets.GV_CI_CROSS_REPO_TOKEN }}
|
|
64
|
+
branch: dry-lint/ratchet
|
|
65
|
+
delete-branch: true
|
|
66
|
+
add-paths: |
|
|
67
|
+
.dry-lint/baseline.json
|
|
68
|
+
.dry-lint/progress.json
|
|
69
|
+
README.md
|
|
70
|
+
commit-message: 'chore(dry-lint): record cleaned duplicate pairs in the baseline'
|
|
71
|
+
title: 'chore(dry-lint): record cleaned duplicate pairs in the baseline'
|
|
72
|
+
body: |
|
|
73
|
+
## TLDR
|
|
74
|
+
|
|
75
|
+
The weekly dry-lint audit found accepted duplicate pairs that no longer exist or were judged separate,
|
|
76
|
+
and shrinks `.dry-lint/baseline.json`, the progress badge and the README block to match.
|
|
77
|
+
|
|
78
|
+
The baseline can only shrink: the required `dry-lint` check rejects any pull request that widens it.
|
|
79
|
+
The full audit is in the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}).
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
BEFORE: merged cleanup -> accepted baseline and README still show old debt
|
|
83
|
+
AFTER: complete audit -> reviewed metadata PR -> baseline and README record cleanup
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
| Policy | Before | After |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| Accepted pairs | Previously recorded states | Removed/separate pairs marked cleaned; explicit exclusions dismissed |
|
|
89
|
+
| New debt | Rejected | Still rejected; no added allowances |
|
|
90
|
+
|
|
91
|
+
Pair-count changes appear in the baseline/progress diff and the linked audit. No application code changes.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: dry-lint judge
|
|
2
|
+
on:
|
|
3
|
+
workflow_run:
|
|
4
|
+
workflows: [dry-lint]
|
|
5
|
+
types: [completed]
|
|
6
|
+
permissions:
|
|
7
|
+
actions: read
|
|
8
|
+
checks: write
|
|
9
|
+
contents: read
|
|
10
|
+
pull-requests: write
|
|
11
|
+
concurrency:
|
|
12
|
+
group: dry-lint-judge-${{ github.event.workflow_run.head_branch }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
jobs:
|
|
15
|
+
judge:
|
|
16
|
+
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.head_repository.full_name != github.repository
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
# Only trusted default-branch settings and baseline; fork code is artifact data.
|
|
20
|
+
- uses: actions/checkout@v7
|
|
21
|
+
with:
|
|
22
|
+
persist-credentials: false
|
|
23
|
+
- uses: gigaverse-app/dry-lint@v1
|
|
24
|
+
with:
|
|
25
|
+
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
26
|
+
plugins: anthropic==2.4.0
|
|
27
|
+
baseline: .dry-lint/baseline.json
|
|
28
|
+
require-complete: 'true'
|
|
29
|
+
comment: 'true'
|
|
30
|
+
comment-on-clean: 'true'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: dry-lint
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
types: [opened, synchronize, reopened]
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
pull-requests: write
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: dry-lint-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }}
|
|
15
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
check:
|
|
19
|
+
# A detection-only fork job must never satisfy the required judged check.
|
|
20
|
+
name: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && 'dry-lint detect' || 'dry-lint' }}
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v7
|
|
24
|
+
with:
|
|
25
|
+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
26
|
+
fetch-depth: 1
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
- uses: gigaverse-app/dry-lint@v1
|
|
29
|
+
with:
|
|
30
|
+
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
31
|
+
plugins: anthropic==2.4.0
|
|
32
|
+
baseline: .dry-lint/baseline.json
|
|
33
|
+
require-complete: 'true'
|
|
34
|
+
comment: 'true'
|
|
35
|
+
comment-on-clean: 'true'
|
|
36
|
+
|
|
37
|
+
audit:
|
|
38
|
+
# Manual full validation also exercises the scheduled ratchet before its first merge.
|
|
39
|
+
if: github.event_name == 'workflow_dispatch'
|
|
40
|
+
uses: ./.github/workflows/dry-lint-audit.yml
|
|
41
|
+
secrets: inherit
|
|
@@ -14,7 +14,7 @@ jobs:
|
|
|
14
14
|
timeout-minutes: 5
|
|
15
15
|
steps:
|
|
16
16
|
# Only reads PR metadata. Never check out or execute PR code in this workflow.
|
|
17
|
-
- uses: amannn/action-semantic-pull-request@
|
|
17
|
+
- uses: amannn/action-semantic-pull-request@v6
|
|
18
18
|
with:
|
|
19
19
|
types: |
|
|
20
20
|
feat
|
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
fromJSON(needs.select-tests.outputs.lanes).tests) }}
|
|
28
28
|
runs-on: ubuntu-latest
|
|
29
29
|
steps:
|
|
30
|
-
- uses: actions/checkout@
|
|
30
|
+
- uses: actions/checkout@v7
|
|
31
31
|
with:
|
|
32
32
|
fetch-depth: 0
|
|
33
33
|
- name: Use the reviewed repository graph
|
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
steps:
|
|
29
29
|
- name: Only process the tested main head
|
|
30
30
|
id: current
|
|
31
|
-
uses: actions/github-script@
|
|
31
|
+
uses: actions/github-script@v9
|
|
32
32
|
with:
|
|
33
33
|
script: |
|
|
34
34
|
const {data: branch} = await github.rest.repos.getBranch({...context.repo, branch: 'main'});
|
|
@@ -44,7 +44,7 @@ jobs:
|
|
|
44
44
|
fi
|
|
45
45
|
- name: Prepare release PR or publish its GitHub release
|
|
46
46
|
if: steps.current.outputs.matches == 'true'
|
|
47
|
-
uses: googleapis/release-please-action@
|
|
47
|
+
uses: googleapis/release-please-action@v5
|
|
48
48
|
with:
|
|
49
49
|
# This credential triggers CI on release PRs and Publish on releases.
|
|
50
50
|
# GITHUB_TOKEN would suppress those follow-up workflow events.
|
|
@@ -10,8 +10,8 @@ jobs:
|
|
|
10
10
|
validate-tag:
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
steps:
|
|
13
|
-
- uses: actions/checkout@
|
|
14
|
-
- uses: astral-sh/setup-uv@
|
|
13
|
+
- uses: actions/checkout@v7
|
|
14
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
15
15
|
with:
|
|
16
16
|
python-version: '3.14'
|
|
17
17
|
- name: Require a version-matching tag
|
|
@@ -31,12 +31,12 @@ jobs:
|
|
|
31
31
|
permissions:
|
|
32
32
|
id-token: write
|
|
33
33
|
steps:
|
|
34
|
-
- uses: actions/download-artifact@
|
|
34
|
+
- uses: actions/download-artifact@v8
|
|
35
35
|
with:
|
|
36
36
|
name: distributions
|
|
37
37
|
path: dist
|
|
38
38
|
- name: Publish tested distributions with attestations
|
|
39
|
-
uses: pypa/gh-action-pypi-publish@
|
|
39
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
40
40
|
|
|
41
41
|
action-version:
|
|
42
42
|
needs: publish
|
|
@@ -21,34 +21,38 @@ jobs:
|
|
|
21
21
|
matrix:
|
|
22
22
|
python: ['3.11', '3.14']
|
|
23
23
|
steps:
|
|
24
|
-
- uses: actions/checkout@
|
|
24
|
+
- uses: actions/checkout@v7
|
|
25
25
|
with:
|
|
26
26
|
ref: ${{ inputs.baseline || github.event.pull_request.base.sha }}
|
|
27
27
|
path: baseline
|
|
28
|
-
- uses: actions/checkout@
|
|
28
|
+
- uses: actions/checkout@v7
|
|
29
29
|
with:
|
|
30
30
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
31
31
|
path: candidate
|
|
32
|
-
- uses: astral-sh/setup-uv@
|
|
32
|
+
- uses: astral-sh/setup-uv@v10.3.3
|
|
33
33
|
with:
|
|
34
34
|
python-version: ${{ matrix.python }}
|
|
35
35
|
cache-suffix: matched-windows-${{ matrix.python }}
|
|
36
36
|
- run: uv sync --directory baseline --locked
|
|
37
37
|
- run: uv sync --directory candidate --locked
|
|
38
|
+
- name: Preserve the baseline Git search path
|
|
39
|
+
shell: pwsh
|
|
40
|
+
run: '"BASELINE_GIT_PATH=$env:PATH" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append'
|
|
41
|
+
- uses: gigaverse-app/ci-esta/actions/native-windows-git@v1
|
|
38
42
|
- name: Run complete suites in both orders on the same worker
|
|
39
43
|
shell: pwsh
|
|
40
44
|
run: |
|
|
41
45
|
$results = Join-Path $env:GITHUB_WORKSPACE 'measurements'
|
|
42
46
|
New-Item -ItemType Directory -Path $results | Out-Null
|
|
43
47
|
$measurements = @()
|
|
44
|
-
$originalPath = $env:
|
|
48
|
+
$originalPath = $env:BASELINE_GIT_PATH
|
|
49
|
+
$nativeGitPath = $env:PATH
|
|
45
50
|
foreach ($sample in @('baseline-1', 'candidate-1', 'candidate-2', 'baseline-2')) {
|
|
46
51
|
$arm = $sample.Split('-')[0]
|
|
47
52
|
Push-Location (Join-Path $env:GITHUB_WORKSPACE $arm)
|
|
48
53
|
try {
|
|
49
54
|
# Start every arm with the same PATH; only the candidate opts in.
|
|
50
|
-
$env:PATH = $originalPath
|
|
51
|
-
if ($arm -eq 'candidate') { ./scripts/use_native_windows_git.ps1 }
|
|
55
|
+
$env:PATH = if ($arm -eq 'candidate') { $nativeGitPath } else { $originalPath }
|
|
52
56
|
$sha = git rev-parse HEAD
|
|
53
57
|
# Keep repeated arms from timing cleanup of an earlier arm's Git fixtures.
|
|
54
58
|
$temp = Join-Path $env:RUNNER_TEMP "matched-pytest-$sample"
|
|
@@ -63,7 +67,7 @@ jobs:
|
|
|
63
67
|
if ($result -ne 0) { throw "${sample} failed: $result" }
|
|
64
68
|
} finally { Pop-Location }
|
|
65
69
|
}
|
|
66
|
-
- uses: actions/upload-artifact@
|
|
70
|
+
- uses: actions/upload-artifact@v7
|
|
67
71
|
if: always()
|
|
68
72
|
with:
|
|
69
73
|
name: matched-windows-${{ matrix.python }}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
minimum_pre_commit_version: '4.3.0'
|
|
2
|
+
default_install_hook_types: [pre-commit, prepare-commit-msg]
|
|
3
|
+
default_stages: [pre-commit]
|
|
1
4
|
repos:
|
|
2
5
|
- repo: local
|
|
3
6
|
hooks:
|
|
@@ -17,3 +20,12 @@ repos:
|
|
|
17
20
|
language: system
|
|
18
21
|
pass_filenames: false
|
|
19
22
|
types: [markdown]
|
|
23
|
+
|
|
24
|
+
- repo: https://github.com/gigaverse-app/dry-lint
|
|
25
|
+
rev: v1
|
|
26
|
+
hooks:
|
|
27
|
+
- id: dry-lint
|
|
28
|
+
args: [--preset, sonnet, --baseline, .dry-lint/baseline.json]
|
|
29
|
+
language_version: python3.13
|
|
30
|
+
- id: dry-lint-trailers
|
|
31
|
+
language_version: python3.13
|
|
@@ -67,3 +67,8 @@ workflows, selector configuration, helpers, locks and non-import inputs; missing
|
|
|
67
67
|
history or failed planning must execute the full affected lanes and fail the
|
|
68
68
|
required planning gate. Ordinary PRs and pushes use selection; manual/release/scheduled/full overrides
|
|
69
69
|
remain complete checkpoints.
|
|
70
|
+
|
|
71
|
+
## GitHub Actions versions
|
|
72
|
+
|
|
73
|
+
- ALWAYS use published major-version tags for established GitHub Actions, for example `actions/checkout@v7` and `actions/upload-artifact@v7`, so compatible fixes arrive without per-commit maintenance. NEVER replace those tags with commit hashes unless the user explicitly requests that exact exception. If a publisher has no major-version tag, use its published release tag rather than inventing a ref or substituting a hash.
|
|
74
|
+
- ALWAYS use `gigaverse-app/dry-lint@main` until its v1 launch, then use `@v1`. Apply the same ref in workflow examples and adoption instructions.
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.2](https://github.com/gigaverse-app/pytest-selective/compare/v0.4.1...v0.4.2) (2026-11-07)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug fixes
|
|
7
|
+
|
|
8
|
+
* consolidate duplicated selection helpers and retire baseline debt ([#77](https://github.com/gigaverse-app/pytest-selective/issues/77)) ([a7427bf](https://github.com/gigaverse-app/pytest-selective/commit/a7427bf6f550789a835a38f3326b8a971bef114f))
|
|
9
|
+
|
|
3
10
|
## [0.4.1](https://github.com/gigaverse-app/pytest-selective/compare/v0.4.0...v0.4.1) (2026-10-24)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -32,6 +32,23 @@ Changes to collection policy, runtime auditing, or the composite action need tes
|
|
|
32
32
|
at that boundary. Update the tutorial when the public command contract changes.
|
|
33
33
|
Keep performance claims tied to reproducible measurements and their limitations.
|
|
34
34
|
|
|
35
|
+
### Shared implementation owners
|
|
36
|
+
|
|
37
|
+
| Contract | Owner |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| Repository-scoped Git, hook environment isolation, binary and UTF-8 output | `git_operations.py` |
|
|
40
|
+
| Private working-tree snapshots, staged inputs and index timestamp preservation | `working_tree.py` |
|
|
41
|
+
| Python module names, Unicode matching and dotted import relationships | `ast_imports.py` |
|
|
42
|
+
| Test-file discovery and cache exclusions | `test_inventory.py` |
|
|
43
|
+
| Repository-relative path containment, including the dot root | `impact_graph.within` |
|
|
44
|
+
|
|
45
|
+
The expansion guard imports the first three owners directly when run as a script;
|
|
46
|
+
keep them stdlib-only. Its snapshot updates Python paths and preserves the stat
|
|
47
|
+
cache; the planner rebuilds the staged entries to see edits hidden by index flags
|
|
48
|
+
and updates all inputs. Preserve the copied index timestamp: Git uses it to detect
|
|
49
|
+
same-size edits made within its stat-cache window. The snapshot tests cover ordinary indexes,
|
|
50
|
+
split indexes and linked worktrees without modifying the user's index or HEAD.
|
|
51
|
+
|
|
35
52
|
## CI and dependency maintenance
|
|
36
53
|
|
|
37
54
|
CI tests Python 3.11 and 3.14 on Linux, Windows, and macOS. A separate job checks
|
|
@@ -41,7 +58,8 @@ environment on both Python versions. Evidence artifacts carry coverage and tutor
|
|
|
41
58
|
|
|
42
59
|
Use `uv lock --upgrade-package NAME` for a targeted dependency update and run the
|
|
43
60
|
affected checks. Dependabot proposes weekly uv and GitHub Actions updates.
|
|
44
|
-
Actions
|
|
61
|
+
Established Actions use published major-version tags; use a published release tag when no major tag exists.
|
|
62
|
+
Review release notes when upgrading a major version.
|
|
45
63
|
|
|
46
64
|
## Pull requests
|
|
47
65
|
|
|
@@ -152,3 +170,53 @@ workflows, selector configuration, helpers, locks and non-import inputs; missing
|
|
|
152
170
|
history or failed planning must execute the full affected lanes and fail the
|
|
153
171
|
required planning gate. Ordinary PRs and pushes use selection; manual/release/scheduled/full overrides
|
|
154
172
|
remain complete checkpoints.
|
|
173
|
+
|
|
174
|
+
## Duplication
|
|
175
|
+
|
|
176
|
+
`uv run pre-commit install` installs both the staged dry-lint check and the
|
|
177
|
+
`prepare-commit-msg` trailer hook, alongside Ruff and documentation checks.
|
|
178
|
+
Put your own `ANTHROPIC_API_KEY` in the shell or the ignored `.env`. The hook uses
|
|
179
|
+
Sonnet, Python 3.13 and the same accepted baseline as CI. Missing judge credentials
|
|
180
|
+
fail strict checking. The trailer records duplicates fixed before the first push,
|
|
181
|
+
so the PR sticky includes that local prevention credit.
|
|
182
|
+
|
|
183
|
+
The required judged `dry-lint` check rejects new blocking duplicates, incomplete
|
|
184
|
+
judgments and baseline widening. Forks detect candidates without secrets; the
|
|
185
|
+
trusted judge workflow assesses their artifacts. CI's general quality job skips
|
|
186
|
+
only the semantic hook, because the dedicated required job owns judging and its
|
|
187
|
+
credentials. Other pre-commit hooks still run there.
|
|
188
|
+
|
|
189
|
+
When a finding appears, inspect both functions. Reuse the existing owner when they
|
|
190
|
+
implement one concept, preserve selection/fallback behavior and run the affected
|
|
191
|
+
tests. For genuinely distinct concepts, add a narrow `distinct-from` comment and
|
|
192
|
+
its reason. Do not weaken thresholds or use blanket ignores to make CI pass.
|
|
193
|
+
|
|
194
|
+
The PR sticky tracks findings and fixes across pushes. Every default-branch push
|
|
195
|
+
can finish folding merged PRs into the repository ledger. The README sign shows
|
|
196
|
+
new duplicates prevented separately from old debt cleaned and remaining. Counts
|
|
197
|
+
are pairs, not lines or estimated time savings; dismissals never count as cleanup.
|
|
198
|
+
The cache-backed ledger starts a new accounting period if evicted.
|
|
199
|
+
|
|
200
|
+
The weekly/manual **dry-lint audit** retains its reports, then opens or updates one
|
|
201
|
+
`dry-lint/ratchet` PR with only the baseline, progress JSON and README metadata.
|
|
202
|
+
The inherited `GV_CI_CROSS_REPO_TOKEN` lets that PR run ordinary CI. New debt,
|
|
203
|
+
incomplete judging or missing authentication fails visibly. Humans and agents
|
|
204
|
+
choose refactors; the audit never edits application code or merges its own PR.
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
uv tool install --no-config --python 3.13 'dry-lint[anthropic] @ git+https://github.com/gigaverse-app/dry-lint@v1'
|
|
208
|
+
dry-lint sweep --budget-usd 5 --report audit.json --output audit.md
|
|
209
|
+
# Review both sides, refactor and test before recording progress.
|
|
210
|
+
dry-lint sweep --update --budget-usd 5 --readme README.md --repository gigaverse-app/pytest-selective --repository-id 1430133155
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Commit the generated metadata with a cleanup, or dispatch the audit after the
|
|
214
|
+
cleanup merges. A manual run of the **dry-lint** workflow also calls the same
|
|
215
|
+
reusable audit, allowing validation on an adoption branch before the new scheduled
|
|
216
|
+
workflow exists on `main`. Ratchet PRs target the selected branch. Preserve the nine-pair adoption history; never delete and
|
|
217
|
+
reinitialize the baseline. No-change audits produce no metadata diff. Keep raw
|
|
218
|
+
reports and verdict caches outside Git. The scope uses dry-lint's default
|
|
219
|
+
exclusions; changes to detection policy require an explicitly reviewed migration.
|
|
220
|
+
|
|
221
|
+
See the [full adoption playbook](https://github.com/gigaverse-app/dry-lint/blob/main/docs/adoption-playbook.md)
|
|
222
|
+
and [sweep semantics](https://github.com/gigaverse-app/dry-lint/blob/main/docs/sweeps.md).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pytest-selective
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
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://pytest-selective.readthedocs.io/en/latest/
|
|
@@ -316,3 +316,13 @@ show provenance, runner cost and the actual dependency paths. This repository
|
|
|
316
316
|
also uses CI-esta's shared native Windows Git action while retaining full
|
|
317
317
|
coverage on all six Python/platform lanes.
|
|
318
318
|
|
|
319
|
+
### Duplicates kept out
|
|
320
|
+
|
|
321
|
+
Local hooks and the required PR check prevent new copies. The weekly audit
|
|
322
|
+
records progress against the accepted backlog. [Setup and cleanup workflow](CONTRIBUTING.md#duplication).
|
|
323
|
+
|
|
324
|
+
<!-- dry-lint-progress:start -->
|
|
325
|
+
<a href="https://github.com/gigaverse-app/dry-lint"><picture><source media="(prefers-color-scheme: dark)" srcset="https://dry-lint-counter.gigaverse-oss.workers.dev/v1/sign.svg?theme=dark&key=f8e41d50ca4018845c305f2f0dbd1cfd6d9b281e53b352490af53154a54e6265&name=gigaverse-app%2Fpytest-selective&cleaned=9&remaining=0&dismissed=0"><img alt="dry-lint in gigaverse-app/pytest-selective: new duplicates kept out of its pull requests, 9 old duplicates cleaned up, 0 remaining" src="https://dry-lint-counter.gigaverse-oss.workers.dev/v1/sign.svg?key=f8e41d50ca4018845c305f2f0dbd1cfd6d9b281e53b352490af53154a54e6265&name=gigaverse-app%2Fpytest-selective&cleaned=9&remaining=0&dismissed=0" width="100%"></picture></a>
|
|
326
|
+
|
|
327
|
+
[Accepted backlog](.dry-lint/baseline.json) · [Weekly audit](https://github.com/gigaverse-app/pytest-selective/actions/workflows/dry-lint-audit.yml)
|
|
328
|
+
<!-- dry-lint-progress:end -->
|
|
@@ -285,3 +285,13 @@ show provenance, runner cost and the actual dependency paths. This repository
|
|
|
285
285
|
also uses CI-esta's shared native Windows Git action while retaining full
|
|
286
286
|
coverage on all six Python/platform lanes.
|
|
287
287
|
|
|
288
|
+
### Duplicates kept out
|
|
289
|
+
|
|
290
|
+
Local hooks and the required PR check prevent new copies. The weekly audit
|
|
291
|
+
records progress against the accepted backlog. [Setup and cleanup workflow](CONTRIBUTING.md#duplication).
|
|
292
|
+
|
|
293
|
+
<!-- dry-lint-progress:start -->
|
|
294
|
+
<a href="https://github.com/gigaverse-app/dry-lint"><picture><source media="(prefers-color-scheme: dark)" srcset="https://dry-lint-counter.gigaverse-oss.workers.dev/v1/sign.svg?theme=dark&key=f8e41d50ca4018845c305f2f0dbd1cfd6d9b281e53b352490af53154a54e6265&name=gigaverse-app%2Fpytest-selective&cleaned=9&remaining=0&dismissed=0"><img alt="dry-lint in gigaverse-app/pytest-selective: new duplicates kept out of its pull requests, 9 old duplicates cleaned up, 0 remaining" src="https://dry-lint-counter.gigaverse-oss.workers.dev/v1/sign.svg?key=f8e41d50ca4018845c305f2f0dbd1cfd6d9b281e53b352490af53154a54e6265&name=gigaverse-app%2Fpytest-selective&cleaned=9&remaining=0&dismissed=0" width="100%"></picture></a>
|
|
295
|
+
|
|
296
|
+
[Accepted backlog](.dry-lint/baseline.json) · [Weekly audit](https://github.com/gigaverse-app/pytest-selective/actions/workflows/dry-lint-audit.yml)
|
|
297
|
+
<!-- dry-lint-progress:end -->
|