fix: allow prerelease spec-kit versions in compatibility checks (#2695)

* docs: generate integrations reference from catalog

* refactor: integrate table rendering into specify integration search --markdown

- Remove standalone scripts/generate_integrations_reference.py
- Strip doc injection machinery from catalog_docs.py; keep only table rendering
- Wire render_integrations_table() into existing --markdown flag of integration search
- Remove old simple markdown table block from integration_search (was Name|ID|Version|Description|Author)
- Simplify tests: drop subprocess/doc-path tests, keep table rendering and metadata tests
- Clean up docs/reference/integrations.md: remove generated markers, update note

* fix: address Copilot review feedback on catalog_docs and integration_search

- Warn when --markdown is combined with filters (query/--tag/--author) which are
  silently ignored; catch ValueError/FileNotFoundError and surface clean error
  via console instead of raw traceback (r3244821516)
- Add coverage enforcement in list_integrations_for_docs(): raises ValueError
  with actionable message if any registry key is missing from INTEGRATION_DOC_URLS,
  preventing silently incomplete doc tables (r3244821589)
- Rename test to accurately reflect sources: label derives from registry config,
  URL comes from INTEGRATION_DOC_URLS doc map — not solely from registry (r3244821607)
- Simplify test dict construction to idiomatic dict comprehension (r3244821619)

* fix: add sync test, INTEGRATIONS_REFERENCE_PATH constant, and fix naming

* revert: restore docs/reference/integrations.md to upstream/main; remove sync test (GH Actions job will handle)

* fix: remove dead INTEGRATIONS_REFERENCE_PATH, drop URL-length padding, fix docstring, drop FileNotFoundError

* fix: send --markdown warnings/errors to stderr, rename test for clarity

* fix: detect stale doc-map keys, test _render_cell escaping, strengthen header assertion

* refactor: promote _render_cell to public render_cell function

* test: mock registry and doc maps to avoid brittle live registry coupling

* refactor: flatten patches, remove unused imports, fix trailing whitespace, optimize missing calculation

* refactor: make validation non-fatal, fix context manager syntax, add CLI tests

* fix: improve docstring clarity, test robustness, and exception handling

* fix: improve test assertions, disable warnings by default, enhance exception handling

* fix: make CLI tests deterministic and improve config access resilience

* fix: remove extra blank line, add stale keys validation, add regression test for docs sync

* Fix 5 remaining feedback items:
- Rename _get_mocked_cli_runner() to _get_catalog_docs_patches() for clarity
- Use ExitStack context manager for guaranteed patch cleanup
- Add explicit UTF-8 encoding to file reads
- Skip doc sync test gracefully when docs aren't present
- Remove exception chaining from typer.Exit to avoid noisy tracebacks

* address all outstanding copilot review feedback on PR 2563

* Address Copilot feedback: escape URLs in markdown links, deduplicate cell rendering, fix table parser for escaped pipes

* Address 3 new Copilot feedback: add URL escaping test, fix parse_first_markdown_table for escaped pipes, guard community tests with skip

* Address 3 new Copilot feedback: escape id field, remove unused alias, escape integration URLs

* Address 3 new Copilot feedback: fix comment name, include all integrations in list

* Fix architectural issue: escape raw fields before composing Markdown to prevent double-escaping

* Deduplicate _escape_url_for_markdown_link and add URL escaping test

* Address 4 new Copilot feedback: add trailing newline, fix test helper ExitStack, update warning message

* Address 4 new Copilot feedback: make escape function public, fix error message, validate test rows, prevent double newline

* Update error message in test_missing_catalog_file for clarity

* Remove obsolete integrations sync test

* keep integrations docs in sync

* fix: allow prerelease spec-kit versions in compatibility checks

Allow prerelease/dev builds to satisfy extension and preset compatibility
checks when their version number falls within the required specifier range.
Also harden the integrations docs rendering helpers and add regression
coverage for the markdown table parsing and version gating paths.

Tests: pytest -q; python3 -m compileall -q .; black/flake8 unavailable
Reference: branch 002-generate-integrations-docs; source patch /tmp/spec-kit-changes.patch

* fix: isolate prerelease compatibility gate changes

Keep the prerelease/version compatibility fix on its own branch and remove
the unrelated integrations docs updates that belong with PR 2563.

Tests: full suite passed on the prerelease branch before splitting; docs branch covered by targeted docs tests
Reference: upstream/main; source patch /tmp/spec-kit-changes.patch

* Address PR 2695 feedback: Centralize prerelease policy and add boundary test

* Address remaining Copilot PR feedback: revert docs and add preset prerelease tests

* Remove unreachable raise CompatibilityError

* Fix PEP8 E302 and E303 formatting issues
This commit is contained in:
Dyan Galih
2026-06-30 21:41:57 +07:00
committed by GitHub
parent 5e72b1d486
commit 6fb7e77b3e
6 changed files with 65 additions and 40 deletions

View File

@@ -37,8 +37,8 @@ from specify_cli.extensions import (
ValidationError,
CompatibilityError,
normalize_priority,
version_satisfies,
)
from specify_cli._utils import version_satisfies
# Minimal valid ZIP (empty end-of-central-directory record). Passes
# zipfile.is_zipfile() so --from download tests exercise the content guard.
@@ -1005,6 +1005,14 @@ class TestExtensionManager:
with pytest.raises(CompatibilityError, match="Extension requires spec-kit"):
manager.check_compatibility(manifest, "0.0.1")
def test_check_compatibility_allows_prerelease_builds(self, extension_dir, project_dir):
"""Prerelease spec-kit builds should satisfy compatible version ranges."""
manager = ExtensionManager(project_dir)
manifest = ExtensionManifest(extension_dir / "extension.yml")
result = manager.check_compatibility(manifest, "0.8.8.dev0")
assert result is True
def test_install_from_directory(self, extension_dir, project_dir):
"""Test installing extension from directory."""
manager = ExtensionManager(project_dir)
@@ -2629,6 +2637,12 @@ class TestVersionSatisfies:
assert version_satisfies("1.0.5", ">=1.0.0,!=1.0.3")
assert not version_satisfies("1.0.3", ">=1.0.0,!=1.0.3")
def test_version_satisfies_prerelease(self):
"""Prerelease builds should satisfy compatible lower bounds, but not higher bounds."""
assert version_satisfies("0.8.8.dev0", ">=0.2.0")
assert not version_satisfies("0.2.0.dev0", ">=0.2.0")
assert not version_satisfies("0.8.7.dev1", ">=0.8.8")
def test_version_satisfies_invalid(self):
"""Test invalid version strings."""
assert not version_satisfies("invalid", ">=1.0.0")

View File

@@ -710,6 +710,15 @@ class TestPresetManager:
manifest = PresetManifest(pack_dir / "preset.yml")
assert manager.check_compatibility(manifest, "0.1.5") is True
def test_check_compatibility_prerelease(self, pack_dir, temp_dir):
"""Test compatibility check allows prereleases and fails on boundary."""
manager = PresetManager(temp_dir)
manifest = PresetManifest(pack_dir / "preset.yml")
# manifest requires >=0.1.0
assert manager.check_compatibility(manifest, "0.8.8.dev0") is True
with pytest.raises(PresetCompatibilityError, match="Preset requires spec-kit"):
manager.check_compatibility(manifest, "0.1.0.dev0")
def test_check_compatibility_invalid(self, pack_dir, temp_dir):
"""Test compatibility check with invalid specifier."""
manager = PresetManager(temp_dir)