mirror of
https://github.com/github/spec-kit.git
synced 2026-07-03 20:36:23 +08:00
* Stage 6: Complete migration — remove legacy scaffold path (#1924) Remove the legacy GitHub download and offline scaffold code paths. All 26 agents now use the integration system exclusively. Code removal (~1073 lines from __init__.py): - download_template_from_github(), download_and_extract_template() - scaffold_from_core_pack(), _locate_release_script() - install_ai_skills(), _get_skills_dir (restored slim version for presets) - _has_bundled_skills(), _migrate_legacy_kimi_dotted_skills() - AGENT_SKILLS_MIGRATIONS, _handle_agent_skills_migration() - _parse_rate_limit_headers(), _format_rate_limit_error() - Three-way branch in init() collapsed to integration-only Config derivation (single source of truth): - AGENT_CONFIG derived from INTEGRATION_REGISTRY (replaced 180-line dict) - CommandRegistrar.AGENT_CONFIGS derived from INTEGRATION_REGISTRY (replaced 160-line dict) - Backward-compat constants kept for presets/extensions: SKILL_DESCRIPTIONS, NATIVE_SKILLS_AGENTS, DEFAULT_SKILLS_DIR Release pipeline cleanup: - Deleted create-release-packages.sh/.ps1 (948 lines of ZIP packaging) - Deleted create-github-release.sh, generate-release-notes.sh - Deleted simulate-release.sh, get-next-version.sh, update-version.sh - Removed .github/workflows/scripts/ directory entirely - release.yml is now self-contained: check, notes, release all inlined - Install instructions use uv tool install with version tag Test cleanup: - Deleted test_ai_skills.py (tested removed functions) - Deleted test_core_pack_scaffold.py (tested removed scaffold) - Cleaned test_agent_config_consistency.py (removed 19 release-script tests) - Fixed test_branch_numbering.py (removed dead monkeypatches) - Updated auto-promote tests (verify files created, not tip messages) 1089 tests pass, 0 failures, ruff clean. * fix: resolve merge conflicts with #2051 (claude as skills) - Fix circular import: move CommandRegistrar import in claude integration to inside method bodies (was at module level) - Lazy-populate AGENT_CONFIGS via _ensure_configs() to avoid circular import at class definition time - Set claude registrar_config to .claude/commands (extension/preset target) since the integration handles .claude/skills in setup() - Update tests from #2051 to match: registrar_config assertions, remove --integration tip assertions, remove install_ai_skills mocks 1086 tests pass. * fix: properly preserve claude skills migration from #2051 Restore ClaudeIntegration.registrar_config to .claude/skills (not .claude/commands) so extension/preset registrations write to the correct skills directory. Update tests that simulate claude setup to use .claude/skills and check for SKILL.md layout. Some tests still need updating for the full skills path — 10 remaining failures from the #2051 test expectations around the extension/preset skill registration flow. WIP: 1076/1086 pass. * fix: properly handle SKILL.md paths in extension update rollback and tests Fix extension update rollback using _compute_output_name() for SKILL.md agents (converts dots to hyphens in skill directory names). Previously the backup and cleanup code constructed paths with raw command names (e.g. speckit.test-ext.hello/SKILL.md) instead of the correct computed names (speckit-test-ext-hello/SKILL.md). Test fixes for claude skills migration: - Update claude tests to use .claude/skills paths and SKILL.md layout - Use qwen (not claude) for skills-guard tests since claude's agent dir IS the skills dir — creating it triggers command registration - Fix test_extension_command_registered_when_extension_present to check skills path format 1086 tests pass, 0 failures, ruff clean. * fix: address PR review — lazy init, assertions, deprecated flags - _ensure_configs(): catch ImportError (not Exception), don't set _configs_loaded on failure so retries work - Move _ensure_configs() before unregister loop (not inside it) - Module-level try/except catches ImportError specifically - Remove tautology assertion (or True) in test_extensions.py - Strengthen preset provenance assertion to check source: field - Mark --offline, --skip-tls, --debug, --github-token as hidden deprecated no-ops in init() 1086 tests pass. * fix: remove deleted release scripts from pyproject.toml force-include Removes force-include entries for create-release-packages.sh/.ps1 which were deleted but still referenced in [tool.hatch.build].
75 lines
3.0 KiB
Python
75 lines
3.0 KiB
Python
"""
|
|
Unit tests for branch numbering options (sequential vs timestamp).
|
|
|
|
Tests cover:
|
|
- Persisting branch_numbering in init-options.json
|
|
- Default value when branch_numbering is None
|
|
- Validation of branch_numbering values
|
|
"""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from specify_cli import save_init_options
|
|
|
|
|
|
class TestSaveBranchNumbering:
|
|
"""Tests for save_init_options with branch_numbering."""
|
|
|
|
def test_save_branch_numbering_timestamp(self, tmp_path: Path):
|
|
opts = {"branch_numbering": "timestamp", "ai": "claude"}
|
|
save_init_options(tmp_path, opts)
|
|
|
|
saved = json.loads((tmp_path / ".specify/init-options.json").read_text())
|
|
assert saved["branch_numbering"] == "timestamp"
|
|
|
|
def test_save_branch_numbering_sequential(self, tmp_path: Path):
|
|
opts = {"branch_numbering": "sequential", "ai": "claude"}
|
|
save_init_options(tmp_path, opts)
|
|
|
|
saved = json.loads((tmp_path / ".specify/init-options.json").read_text())
|
|
assert saved["branch_numbering"] == "sequential"
|
|
|
|
def test_branch_numbering_defaults_to_sequential(self, tmp_path: Path):
|
|
from typer.testing import CliRunner
|
|
from specify_cli import app
|
|
|
|
project_dir = tmp_path / "proj"
|
|
runner = CliRunner()
|
|
result = runner.invoke(app, ["init", str(project_dir), "--ai", "claude", "--ignore-agent-tools", "--no-git", "--script", "sh"])
|
|
assert result.exit_code == 0
|
|
|
|
saved = json.loads((project_dir / ".specify/init-options.json").read_text())
|
|
assert saved["branch_numbering"] == "sequential"
|
|
|
|
|
|
class TestBranchNumberingValidation:
|
|
"""Tests for branch_numbering CLI validation via CliRunner."""
|
|
|
|
def test_invalid_branch_numbering_rejected(self, tmp_path: Path):
|
|
from typer.testing import CliRunner
|
|
from specify_cli import app
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(app, ["init", str(tmp_path / "proj"), "--ai", "claude", "--branch-numbering", "foobar", "--ignore-agent-tools"])
|
|
assert result.exit_code == 1
|
|
assert "Invalid --branch-numbering" in result.output
|
|
|
|
def test_valid_branch_numbering_sequential(self, tmp_path: Path):
|
|
from typer.testing import CliRunner
|
|
from specify_cli import app
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(app, ["init", str(tmp_path / "proj"), "--ai", "claude", "--branch-numbering", "sequential", "--ignore-agent-tools", "--no-git", "--script", "sh"])
|
|
assert result.exit_code == 0
|
|
assert "Invalid --branch-numbering" not in (result.output or "")
|
|
|
|
def test_valid_branch_numbering_timestamp(self, tmp_path: Path):
|
|
from typer.testing import CliRunner
|
|
from specify_cli import app
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(app, ["init", str(tmp_path / "proj"), "--ai", "claude", "--branch-numbering", "timestamp", "--ignore-agent-tools", "--no-git", "--script", "sh"])
|
|
assert result.exit_code == 0
|
|
assert "Invalid --branch-numbering" not in (result.output or "")
|