claude-dev-env 2.4.0 → 2.7.0
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.
- package/CLAUDE.md +26 -59
- package/_shared/pr-loop/scripts/_claude_permissions_common.py +84 -0
- package/_shared/pr-loop/scripts/code_rules_gate.py +6 -3
- package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +12 -2
- package/_shared/pr-loop/scripts/code_rules_gate_parts/baseline_import_isolation.py +309 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_regression.py +540 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_running.py +206 -70
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/__init__.py +1 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/_repo_test_helpers.py +76 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_baseline_import_isolation.py +248 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_regression.py +309 -0
- package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_running.py +91 -58
- package/_shared/pr-loop/scripts/grant_project_claude_permissions.py +306 -306
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/claude_permissions_constants.py +44 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +202 -0
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/copilot_quota_constants.py +24 -24
- package/_shared/pr-loop/scripts/pr_loop_shared_constants/stale_worktree_rule_sweep_constants.py +107 -107
- package/_shared/pr-loop/scripts/revoke_project_claude_permissions.py +290 -48
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_common.py +42 -2
- package/_shared/pr-loop/scripts/tests/test_claude_permissions_constants.py +36 -0
- package/_shared/pr-loop/scripts/tests/test_code_rules_gate.py +100 -1
- package/_shared/pr-loop/scripts/tests/test_fix_hookspath.py +497 -497
- package/_shared/pr-loop/scripts/tests/test_revoke_project_claude_permissions.py +311 -2
- package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep.py +301 -301
- package/_shared/pr-loop/scripts/tests/test_stale_worktree_rule_sweep_constants.py +85 -85
- package/_shared/pr-loop/worker-spawn.md +1 -1
- package/agents/CLAUDE.md +3 -2
- package/agents/caveman.md +0 -1
- package/agents/clasp-deployment-orchestrator.md +0 -1
- package/agents/clean-coder.md +0 -1
- package/agents/code-advisor.md +0 -1
- package/agents/code-quality-agent.md +1 -2
- package/agents/code-verifier.md +36 -8
- package/agents/deep-research.md +0 -1
- package/agents/docs-agent.md +0 -1
- package/agents/git-commit-crafter.md +0 -1
- package/agents/issue-tracker.md +42 -0
- package/agents/plan-packet-validator.md +0 -1
- package/agents/pr-description-writer.md +0 -1
- package/agents/test_agent_frontmatter.py +67 -18
- package/audit-rubrics/category_rubrics/category-o-docstring-vs-impl-drift.md +143 -141
- package/bin/CLAUDE.md +68 -5
- package/bin/codex-compat.mjs +104 -0
- package/bin/codex-compat.test.mjs +51 -0
- package/bin/ever-shipped-skills.mjs +1 -0
- package/bin/install-constants.mjs +88 -0
- package/bin/install.mjs +1138 -114
- package/bin/install.prune.test.mjs +869 -19
- package/bin/install.test.mjs +906 -2
- package/codex-capability-map.json +13 -0
- package/commands/implement.md +1 -1
- package/commands/right-size.md +1 -1
- package/docs/CLAUDE.md +1 -0
- package/docs/CODE_RULES.md +2 -0
- package/docs/codex-compatibility.md +25 -0
- package/docs/host-pool-health-monitor.md +102 -0
- package/docs/nas-ssh-invocation.md +96 -12
- package/docs/references/CLAUDE.md +4 -2
- package/docs/references/advisor-tool.md +13 -0
- package/docs/references/code-review-enforcement.md +35 -0
- package/docs/references/team-advisor-skill.md +14 -0
- package/hooks/blocking/CLAUDE.md +4 -0
- package/hooks/blocking/code_review_pr_create_gate.py +7 -3
- package/hooks/blocking/code_review_push_gate.py +9 -4
- package/hooks/blocking/code_review_stamp_directory_write_blocker.py +8 -0
- package/hooks/blocking/config/__init__.py +5 -5
- package/hooks/blocking/config/code_review_enforcement_constants.py +40 -7
- package/hooks/blocking/config/test_code_review_enforcement_constants.py +58 -0
- package/hooks/blocking/config/verified_commit_constants.py +160 -159
- package/hooks/blocking/eli11_reply_enforcer.py +479 -0
- package/hooks/blocking/gh_body_arg_blocker.py +1 -1
- package/hooks/blocking/nas_ssh_binary_enforcer.py +8 -46
- package/hooks/blocking/orchestrator_refresh_reschedule_gate.py +256 -0
- package/hooks/blocking/pre_tool_use_dispatcher.py +24 -24
- package/hooks/blocking/shell_substitution_blocker.py +129 -0
- package/hooks/blocking/state_description_blocker.py +1 -1
- package/hooks/blocking/stop_dispatcher.py +1 -1
- package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +2 -3
- package/hooks/blocking/test_code_review_pr_create_gate.py +14 -0
- package/hooks/blocking/test_code_review_push_gate.py +16 -0
- package/hooks/blocking/test_code_review_stamp_directory_write_blocker.py +19 -0
- package/hooks/blocking/test_eli11_reply_enforcer.py +457 -0
- package/hooks/blocking/test_orchestrator_refresh_reschedule_gate.py +231 -0
- package/hooks/blocking/test_pre_tool_use_dispatcher.py +10 -1
- package/hooks/blocking/test_shell_substitution_blocker.py +124 -0
- package/hooks/blocking/test_stop_dispatcher.py +23 -0
- package/hooks/blocking/test_unscoped_search_blocker.py +102 -0
- package/hooks/blocking/test_verdict_directory_write_blocker.py +804 -808
- package/hooks/blocking/test_verification_verdict_store.py +54 -0
- package/hooks/blocking/test_verified_commit_gate.py +581 -581
- package/hooks/blocking/test_verified_commit_message_accuracy_blocker.py +131 -131
- package/hooks/blocking/unscoped_search_blocker.py +391 -0
- package/hooks/blocking/verdict_directory_write_blocker.py +687 -687
- package/hooks/blocking/verification_verdict_store.py +1039 -1036
- package/hooks/blocking/verified_commit_message_accuracy_blocker.py +167 -167
- package/hooks/blocking/verifier_verdict_minter.py +280 -280
- package/hooks/git-hooks/CLAUDE.md +3 -0
- package/hooks/git-hooks/conftest.py +30 -0
- package/hooks/git-hooks/gate_utils.py +2 -2
- package/hooks/git-hooks/git_hooks_constants/__init__.py +41 -2
- package/hooks/git-hooks/pre_push.py +75 -4
- package/hooks/git-hooks/pre_push_base_reference.py +166 -0
- package/hooks/git-hooks/test_config.py +0 -15
- package/hooks/git-hooks/test_gate_utils.py +3 -15
- package/hooks/git-hooks/test_pre_commit.py +1 -15
- package/hooks/git-hooks/test_pre_push.py +257 -23
- package/hooks/git-hooks/test_pre_push_base_reference.py +339 -0
- package/hooks/hooks.json +10 -12
- package/hooks/hooks_constants/CLAUDE.md +7 -2
- package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +4 -4
- package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +101 -0
- package/hooks/hooks_constants/enter_worktree_prefetch_constants.py +18 -18
- package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +2 -8
- package/hooks/hooks_constants/orchestrator_refresh_reschedule_gate_constants.py +48 -0
- package/hooks/hooks_constants/ruff_integration_constants.py +16 -0
- package/hooks/hooks_constants/shell_command_segments.py +82 -0
- package/hooks/hooks_constants/shell_substitution_blocker_constants.py +67 -0
- package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -0
- package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +5 -6
- package/hooks/hooks_constants/test_stop_dispatcher_constants.py +1 -0
- package/hooks/hooks_constants/unscoped_search_blocker_constants.py +153 -0
- package/hooks/lifecycle/enter_worktree_origin_prefetch.py +163 -146
- package/hooks/lifecycle/test_enter_worktree_origin_prefetch.py +185 -178
- package/hooks/pyproject.toml +1 -0
- package/hooks/validators/CLAUDE.md +1 -0
- package/hooks/validators/config/__init__.py +0 -0
- package/hooks/validators/config/directory_exemption_constants.py +183 -0
- package/hooks/validators/config/test_directory_exemption_constants.py +21 -0
- package/hooks/validators/conftest.py +4 -0
- package/hooks/validators/ruff_integration.py +49 -5
- package/hooks/validators/run_all_validators.py +206 -9
- package/hooks/validators/test_directory_exemption_constants.py +185 -0
- package/hooks/validators/test_python_antipattern_checks.py +110 -5
- package/hooks/validators/test_ruff_integration.py +92 -1
- package/hooks/validators/test_run_all_validators.py +115 -68
- package/hooks/validators/test_run_all_validators_pretooluse.py +159 -1
- package/package.json +13 -3
- package/rules/CLAUDE.md +17 -22
- package/rules/agent-spawn-protocol.md +6 -6
- package/rules/anti-corollary-tests.md +1 -1
- package/rules/bdd.md +1 -1
- package/rules/cleanup-temp-files.md +10 -4
- package/rules/code-standards.md +7 -0
- package/rules/conservative-action.md +1 -5
- package/rules/context7.md +0 -4
- package/rules/destructive-commands.md +47 -0
- package/rules/doc-inventory-integrity.md +48 -0
- package/rules/doc-prose-cuts.md +58 -0
- package/rules/docstring-prose-matches-implementation.md +53 -44
- package/rules/durable-post-artifacts.md +0 -4
- package/rules/eli11-replies.md +31 -0
- package/rules/explore-thoroughly.md +4 -4
- package/rules/falsify-before-green.md +68 -0
- package/rules/file-global-constants.md +1 -1
- package/rules/filesystem-search.md +51 -0
- package/rules/gh-cli-conventions.md +27 -0
- package/rules/git-workflow.md +26 -0
- package/rules/hedging-claims.md +9 -0
- package/rules/long-horizon-autonomy.md +0 -4
- package/rules/measurement-denominators.md +48 -0
- package/rules/nas-ssh-invocation.md +23 -5
- package/rules/parallel-tools.md +2 -2
- package/rules/plain-illustrative-docstrings.md +3 -7
- package/rules/plain-language.md +2 -0
- package/rules/proof-of-work-pr-comments.md +0 -4
- package/rules/re-stage-before-commit.md +2 -0
- package/rules/research-mode.md +10 -0
- package/rules/shell-invocation.md +21 -0
- package/rules/testing.md +4 -0
- package/rules/verified-commit-gate-skip.md +3 -27
- package/rules/verify-before-asking.md +5 -0
- package/rules/windows-filesystem-safe.md +1 -1
- package/rules/workers-done-before-complete.md +4 -0
- package/scripts/CLAUDE.md +1 -0
- package/scripts/Capture-PoolHealth.ps1 +410 -0
- package/scripts/Migrate-ShellPolicy.ps1 +1 -1
- package/scripts/_code_review_test_support.py +404 -0
- package/scripts/claude_chain_runner.py +141 -1
- package/scripts/codex_capability_bridge.py +171 -0
- package/scripts/codex_compat_materializer.py +1087 -0
- package/scripts/codex_compat_watcher.py +502 -0
- package/scripts/conftest.py +16 -1
- package/scripts/dev_env_scripts_constants/CLAUDE.md +1 -1
- package/scripts/dev_env_scripts_constants/claude_chain_constants.py +9 -0
- package/scripts/dev_env_scripts_constants/code_review_constants.py +37 -0
- package/scripts/invoke_code_review.py +11 -4
- package/scripts/resolve_worker_spawn.py +626 -626
- package/scripts/spawn_grok_batch.py +672 -672
- package/scripts/sync_to_cursor/rules.py +0 -10
- package/scripts/test_claude_chain_runner.py +131 -0
- package/scripts/test_invoke_code_review.py +85 -908
- package/scripts/test_invoke_code_review_chain.py +70 -0
- package/scripts/test_invoke_code_review_cli.py +192 -0
- package/scripts/test_invoke_code_review_contract.py +256 -0
- package/scripts/test_invoke_code_review_git.py +123 -0
- package/scripts/test_invoke_code_review_mode.py +99 -0
- package/scripts/test_resolve_worker_spawn.py +1014 -1014
- package/scripts/tests/test_code_review_constants.py +80 -0
- package/scripts/tests/test_codex_capability_bridge.py +91 -0
- package/scripts/tests/test_codex_compat_materializer.py +632 -0
- package/scripts/tests/test_codex_compat_watcher.py +599 -0
- package/scripts/tests/test_sync_to_cursor.py +0 -1
- package/skills/CLAUDE.md +2 -0
- package/skills/auditing-claude-config/SKILL.md +114 -114
- package/skills/autoconverge/SKILL.md +427 -427
- package/skills/autoconverge/reference/convergence.md +24 -3
- package/skills/autoconverge/workflow/CLAUDE.md +1 -0
- package/skills/autoconverge/workflow/converge.clean-audit.test.mjs +3 -3
- package/skills/autoconverge/workflow/converge.contract.test.mjs +1263 -1263
- package/skills/autoconverge/workflow/converge.mjs +168 -1
- package/skills/autoconverge/workflow/converge.p2-advance.test.mjs +202 -0
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a11d903476b803493.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a26213978adeef6fb.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a3def0d15ed9d9110.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a41f41b1b708ee3b7.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a758b880abecc3ff7.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-a8897b89656b1bd16.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-abd463d744a1437bc.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/subagents/workflows/wf_881252e6-700/agent-ad19d027ae8ee1816.jsonl +2 -2
- package/skills/autoconverge/workflow/fixtures/wf_run/workflows/wf_881252e6-700.json +265 -265
- package/skills/bugteam/reference/copilot-gap-analysis.md +1 -1
- package/skills/closeout/SKILL.md +33 -50
- package/skills/codex-review/scripts/codex_review_scripts_constants/run_constants.py +8 -0
- package/skills/codex-review/scripts/run_codex_review.py +233 -1
- package/skills/codex-review/scripts/test_run_codex_review.py +189 -0
- package/skills/condensing-instructions/SKILL.md +72 -0
- package/skills/copilot-review/SKILL.md +119 -119
- package/skills/e-code-review/SKILL.md +52 -0
- package/skills/e-code-review/reference/fix.md +54 -0
- package/skills/e-code-review/reference/loop.md +43 -0
- package/skills/e-code-review/reference/low.md +57 -0
- package/skills/e-code-review/reference/medium.md +153 -0
- package/skills/e-code-review/reference/xhigh.md +182 -0
- package/skills/e-simplify/SKILL.md +97 -0
- package/skills/fresh-branch/CLAUDE.md +1 -1
- package/skills/fresh-branch/SKILL.md +5 -6
- package/skills/fresh-branch/scripts/create_fresh_branch.py +42 -24
- package/skills/fresh-branch/scripts/fresh_branch_scripts_constants/fresh_branch_cli_constants.py +1 -3
- package/skills/fresh-branch/scripts/test_create_fresh_branch.py +30 -126
- package/skills/issue-tracker/SKILL.md +92 -0
- package/skills/issue-tracker/reference/epic-and-sub-issue-model.md +55 -0
- package/skills/issue-tracker/reference/handoff-schema.md +64 -0
- package/skills/issue-tracker/reference/operation-matrix.md +41 -0
- package/skills/orchestrator/SKILL.md +177 -22
- package/skills/orchestrator/scripts/status_gate.py +625 -0
- package/skills/orchestrator/scripts/status_gate_constants/__init__.py +1 -0
- package/skills/orchestrator/scripts/status_gate_constants/config/__init__.py +1 -0
- package/skills/orchestrator/scripts/status_gate_constants/config/constants.py +47 -0
- package/skills/orchestrator/scripts/test_status_gate.py +439 -0
- package/skills/orchestrator-refresh/SKILL.md +129 -35
- package/skills/plan-to-pr/SKILL.md +155 -0
- package/skills/plan-to-pr/reference/final-validation-tasks.md +15 -0
- package/skills/plan-to-pr/reference/model-routing.md +36 -0
- package/skills/plan-to-pr/reference/packet-contract.md +43 -0
- package/skills/plan-to-pr/reference/packet-schema.json +57 -0
- package/skills/plan-to-pr/reference/process-inventory.md +22 -0
- package/skills/plan-to-pr/reference/review-loop.md +33 -0
- package/skills/plan-to-pr/reference/run-record.schema.json +27 -0
- package/skills/plan-to-pr/reference/self-audit-tasks.md +15 -0
- package/skills/plan-to-pr/reference/task-seeds.md +14 -0
- package/skills/plan-to-pr/reference/task-ticket.md +38 -0
- package/skills/plan-to-pr/scripts/config/__init__.py +1 -0
- package/skills/plan-to-pr/scripts/config/constants.py +193 -0
- package/skills/plan-to-pr/scripts/create_packet.py +173 -0
- package/skills/plan-to-pr/scripts/test_create_packet.py +102 -0
- package/skills/plan-to-pr/scripts/test_validate_packet.py +256 -0
- package/skills/plan-to-pr/scripts/test_validate_protocol.py +135 -0
- package/skills/plan-to-pr/scripts/test_validate_run.py +158 -0
- package/skills/plan-to-pr/scripts/validate_packet.py +655 -0
- package/skills/plan-to-pr/scripts/validate_protocol.py +622 -0
- package/skills/plan-to-pr/scripts/validate_run.py +173 -0
- package/skills/plan-to-pr/test_skill_contract.py +207 -0
- package/skills/plan-to-pr/test_task_ticket_contract.py +151 -0
- package/skills/pr-converge/SKILL.md +472 -469
- package/skills/pr-converge/reference/examples.md +3 -3
- package/skills/pr-converge/reference/fix-protocol.md +1 -1
- package/skills/pr-converge/reference/ground-rules.md +7 -4
- package/skills/pr-converge/reference/multi-pr-orchestration.md +4 -1
- package/skills/pr-converge/reference/per-tick.md +5 -5
- package/skills/pr-converge/reference/progress-checklist.md +1 -1
- package/skills/pr-converge/scripts/check_convergence_gates.py +279 -279
- package/skills/pr-converge/scripts/test_check_convergence_codex.py +507 -507
- package/skills/pr-converge/scripts/test_check_convergence_gates.py +84 -84
- package/skills/pr-converge/test_step5_host_branch.py +1 -1
- package/skills/pr-fix-protocol/SKILL.md +1 -1
- package/skills/privacy-hygiene/SKILL.md +68 -68
- package/skills/privacy-hygiene/reference/sweep-procedure.md +1 -1
- package/skills/prototype/workflows/promotion.md +1 -1
- package/skills/release-notes-html/SKILL.md +164 -0
- package/skills/session-log/SKILL.md +1 -1
- package/skills/task-build/CLAUDE.md +8 -7
- package/skills/task-build/SKILL.md +16 -8
- package/skills/task-build/reference/tool-routing.md +19 -0
- package/rules/claude-md-orphan-file.md +0 -28
- package/rules/cleanup-command-forms.md +0 -23
- package/rules/code-reviews.md +0 -11
- package/rules/env-var-table-code-drift.md +0 -10
- package/rules/gh-body-file.md +0 -5
- package/rules/gh-paginate.md +0 -3
- package/rules/hook-prose-matches-detector.md +0 -15
- package/rules/no-historical-clutter.md +0 -26
- package/rules/no-inline-destructive-literals.md +0 -9
- package/rules/no-justification-noise.md +0 -61
- package/rules/package-inventory-stale-entry.md +0 -25
- package/rules/right-sized-engineering.md +0 -28
- package/rules/self-contained-docs.md +0 -17
- package/rules/shell-invocation-policy.md +0 -5
- package/rules/tdd.md +0 -7
- package/skills/closeout/reference/issue-body-templates.md +0 -108
|
@@ -1,53 +1,43 @@
|
|
|
1
1
|
"""Behavioral tests for the staged_test_running parts module."""
|
|
2
2
|
|
|
3
|
-
import subprocess
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
import pytest
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
subprocess.run(
|
|
11
|
-
["git", *arguments],
|
|
12
|
-
cwd=str(repository_root),
|
|
13
|
-
check=True,
|
|
14
|
-
capture_output=True,
|
|
15
|
-
env=git_file_sets.repository_environment(),
|
|
16
|
-
)
|
|
7
|
+
from code_rules_gate_parts import staged_test_running
|
|
8
|
+
from code_rules_gate_parts.tests._repo_test_helpers import repository_root_without_pytest_config
|
|
17
9
|
|
|
18
10
|
|
|
19
|
-
def
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
_git(repository_root, "config", "commit.gpgsign", "false")
|
|
24
|
-
(repository_root / "seed.txt").write_text("seed\n", encoding="utf-8")
|
|
25
|
-
_git(repository_root, "add", "-A")
|
|
26
|
-
_git(repository_root, "commit", "-m", "seed")
|
|
11
|
+
def _write_pytest_config(directory: Path) -> None:
|
|
12
|
+
"""Write a minimal ``pytest.ini`` into *directory*, creating it when absent."""
|
|
13
|
+
directory.mkdir(parents=True, exist_ok=True)
|
|
14
|
+
(directory / "pytest.ini").write_text("[pytest]\n", encoding="utf-8")
|
|
27
15
|
|
|
28
16
|
|
|
29
|
-
def
|
|
17
|
+
def _write_test_file(repository_root: Path, relative_path: str) -> Path:
|
|
18
|
+
"""Write a trivially passing test module at *relative_path* and return its path."""
|
|
30
19
|
file_path = repository_root / relative_path
|
|
31
20
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
32
|
-
file_path.write_text(
|
|
33
|
-
|
|
21
|
+
file_path.write_text(
|
|
22
|
+
"def test_placeholder() -> None:\n assert True\n", encoding="utf-8"
|
|
23
|
+
)
|
|
34
24
|
return file_path
|
|
35
25
|
|
|
36
26
|
|
|
37
|
-
def
|
|
38
|
-
|
|
39
|
-
repository_root.mkdir()
|
|
40
|
-
_init_repository(repository_root)
|
|
41
|
-
(repository_root / "pytest.ini").write_text("[pytest]\n", encoding="utf-8")
|
|
42
|
-
return repository_root
|
|
27
|
+
def _refuse_to_resolve(monkeypatch: pytest.MonkeyPatch, refused_path: Path) -> None:
|
|
28
|
+
"""Make ``Path.resolve`` raise ``OSError`` for *refused_path* and nothing else.
|
|
43
29
|
|
|
30
|
+
Stands in for a staged file the filesystem accepts as a file yet refuses to
|
|
31
|
+
resolve, such as a broken junction or a path the user may not traverse.
|
|
32
|
+
"""
|
|
33
|
+
original_resolve = Path.resolve
|
|
44
34
|
|
|
45
|
-
def
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
35
|
+
def _resolve_unless_refused(each_path: Path, strict: bool = False) -> Path:
|
|
36
|
+
if each_path == refused_path:
|
|
37
|
+
raise OSError("resolve refused")
|
|
38
|
+
return original_resolve(each_path, strict=strict)
|
|
49
39
|
|
|
50
|
-
|
|
40
|
+
monkeypatch.setattr(Path, "resolve", _resolve_unless_refused)
|
|
51
41
|
|
|
52
42
|
|
|
53
43
|
def test_batched_pytest_arguments_splits_over_the_budget() -> None:
|
|
@@ -73,44 +63,87 @@ def test_pytest_target_paths_drops_conftest_and_keeps_real_tests() -> None:
|
|
|
73
63
|
assert all_targets == [Path("pkg_a/test_alpha.py")]
|
|
74
64
|
|
|
75
65
|
|
|
76
|
-
def
|
|
66
|
+
def test_group_staged_tests_by_root_splits_config_less_top_level_directories(
|
|
77
67
|
tmp_path: Path,
|
|
78
68
|
) -> None:
|
|
79
|
-
repository_root =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
69
|
+
repository_root = repository_root_without_pytest_config(tmp_path)
|
|
70
|
+
alpha_test_path = _write_test_file(repository_root, "alpha_package/tests/test_alpha.py")
|
|
71
|
+
beta_test_path = _write_test_file(repository_root, "beta_package/tests/test_beta.py")
|
|
72
|
+
|
|
73
|
+
all_tests_by_root = staged_test_running._group_staged_tests_by_root(
|
|
74
|
+
[alpha_test_path, beta_test_path], repository_root
|
|
84
75
|
)
|
|
85
76
|
|
|
86
|
-
assert
|
|
77
|
+
assert all_tests_by_root == {
|
|
78
|
+
(repository_root / "alpha_package").resolve(): [alpha_test_path],
|
|
79
|
+
(repository_root / "beta_package").resolve(): [beta_test_path],
|
|
80
|
+
}
|
|
87
81
|
|
|
88
82
|
|
|
89
|
-
def
|
|
83
|
+
def test_group_staged_tests_by_root_places_every_input_in_exactly_one_group(
|
|
90
84
|
tmp_path: Path,
|
|
91
85
|
) -> None:
|
|
92
|
-
repository_root =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
repository_root,
|
|
97
|
-
"
|
|
98
|
-
|
|
86
|
+
repository_root = repository_root_without_pytest_config(tmp_path)
|
|
87
|
+
_write_pytest_config(repository_root / "configured_package")
|
|
88
|
+
all_staged_test_paths = [
|
|
89
|
+
_write_test_file(repository_root, "configured_package/suite/test_configured.py"),
|
|
90
|
+
_write_test_file(repository_root, "alpha_package/tests/test_alpha.py"),
|
|
91
|
+
_write_test_file(repository_root, "alpha_package/tests/test_second_alpha.py"),
|
|
92
|
+
_write_test_file(repository_root, "beta_package/test_beta.py"),
|
|
93
|
+
_write_test_file(repository_root, "test_at_repository_root.py"),
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
all_tests_by_root = staged_test_running._group_staged_tests_by_root(
|
|
97
|
+
all_staged_test_paths, repository_root
|
|
99
98
|
)
|
|
100
99
|
|
|
101
|
-
|
|
100
|
+
all_grouped_test_paths = [
|
|
101
|
+
each_path for each_group in all_tests_by_root.values() for each_path in each_group
|
|
102
|
+
]
|
|
103
|
+
assert sorted(all_grouped_test_paths) == sorted(all_staged_test_paths)
|
|
102
104
|
|
|
103
105
|
|
|
104
|
-
def
|
|
106
|
+
def test_group_staged_tests_by_root_groups_at_the_config_owning_ancestor(
|
|
105
107
|
tmp_path: Path,
|
|
106
108
|
) -> None:
|
|
107
|
-
repository_root =
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
repository_root,
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
repository_root = repository_root_without_pytest_config(tmp_path)
|
|
110
|
+
configured_package_root = repository_root / "configured_package"
|
|
111
|
+
_write_pytest_config(configured_package_root)
|
|
112
|
+
nested_test_path = _write_test_file(
|
|
113
|
+
repository_root, "configured_package/suite/test_configured.py"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
all_tests_by_root = staged_test_running._group_staged_tests_by_root(
|
|
117
|
+
[nested_test_path], repository_root
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
assert all_tests_by_root == {configured_package_root.resolve(): [nested_test_path]}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_group_staged_tests_by_root_keeps_a_repository_root_file_at_the_root(
|
|
124
|
+
tmp_path: Path,
|
|
125
|
+
) -> None:
|
|
126
|
+
repository_root = repository_root_without_pytest_config(tmp_path)
|
|
127
|
+
root_level_test_path = _write_test_file(repository_root, "test_at_repository_root.py")
|
|
128
|
+
|
|
129
|
+
all_tests_by_root = staged_test_running._group_staged_tests_by_root(
|
|
130
|
+
[root_level_test_path], repository_root
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
assert all_tests_by_root == {repository_root.resolve(): [root_level_test_path]}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_group_staged_tests_by_root_falls_back_to_the_root_when_resolve_raises(
|
|
137
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
138
|
+
) -> None:
|
|
139
|
+
repository_root = repository_root_without_pytest_config(tmp_path)
|
|
140
|
+
unresolvable_test_path = _write_test_file(
|
|
141
|
+
repository_root, "alpha_package/tests/test_alpha.py"
|
|
142
|
+
)
|
|
143
|
+
_refuse_to_resolve(monkeypatch, unresolvable_test_path)
|
|
144
|
+
|
|
145
|
+
all_tests_by_root = staged_test_running._group_staged_tests_by_root(
|
|
146
|
+
[unresolvable_test_path], repository_root
|
|
114
147
|
)
|
|
115
148
|
|
|
116
|
-
assert
|
|
149
|
+
assert all_tests_by_root == {repository_root.resolve(): [unresolvable_test_path]}
|