mirror of
https://github.com/github/spec-kit.git
synced 2026-07-03 12:28:06 +08:00
* ci: add windows-latest to test matrix Add windows-latest to the pytest job OS matrix so tests run on both Ubuntu and Windows for all Python versions. Closes #2232 * test: skip bash-specific tests on Windows Add sys.platform skip markers to all test classes and methods that execute bash scripts via subprocess, so they are skipped on Windows where bash is not available. Mixed classes with both bash and pwsh tests have markers on individual bash methods only. * test: fix 3 Windows-specific test failures - test_manifest: use platform-appropriate absolute path (C:\ on Windows vs /tmp on POSIX) since /tmp is not absolute on Windows - test_extensions: add agent_scripts.ps entry and platform-conditional assertions for codex skill fallback variant test - test_timestamp_branches: use json.dumps() instead of f-string to properly escape Windows backslash paths in feature.json * test: extract requires_bash marker and fix PS test skip Address PR review feedback: - Define a reusable requires_bash marker in conftest.py and use it across all 3 test files instead of repeating the skipif inline - Move test_powershell_scanner_uses_long_tryparse_for_large_prefixes into its own TestSequentialBranchPowerShell class so it is not incorrectly skipped on Windows by the class-level bash marker * test: use runtime bash check instead of platform check Replace sys.platform == 'win32' with an actual bash invocation test to handle environments where bash exists but is non-functional (e.g., WSL stub on Windows without an installed distro). * test: reject WSL bash, accept only MSYS/MINGW on Windows On Windows, verify uname -s reports MSYS, MINGW, or CYGWIN so the WSL launcher (System32\bash.exe) is rejected — it cannot handle native Windows paths used by test fixtures. Add SPECKIT_TEST_BASH=1 env var escape hatch to force-enable bash tests in non-standard setups. * ci: add comment explaining Windows bash test behavior * test: early-reject WSL launcher, fix remaining f-string JSON - Check resolved bash path for System32 before spawning any subprocess to avoid WSL init prompts and timeout during test collection - Convert remaining feature_json f-string writes to json.dumps() so paths with backslashes produce valid JSON on Windows * test: use bare 'bash' for detection to match test invocation On Windows, subprocess.run(['bash', ...]) uses CreateProcess which searches System32 before PATH — finding WSL bash even when shutil.which('bash') returns Git-for-Windows. Probe with bare 'bash' (same as test helpers) so the detection matches actual test behavior.
69 lines
2.2 KiB
Python
69 lines
2.2 KiB
Python
"""Shared test helpers for the Spec Kit test suite."""
|
|
|
|
import os
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
_ANSI_ESCAPE_RE = re.compile(r"\x1b\[[0-?]*[ -/]*[@-~]")
|
|
|
|
|
|
def _has_working_bash() -> bool:
|
|
"""Check whether a functional native bash is available.
|
|
|
|
On Windows, ``subprocess.run(["bash", ...])`` uses CreateProcess,
|
|
which searches System32 *before* PATH — so it may find the WSL
|
|
launcher even when Git-for-Windows bash appears first in PATH via
|
|
``shutil.which``. We therefore probe with bare ``"bash"`` (the
|
|
same way test helpers invoke it) to get an accurate result.
|
|
|
|
On Windows, only Git-for-Windows bash (MSYS2/MINGW) is accepted.
|
|
The WSL launcher is rejected because it runs in a separate Linux
|
|
filesystem and cannot handle native Windows paths used by the
|
|
test fixtures.
|
|
|
|
Set SPECKIT_TEST_BASH=1 to force-enable bash tests regardless.
|
|
"""
|
|
if os.environ.get("SPECKIT_TEST_BASH") == "1":
|
|
return True
|
|
if shutil.which("bash") is None:
|
|
return False
|
|
# Probe with bare "bash" — same as the test helpers — so that
|
|
# Windows CreateProcess resolution order is respected.
|
|
try:
|
|
r = subprocess.run(
|
|
["bash", "-c", "echo ok"],
|
|
capture_output=True, text=True, timeout=5,
|
|
)
|
|
if r.returncode != 0 or "ok" not in r.stdout:
|
|
return False
|
|
except (OSError, subprocess.TimeoutExpired):
|
|
return False
|
|
# On Windows, verify we have MSYS/MINGW bash (Git for Windows),
|
|
# not the WSL launcher which can't handle native paths.
|
|
if sys.platform == "win32":
|
|
try:
|
|
u = subprocess.run(
|
|
["bash", "-c", "uname -s"],
|
|
capture_output=True, text=True, timeout=5,
|
|
)
|
|
kernel = u.stdout.strip().upper()
|
|
if not any(k in kernel for k in ("MSYS", "MINGW", "CYGWIN")):
|
|
return False
|
|
except (OSError, subprocess.TimeoutExpired):
|
|
return False
|
|
return True
|
|
|
|
|
|
requires_bash = pytest.mark.skipif(
|
|
not _has_working_bash(), reason="working bash not available"
|
|
)
|
|
|
|
|
|
def strip_ansi(text: str) -> str:
|
|
"""Remove ANSI escape codes from Rich-formatted CLI output."""
|
|
return _ANSI_ESCAPE_RE.sub("", text)
|