mirror of
https://github.com/github/spec-kit.git
synced 2026-07-07 14:39:00 +08:00
feat: support SPECKIT_INTEGRATION_<KEY>_EXECUTABLE env var (#2743)
* Initial plan * feat: support SPECKIT_INTEGRATION_<KEY>_EXECUTABLE env var override Adds `IntegrationBase._resolve_executable()` which reads `SPECKIT_INTEGRATION_<KEY>_EXECUTABLE` (hyphens→underscores, uppercased) and falls back to `self.key` when unset or whitespace-only. All concrete `build_exec_args()` implementations now call `self._resolve_executable()` instead of hard-coding `self.key` or `"agy"` as the first argv token: - MarkdownIntegration, TomlIntegration, SkillsIntegration (base classes) - CodexIntegration, DevinIntegration, OpencodeIntegration, HermesIntegration, AgyIntegration - CopilotIntegration (overrides `_resolve_executable()` to fall back to the platform-specific `_copilot_executable()` default; also updates `dispatch_command()` to use `_resolve_executable()`) Tests added to tests/integrations/test_extra_args.py covering: - default (unset) falls back to key - env var replaces first argv token - whitespace-only env var is a no-op - key hyphen→underscore normalisation - cross-integration scoping (wrong key ignored) - all override integrations (Codex, Devin, Opencode, Copilot) - Copilot dispatch_command path - EXECUTABLE and EXTRA_ARGS can be set simultaneously See issue #2596." * fix: complete docstring sentence in _resolve_executable * test: generalize extra-args test comments for override coverage * Fix stale Codex executable comment --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -146,6 +146,28 @@ class IntegrationBase(ABC):
|
||||
"""
|
||||
return None
|
||||
|
||||
def _resolve_executable(self) -> str:
|
||||
"""Return the executable for this integration's CLI tool.
|
||||
|
||||
Checks ``SPECKIT_INTEGRATION_<KEY>_EXECUTABLE`` first, allowing
|
||||
operators to override the binary path without modifying the
|
||||
integration configuration — useful when the tool is installed in
|
||||
a non-standard location or a specific version must be pinned.
|
||||
Hyphens in the integration key are replaced with underscores and
|
||||
the key is uppercased so that, for example, ``kiro-cli`` maps to
|
||||
``SPECKIT_INTEGRATION_KIRO_CLI_EXECUTABLE``.
|
||||
|
||||
Falls back to ``self.key`` when the env var is unset or
|
||||
whitespace-only so existing behaviour is unchanged.
|
||||
|
||||
See issue #2596.
|
||||
"""
|
||||
env_name = (
|
||||
f"SPECKIT_INTEGRATION_{self.key.upper().replace('-', '_')}_EXECUTABLE"
|
||||
)
|
||||
override = os.environ.get(env_name, "").strip()
|
||||
return override if override else self.key
|
||||
|
||||
def _apply_extra_args_env_var(self, args: list[str]) -> None:
|
||||
"""Append `SPECKIT_INTEGRATION_<KEY>_EXTRA_ARGS` env-var value to *args*.
|
||||
|
||||
@@ -895,7 +917,7 @@ class MarkdownIntegration(IntegrationBase):
|
||||
) -> list[str] | None:
|
||||
if not self.config or not self.config.get("requires_cli"):
|
||||
return None
|
||||
args = [self.key, "-p", prompt]
|
||||
args = [self._resolve_executable(), "-p", prompt]
|
||||
self._apply_extra_args_env_var(args)
|
||||
if model:
|
||||
args.extend(["--model", model])
|
||||
@@ -983,7 +1005,7 @@ class TomlIntegration(IntegrationBase):
|
||||
) -> list[str] | None:
|
||||
if not self.config or not self.config.get("requires_cli"):
|
||||
return None
|
||||
args = [self.key, "-p", prompt]
|
||||
args = [self._resolve_executable(), "-p", prompt]
|
||||
self._apply_extra_args_env_var(args)
|
||||
if model:
|
||||
args.extend(["-m", model])
|
||||
@@ -1402,7 +1424,7 @@ class SkillsIntegration(IntegrationBase):
|
||||
) -> list[str] | None:
|
||||
if not self.config or not self.config.get("requires_cli"):
|
||||
return None
|
||||
args = [self.key, "-p", prompt]
|
||||
args = [self._resolve_executable(), "-p", prompt]
|
||||
self._apply_extra_args_env_var(args)
|
||||
if model:
|
||||
args.extend(["--model", model])
|
||||
|
||||
Reference in New Issue
Block a user