feat(templates): promote examples/ to templates/<author>/<name>/ catalog layout

Set up the catalog directory structure this branch will fill with
community templates. The existing site-status-checker example moves
from examples/templates/ to templates/awizemann/site-status-checker/
(tracked by git as a rename so history is preserved). The examples/
directory is removed.

New top-level docs:
- templates/README.md — landing for folks browsing the catalog on
  github.com. Lists the current templates and points at the live site.
- templates/CONTRIBUTING.md — author-facing submission walkthrough.
  Requires AGENTS.md, pre-flight with tools/build-catalog.py --check
  (added in the next commit), one template per PR, don't edit
  catalog.json (maintainer regenerates it post-merge).

ProjectTemplateExampleTemplateTests.locateExample updated to search
templates/<author>/<name>/ instead of examples/templates/ — the test
still walks up from #filePath to find the repo root so it works in
both xcodebuild and Xcode IDE test runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-04-22 22:52:42 +01:00
parent 38c075d61d
commit d8a0a89db2
10 changed files with 201 additions and 42 deletions
+7 -5
View File
@@ -490,7 +490,7 @@ import Foundation
@Suite struct ProjectTemplateExampleTemplateTests {
@Test func siteStatusCheckerParsesAndPlans() throws {
let bundle = try Self.locateExample(name: "site-status-checker")
let bundle = try Self.locateExample(author: "awizemann", name: "site-status-checker")
let service = ProjectTemplateService(context: .local)
let inspection = try service.inspect(zipPath: bundle)
@@ -547,17 +547,19 @@ import Foundation
/// Resolve the example bundle path robustly. Unit-test working dirs
/// differ between `xcodebuild test` (project root) and an Xcode IDE
/// run (build-output dir), so we walk up from this source file until
/// we find the repo root.
nonisolated private static func locateExample(name: String) throws -> String {
/// we find the repo root. Templates live at
/// `templates/<author>/<name>/<name>.scarftemplate` per the catalog
/// layout (see `templates/README.md`).
nonisolated private static func locateExample(author: String, name: String) throws -> String {
var dir = URL(fileURLWithPath: #filePath).deletingLastPathComponent()
for _ in 0..<6 {
let candidate = dir.appendingPathComponent("examples/templates/\(name)/\(name).scarftemplate")
let candidate = dir.appendingPathComponent("templates/\(author)/\(name)/\(name).scarftemplate")
if FileManager.default.fileExists(atPath: candidate.path) {
return candidate.path
}
dir = dir.deletingLastPathComponent()
}
throw ProjectTemplateError.requiredFileMissing("examples/templates/\(name)/\(name).scarftemplate")
throw ProjectTemplateError.requiredFileMissing("templates/\(author)/\(name)/\(name).scarftemplate")
}
}