Skip to content

Commit d650c3a

Browse files
committed
test: add end-to-end regression guard for upgrade-overwrites-copilot-skills (#3849)
The existing regression tests in TestRegisterExtensionSkillsForceFlag exercise the new force parameter at the helper level, so without the fix they fail only with a TypeError (unknown kwarg) rather than on the user-facing behaviour. Add a command-level test that runs 'specify integration upgrade copilot --skills --force' end-to-end and asserts the installed git extension's SKILL.md is restored (with its extension content, not a bare core-template stub) when the skill directory already exists — the exact skill_dir_preexists path the bug depends on. The test fails on pre-fix source (the skill is never recreated) and passes with the fix, so it is a genuine behavioural regression guard rather than an API-surface check. Refs #3849 Assisted-by: GitHub Copilot (model: claude-opus-4.8, autonomous)
1 parent 30ea7c7 commit d650c3a

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

‎tests/integrations/test_integration_subcommand.py‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3831,6 +3831,68 @@ def test_upgrade_active_integration_reregisters_extensions(self, tmp_path):
38313831
"upgrade of the active integration re-registers extension commands"
38323832
)
38333833

3834+
def test_upgrade_copilot_skills_restores_extension_skill_over_regenerated_dir(
3835+
self, tmp_path
3836+
):
3837+
"""End-to-end regression for #3849 (upgrade-overwrites-copilot-skills).
3838+
3839+
In Copilot skills mode, ``integration upgrade`` runs ``setup()`` — which
3840+
regenerates the core-template skill directories — *before* re-registering
3841+
installed extensions. The extension re-registration then hits the
3842+
``skill_dir_preexists`` guard in ``_register_extension_skills`` (the skill
3843+
sub-directory exists, courtesy of ``setup()``, but its ``SKILL.md`` has
3844+
not been rewritten with extension content), so pre-fix the extension
3845+
skill was silently left missing — its command content lost even though the
3846+
extension remained installed and registered.
3847+
3848+
The fix threads ``force=True`` from ``integration_upgrade()`` down to
3849+
``_register_extension_skills`` so the guard is bypassed and the extension
3850+
content is re-composed on top of the just-regenerated directory. This test
3851+
exercises the full ``specify integration upgrade`` command path and fails
3852+
without the fix (the skill is never recreated).
3853+
"""
3854+
project = _init_project(
3855+
tmp_path, "copilot", integration_options="--skills"
3856+
)
3857+
3858+
result = _run_in_project(project, ["extension", "add", "git"])
3859+
assert result.exit_code == 0, f"extension add failed: {result.output}"
3860+
3861+
skill_dir = project / ".github" / "skills" / "speckit-git-feature"
3862+
skill_file = skill_dir / "SKILL.md"
3863+
assert skill_file.exists(), (
3864+
"precondition: git extension renders as a Copilot skill"
3865+
)
3866+
original = skill_file.read_text(encoding="utf-8")
3867+
assert "source: extension:git" in original, (
3868+
"precondition: skill carries the git extension ownership marker"
3869+
)
3870+
3871+
# Simulate the exact pre-condition the bug depends on: the skill file is
3872+
# gone but its directory survives (as it does once setup() regenerates the
3873+
# core-template layout during upgrade), triggering the skill_dir_preexists
3874+
# skip guard on re-registration.
3875+
skill_file.unlink()
3876+
assert skill_dir.exists() and not skill_file.exists()
3877+
3878+
result = _run_in_project(project, [
3879+
"integration", "upgrade", "copilot",
3880+
"--integration-options", "--skills",
3881+
"--script", "sh", "--force",
3882+
])
3883+
assert result.exit_code == 0, result.output
3884+
3885+
assert skill_file.exists(), (
3886+
"upgrade must restore the extension skill even when its directory "
3887+
"already exists (regression #3849)"
3888+
)
3889+
restored = skill_file.read_text(encoding="utf-8")
3890+
assert "source: extension:git" in restored, (
3891+
"restored skill must contain the git extension content, not a bare "
3892+
"core-template stub"
3893+
)
3894+
assert "# Git Feature Skill" in restored
3895+
38343896
def test_upgrade_active_integration_reregisters_presets(self, tmp_path):
38353897
"""Upgrading the active integration restores missing preset artifacts."""
38363898
import yaml

0 commit comments

Comments
 (0)