Skip to content

Commit e790a18

Browse files
author
Aaron Sun
committed
Added warning message about git extension no longer being enabled by default
1 parent cdbea09 commit e790a18

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Add notice that git extension will no longer be enabled by default at 1.0.0
2+
3+
> **Source**: [#2165](https://github.com/github/spec-kit/issues/2165) — imported on 2026-04-12
4+
5+
## Overview
6+
7+
Add a deprecation notice during `specify init` to inform users that the git extension, currently auto-enabled by default, will require explicit opt-in starting with v1.0.0. This ensures users are aware of the upcoming behavioral change well in advance.
8+
9+
## Problem Statement
10+
11+
The `git` extension is currently bundled and enabled by default during `specify init`. Starting with v1.0.0, it will still be bundled but no longer enabled by default — users will need to explicitly opt in. Without advance notice, users may be surprised by this change when upgrading to v1.0.0.
12+
13+
## Requirements
14+
15+
### Functional Requirements
16+
17+
- FR-1: During `specify init`, display a warning notice when the git extension is auto-enabled
18+
- FR-2: The notice must clearly state the timeline (v1.0.0) for the change
19+
- FR-3: The notice must explain how to opt in after the change (`specify init --extension git` or `specify extension add git`)
20+
- FR-4: The notice must be non-blocking (warning styling, does not halt initialization)
21+
22+
### Non-Functional Requirements
23+
24+
- NFR-1: Notice should use yellow/warning styling consistent with existing CLI warning patterns
25+
- NFR-2: Notice should be concise and actionable
26+
27+
## User Scenarios
28+
29+
### Scenario 1: User runs specify init and sees deprecation notice
30+
31+
**Given** a user is initializing a new project with `specify init`
32+
**When** the git extension is auto-enabled as part of the default behavior
33+
**Then** a warning notice is displayed informing them that the git extension will require explicit opt-in starting with v1.0.0
34+
35+
### Scenario 2: User understands how to opt in after v1.0.0
36+
37+
**Given** a user sees the deprecation notice during `specify init`
38+
**When** they read the notice
39+
**Then** they understand they can use `specify init --extension git` or `specify extension add git` to enable the git extension after v1.0.0
40+
41+
## Acceptance Criteria
42+
43+
- [ ] AC-1: `specify init` shows a notice when the git extension is auto-enabled
44+
- [ ] AC-2: Notice is visible but non-blocking (yellow/warning styling)
45+
- [ ] AC-3: Message clearly states the timeline (v1.0.0) and how to opt in
46+
47+
## Out of Scope
48+
49+
- Changes to the git extension itself or its functionality
50+
- Changes to the bundled status of the git extension (it remains bundled/shipped with spec-kit)
51+
- Actually removing the default-enabled behavior (that happens at v1.0.0, not now)

src/specify_cli/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,7 @@ def init(
12111211

12121212
ensure_constitution_from_template(project_path, tracker=tracker)
12131213

1214+
_git_ext_freshly_installed = False
12141215
if not no_git:
12151216
tracker.start("git")
12161217
git_messages = []
@@ -1245,6 +1246,7 @@ def init(
12451246
bundled_path, get_speckit_version()
12461247
)
12471248
git_messages.append("extension installed")
1249+
_git_ext_freshly_installed = True
12481250
else:
12491251
git_has_error = True
12501252
git_messages.append("bundled extension not found")
@@ -1356,6 +1358,21 @@ def init(
13561358
console.print(tracker.render())
13571359
console.print("\n[bold green]Project ready.[/bold green]")
13581360

1361+
if _git_ext_freshly_installed:
1362+
console.print()
1363+
console.print(
1364+
Panel(
1365+
"The [bold]git[/bold] extension is currently enabled by default, "
1366+
"but starting with [bold]v1.0.0[/bold] it will require explicit opt-in.\n\n"
1367+
"To opt in after v1.0.0:\n"
1368+
" • [cyan]specify init --extension git[/cyan]\n"
1369+
" • [cyan]specify extension add git[/cyan] (post-init)",
1370+
title="[yellow]⚠ Upcoming Change: git Extension[/yellow]",
1371+
border_style="yellow",
1372+
padding=(1, 2),
1373+
)
1374+
)
1375+
13591376
# Agent folder security notice
13601377
agent_config = AGENT_CONFIG.get(selected_ai)
13611378
if agent_config:

tests/extensions/git/test_git_extension.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,3 +587,79 @@ def test_check_feature_branch_rejects_malformed_timestamp(self, tmp_path: Path):
587587
capture_output=True, text=True,
588588
)
589589
assert result.returncode != 0
590+
591+
592+
# ── Deprecation Notice Tests ──────────────────────────────────────────────────
593+
594+
595+
class TestGitExtDeprecationNotice:
596+
"""Tests for the v1.0.0 deprecation notice shown during specify init."""
597+
598+
def test_deprecation_notice_shown_on_fresh_install(self, tmp_path: Path):
599+
"""specify init shows the git extension deprecation notice on first install."""
600+
from typer.testing import CliRunner
601+
from unittest.mock import patch, MagicMock
602+
from specify_cli import app
603+
604+
project_dir = tmp_path / "test-project"
605+
runner = CliRunner()
606+
607+
mock_registry = MagicMock()
608+
mock_registry.is_installed.return_value = False
609+
610+
mock_manager = MagicMock()
611+
mock_manager.registry = mock_registry
612+
613+
with patch("specify_cli.extensions.ExtensionManager", return_value=mock_manager):
614+
result = runner.invoke(
615+
app,
616+
["init", str(project_dir), "--ai", "claude", "--ignore-agent-tools", "--script", "sh"],
617+
catch_exceptions=False,
618+
)
619+
620+
assert result.exit_code == 0, result.output
621+
assert "Upcoming Change: git Extension" in result.output
622+
assert "v1.0.0" in result.output
623+
assert "specify init --extension git" in result.output
624+
625+
def test_deprecation_notice_not_shown_when_already_installed(self, tmp_path: Path):
626+
"""specify init does NOT show the deprecation notice when git extension is already installed."""
627+
from typer.testing import CliRunner
628+
from unittest.mock import patch, MagicMock
629+
from specify_cli import app
630+
631+
project_dir = tmp_path / "test-project"
632+
runner = CliRunner()
633+
634+
mock_registry = MagicMock()
635+
mock_registry.is_installed.return_value = True
636+
637+
mock_manager = MagicMock()
638+
mock_manager.registry = mock_registry
639+
640+
with patch("specify_cli.extensions.ExtensionManager", return_value=mock_manager):
641+
result = runner.invoke(
642+
app,
643+
["init", str(project_dir), "--ai", "claude", "--ignore-agent-tools", "--script", "sh"],
644+
catch_exceptions=False,
645+
)
646+
647+
assert result.exit_code == 0, result.output
648+
assert "Upcoming Change: git Extension" not in result.output
649+
650+
def test_deprecation_notice_not_shown_with_no_git_flag(self, tmp_path: Path):
651+
"""specify init does NOT show the deprecation notice when --no-git is passed."""
652+
from typer.testing import CliRunner
653+
from specify_cli import app
654+
655+
project_dir = tmp_path / "test-project"
656+
runner = CliRunner()
657+
658+
result = runner.invoke(
659+
app,
660+
["init", str(project_dir), "--ai", "claude", "--ignore-agent-tools", "--no-git", "--script", "sh"],
661+
catch_exceptions=False,
662+
)
663+
664+
assert result.exit_code == 0, result.output
665+
assert "Upcoming Change: git Extension" not in result.output

0 commit comments

Comments
 (0)