mirror of
https://github.com/github/spec-kit.git
synced 2026-08-03 06:26:30 +08:00
Add community bundle submission automation (#3553)
* Add community bundle submission automation Add the discovery-only community bundle catalog, online and offline catalog loading, and a restricted agentic workflow for validating bundle submissions and opening draft catalog PRs. Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fbe794bc-667a-4c9e-b48b-825067debc6d * Address community bundle review feedback Ensure explicit install-allowed catalogs take precedence over built-in discovery, tighten component installability validation, and use issue-linked community branches. Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fbe794bc-667a-4c9e-b48b-825067debc6d * Address follow-up bundle review feedback Make offline catalog coverage content-agnostic and require autonomous catalog commits to include the assisted-by trailer. Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fbe794bc-667a-4c9e-b48b-825067debc6d * Harden bundle catalog table rendering Require single-line escaped Markdown table values for untrusted submission metadata. The needs-info label used by validation is now present in the repository. Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fbe794bc-667a-4c9e-b48b-825067debc6d * Clear stale bundle validation labels Allow the submission workflow to remove prior outcome labels before applying the current validation state. Assisted-by: GitHub Copilot (model: GPT-5.6 Sol, autonomous) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fbe794bc-667a-4c9e-b48b-825067debc6d
This commit is contained in:
@@ -43,7 +43,7 @@ class Scope(str, Enum):
|
||||
BUILTIN_DEFAULT_STACK: tuple[dict[str, Any], ...] = (
|
||||
{"id": "default", "url": "builtin://default", "priority": 1,
|
||||
"install_policy": InstallPolicy.INSTALL_ALLOWED.value},
|
||||
{"id": "community", "url": "builtin://community", "priority": 2,
|
||||
{"id": "community", "url": "builtin://community", "priority": 20,
|
||||
"install_policy": InstallPolicy.DISCOVERY_ONLY.value},
|
||||
)
|
||||
|
||||
|
||||
@@ -15,25 +15,26 @@ from pathlib import Path
|
||||
from urllib.parse import ParseResult, urlparse
|
||||
from urllib.request import url2pathname
|
||||
|
||||
from ..._assets import _locate_core_pack, _repo_root
|
||||
from .. import BundlerError
|
||||
from ..lib.yamlio import loads_json
|
||||
from ..models.catalog import CatalogSource
|
||||
from ..models.manifest import ComponentRef
|
||||
|
||||
# Built-in catalog payloads ship empty by default; a host distribution can
|
||||
# replace these with curated content. Keeping them here makes ``search``/``info``
|
||||
# work fully offline against the default stack.
|
||||
COMMUNITY_CATALOG_URL = (
|
||||
"https://raw.githubusercontent.com/github/spec-kit/main/"
|
||||
"bundles/catalog.community.json"
|
||||
)
|
||||
|
||||
# The default catalog is reserved for first-party bundles. The community
|
||||
# catalog is loaded from the repository online and from the packaged snapshot
|
||||
# offline so discovery remains useful without network access.
|
||||
_BUILTIN_CATALOGS: dict[str, dict] = {
|
||||
"builtin://default": {
|
||||
"schema_version": "1.0",
|
||||
"catalog_url": "builtin://default",
|
||||
"bundles": {},
|
||||
},
|
||||
"builtin://community": {
|
||||
"schema_version": "1.0",
|
||||
"catalog_url": "builtin://community",
|
||||
"bundles": {},
|
||||
},
|
||||
}
|
||||
|
||||
HTTP_TIMEOUT_SECONDS = 10
|
||||
@@ -95,6 +96,18 @@ def _validate_remote_url(source_id: str, url: str) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _load_packaged_community_catalog() -> dict:
|
||||
core_pack = _locate_core_pack()
|
||||
path = (
|
||||
core_pack / "bundles" / "catalog.community.json"
|
||||
if core_pack is not None
|
||||
else _repo_root() / "bundles" / "catalog.community.json"
|
||||
)
|
||||
if not path.is_file():
|
||||
raise BundlerError(f"Bundled community catalog not found: {path}")
|
||||
return loads_json(path.read_text(encoding="utf-8"), origin=str(path))
|
||||
|
||||
|
||||
def make_catalog_fetcher(*, allow_network: bool = True):
|
||||
"""Return a fetcher callable suitable for :class:`CatalogStack`.
|
||||
|
||||
@@ -108,6 +121,10 @@ def make_catalog_fetcher(*, allow_network: bool = True):
|
||||
scheme = parsed.scheme.lower()
|
||||
|
||||
if scheme == "builtin":
|
||||
if url == "builtin://community":
|
||||
if allow_network:
|
||||
return _http_get_json(source.id, COMMUNITY_CATALOG_URL)
|
||||
return _load_packaged_community_catalog()
|
||||
payload = _BUILTIN_CATALOGS.get(url)
|
||||
if payload is None:
|
||||
raise BundlerError(f"Unknown built-in catalog '{url}'.")
|
||||
|
||||
Reference in New Issue
Block a user