Skip to content

Commit 534cea3

Browse files
Tommypop2claude
andcommitted
fix: always scaffold from live templates HEAD
Template downloads were pinned to a baked-in solidjs/templates SHA (TEMPLATES_REF), so every upstream template or dependency repin needed a CLI release to reach users. Drop the pin and the SOLID_CLI_TEMPLATES_REF override: scaffolds now come from live HEAD of the default branch, matching what the templates.json manifest already did. Rework the download tests to survive upstream churn: they resolve the template name and subdir from the live manifest, then assert the scaffold is a usable project (package.json parses, has scripts and dependencies, src/ is non-empty) instead of pinning specific filenames or dependency versions. Each test now also starts from a clean destination and removes it afterwards — the previous tests asserted against ./test/ts, which a leftover scaffold from an earlier run could satisfy on its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent fdeaa45 commit 534cea3

3 files changed

Lines changed: 66 additions & 23 deletions

File tree

.changeset/solid-v2-templates.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ Solid 2.0 template support
99
- Optional streaming SSR on templates that support it (currently `basic`): a scaffold-time flip that sets `ssr: true` in `vite.config.ts`, adds the generic production `server.js`, and points the `start` script at it. Defaults to No.
1010
- JavaScript variants of the Solid 2.0 templates via the existing sucrase TS→JS conversion (no `index.html` rewrite; `.ts`/`.tsx` references inside `vite.config` are retargeted, `.d.ts` files dropped, minimal `jsconfig.json`).
1111
- Template lists, subdir paths and per-template flags are now read from a `templates.json` manifest at the templates repo HEAD (2s timeout), with silent fallback to the baked-in lists — so new templates and future repo reorganizations no longer require a CLI release.
12-
- Template tarball downloads can be pinned to a templates-repo ref per CLI release (`TEMPLATES_REF`, overridable via `SOLID_CLI_TEMPLATES_REF`).
12+
- Template tarball downloads track live HEAD of the templates repo, matching the `templates.json` manifest, so template contents and their dependency updates reach users without a CLI release.

packages/create/src/utils/download.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,11 @@ import { downloadRepo, GithubFetcher } from "@begit/core";
33
export const TEMPLATES_REPO = { owner: "solidjs", name: "templates" } as const;
44

55
/**
6-
* Optional ref (tag, sha or branch) of solidjs/templates that scaffold downloads
7-
* are pinned to. Set this at release time (e.g. to a `cli-x.y` tag) so a published
8-
* CLI version keeps scaffolding exactly what it was tested against, immune to
9-
* later reorganizations of the templates repo. `undefined` means live HEAD of the
10-
* default branch, which is the historical behavior.
6+
* Downloads `subdir` of the solidjs/templates repo into `destination`.
7+
*
8+
* No ref is pinned: scaffolds always come from live HEAD of the default branch,
9+
* matching the `templates.json` manifest, so template updates reach users
10+
* without a CLI release.
1111
*/
12-
export const TEMPLATES_REF: string | undefined = "f88b107279694c1cb9a6de8bb1daad09abb263b0";
13-
14-
/** `SOLID_CLI_TEMPLATES_REF` overrides the baked ref, for testing against branches/forks */
15-
export const templatesRef = () => process.env.SOLID_CLI_TEMPLATES_REF || TEMPLATES_REF;
16-
17-
/** Downloads `subdir` of the solidjs/templates repo (at the pinned ref, if any) into `destination` */
1812
export const downloadTemplate = (subdir: string, destination: string) =>
19-
downloadRepo({ repo: { ...TEMPLATES_REPO, subdir, hash: templatesRef() }, dest: destination }, GithubFetcher);
13+
downloadRepo({ repo: { ...TEMPLATES_REPO, subdir }, dest: destination }, GithubFetcher);
Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,65 @@
1-
import { expect, it } from "vitest";
1+
import { afterEach, expect, it } from "vitest";
2+
import { existsSync, readdirSync, readFileSync, rmSync } from "node:fs";
3+
import { join } from "node:path";
24
import { createSolidV2, createVanilla } from "../src";
3-
import { existsSync } from "fs";
4-
it("downloads and extracts the basic template", async () => {
5-
await createVanilla({ template: "basic", destination: "./test/ts" }, false);
5+
import { fetchTemplatesManifest, resolveGroup, type ManifestGroupKey } from "../src/utils/manifest";
66

7-
const appTsx = existsSync("./test/ts/src/App.tsx");
8-
expect(appTsx).toBe(true);
7+
/**
8+
* These download from live solidjs/templates HEAD, so they assert the plumbing —
9+
* that the right subdir was fetched and extracted into a usable project — rather
10+
* than specific files or dependency versions. Template contents, pins and file
11+
* layout all change upstream without a CLI release, and must not fail CI here.
12+
*/
13+
14+
/** Template name + subdir the CLI would actually use, from the live manifest (baked-in fallback) */
15+
const liveTarget = async (key: ManifestGroupKey) => {
16+
const group = resolveGroup(await fetchTemplatesManifest(), key);
17+
const template = group.templates.find((t) => t.default) ?? group.templates[0];
18+
return { path: group.path, template: template.name };
19+
};
20+
21+
// begit resolves the destination against `process.cwd()`, so scaffold targets have to be
22+
// repo-relative. `test/` is gitignored; each run starts from a clean directory so a
23+
// leftover scaffold can never satisfy the assertions on its own.
24+
const destinations: string[] = [];
25+
const scratch = (name: string) => {
26+
const destination = join("test", name);
27+
rmSync(destination, { recursive: true, force: true });
28+
destinations.push(destination);
29+
return destination;
30+
};
31+
32+
afterEach(() => {
33+
for (const destination of destinations.splice(0)) rmSync(destination, { recursive: true, force: true });
934
});
1035

11-
it("downloads and extracts the solid-v2 basic template", async () => {
12-
await createSolidV2({ template: "basic", destination: "./test/solid-v2" }, false);
36+
const expectScaffold = (destination: string) => {
37+
const packageJsonPath = join(destination, "package.json");
38+
expect(existsSync(packageJsonPath)).toBe(true);
39+
40+
const packageJson = JSON.parse(readFileSync(packageJsonPath).toString());
41+
expect(typeof packageJson.name).toBe("string");
42+
expect(Object.keys(packageJson.scripts ?? {}).length).toBeGreaterThan(0);
43+
expect(Object.keys(packageJson.dependencies ?? {}).length).toBeGreaterThan(0);
44+
45+
// Some source to build, whatever the entry files happen to be called
46+
expect(readdirSync(join(destination, "src")).length).toBeGreaterThan(0);
47+
};
48+
49+
it("downloads and extracts the vanilla template", async () => {
50+
const destination = scratch("vanilla");
51+
const { path, template } = await liveTarget("vanilla");
52+
53+
await createVanilla({ template, destination, path }, false);
54+
55+
expectScaffold(destination);
56+
});
57+
58+
it("downloads and extracts the solid-v2 template", async () => {
59+
const destination = scratch("solid-v2");
60+
const { path, template } = await liveTarget("solid");
61+
62+
await createSolidV2({ template, destination, path }, false);
1363

14-
const appTsx = existsSync("./test/solid-v2/src/App.tsx");
15-
expect(appTsx).toBe(true);
64+
expectScaffold(destination);
1665
});

0 commit comments

Comments
 (0)