Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/preset-next-bun-reconcile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@codelitdev/platform-cli": patch
---

The preset and product template now pin `next` 16.4.3 and Bun 1.4.4, the patched releases, so `doctor` no longer fails products that already moved to them. `sync` also records a managed file that was reconciled by hand to the template instead of reporting it as a conflict.

## Product changes

- Use `next` 16.4.3 and Bun 1.4.4 (`packageManager`, CI `bun-version`, `@types/bun` 1.4.4).
- Run `bunx @codelitdev/platform-cli@<this version> sync`. If it reports `platform-conformance.yml` as a conflict, make that file match this release's template, then run `sync` again.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Install Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.4.1
bun-version: 1.4.4

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
- name: Install Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: 1.4.1
bun-version: 1.4.4

- name: Cache Bun install
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ Products depend on individual packages; CI verifies that resolved versions match
{
"schemaVersion": 1,
"runtime": {
"bun": "1.4.1"
"bun": "1.4.4"
},
"packages": {
"@codelitdev/platform": {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"description": "Shared infrastructure packages and product bootstrap for CodeLit applications",
"license": "UNLICENSED",
"type": "module",
"packageManager": "bun@1.4.1",
"packageManager": "bun@1.4.4",
"workspaces": [
"packages/*",
"examples/*/apps/*",
Expand All @@ -24,7 +24,7 @@
"@anatine/zod-openapi@1.14.2": "patches/@anatine__zod-openapi@1.14.2.patch"
},
"engines": {
"bun": ">=1.4.1"
"bun": ">=1.4.4"
},
"scripts": {
"build": "bun run --workspaces --if-present build",
Expand Down
2 changes: 1 addition & 1 deletion packages/billing/scripts/packed-consumer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ writeFileSync(
name: "consumer",
type: "module",
private: true,
packageManager: "bun@1.4.1",
packageManager: "bun@1.4.4",
},
null,
2,
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp-server-kit/scripts/packed-consumer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ writeFileSync(
name: "consumer",
type: "module",
private: true,
packageManager: "bun@1.4.1",
packageManager: "bun@1.4.4",
overrides: {
"@codelitdev/platform": platformTarball,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/observability/scripts/packed-consumer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ writeFileSync(
name: "consumer",
type: "module",
private: true,
packageManager: "bun@1.4.1",
packageManager: "bun@1.4.4",
}),
);
execFileSync("bun", ["add", tarball, "--ignore-scripts"], {
Expand Down
4 changes: 3 additions & 1 deletion packages/platform-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ bunx @codelitdev/platform-cli@0.2.0 sync
replaces a file only when its hash still matches the manifest, and creates a
newly managed file only when it is absent or already identical. Any other
difference is a conflict: nothing is written, and you reconcile the file by
hand. Writes require a clean Git worktree; `--dry-run` works in a dirty one. If
hand. To reconcile, make the file match this release's template, for example
by moving a product change into a product-owned file; the next `sync` records
it. Writes require a clean Git worktree; `--dry-run` works in a dirty one. If
writing fails, the CLI restores the files it changed.

When a release requires changes to product-owned files, its release notes say
Expand Down
2 changes: 1 addition & 1 deletion packages/platform-cli/scripts/packed-consumer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ writeFileSync(
name: "consumer",
type: "module",
private: true,
packageManager: "bun@1.4.1",
packageManager: "bun@1.4.4",
dependencies: {
"@codelitdev/platform-cli": tarball,
},
Expand Down
23 changes: 23 additions & 0 deletions packages/platform-cli/src/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,29 @@ describe("platform-cli", () => {
expect(readManifest(target)).toEqual(manifestBefore);
});

it("records a drifted managed file reconciled by hand to the template", () => {
const target = createCommitted("cli-reconcile-");
const file = path.join(target, WORKFLOW);
const desired = readFileSync(file, "utf8");
writeFileSync(file, "name: edited by the product\n");
const manifest = readManifest(target);
manifest.managedFiles[WORKFLOW] = sha256File(file);
writeManifest(target, manifest);
// An edit after the hash was recorded: drift.
writeFileSync(file, desired.replace("bun-version", "bun-version "));
expect(syncProduct({ root: target, allowDirty: true }).conflicts).toEqual([
WORKFLOW,
]);
// The product resolves it by restoring the template's content.
writeFileSync(file, desired);
git(target, ["commit", "-am", "reconcile workflow"]);
const result = syncProduct({ root: target });
expect(result.conflicts).toEqual([]);
expect(result.changed).toEqual([]);
expect(readManifest(target).managedFiles[WORKFLOW]).toBe(sha256File(file));
expect(doctor(target).issues.filter((i) => i.startsWith("managed_"))).toEqual([]);
});

it("adopts a missing managed file but not a different existing one", () => {
const target = createCommitted("cli-adopt-");
const manifest = readManifest(target);
Expand Down
2 changes: 1 addition & 1 deletion packages/platform-cli/src/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function validateGeneratedMetadata(root: string): void {
) as {
packageManager?: string;
};
if (packageJson.packageManager !== "bun@1.4.1") {
if (packageJson.packageManager !== "bun@1.4.4") {
throw new Error("create_metadata_invalid");
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/platform-cli/src/preset.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"runtime": {
"bun": "1.4.1"
"bun": "1.4.4"
},
"packages": {
"@codelitdev/platform": {
Expand Down Expand Up @@ -59,11 +59,11 @@
"drizzle-orm": "0.45.2",
"drizzle-kit": "0.31.10",
"pino": "9.6.0",
"@types/bun": "1.4.1",
"@types/bun": "1.4.4",
"@electric-sql/pglite": "0.5.8",
"@modelcontextprotocol/sdk": "1.30.0",
"dodopayments": "2.48.0",
"next": "16.3.6",
"next": "16.4.3",
"react": "19.2.8",
"react-dom": "19.2.8"
}
Expand Down
2 changes: 1 addition & 1 deletion packages/platform-cli/src/preset.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe("platform preset", () => {
it("ships schemaVersion 1 with recommended/supported/minimumSecure", () => {
const manifest = loadPresetManifest();
expect(manifest.schemaVersion).toBe(1);
expect(manifest.runtime.bun).toBe("1.4.1");
expect(manifest.runtime.bun).toBe("1.4.4");
const platform = manifest.packages["@codelitdev/platform"];
expect(platform?.recommended).toBeTruthy();
expect(platform?.supported).toContain(">=");
Expand Down
13 changes: 8 additions & 5 deletions packages/platform-cli/src/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,20 @@ export function syncProduct(input: {
const managedFiles: Record<string, string> = {};

// Compute and validate the complete plan before touching any file. A
// managed hash mismatch is a conflict, not a best-effort warning. A new
// managed file may be adopted only when it is absent or already identical.
// managed hash mismatch is a conflict, not a best-effort warning. A file
// that already matches the template is never a conflict: that is how a
// product reconciles a conflict by hand, and how a new managed file is
// adopted when it exists.
for (const rel of MANAGED_FILES) {
const file = path.join(root, rel);
const desired = renderTemplateFile(rel, manifest.product);
const recorded = manifest.managedFiles[rel];
const current = existsSync(file) ? readFileSync(file, "utf8") : undefined;
const drifted =
recorded === undefined
? current !== undefined && current !== desired
: current === undefined || sha256File(file) !== recorded;
current !== desired &&
(recorded === undefined
? current !== undefined
: current === undefined || sha256File(file) !== recorded);
if (drifted) {
conflicts.push(rel);
continue;
Expand Down
2 changes: 1 addition & 1 deletion packages/platform-conformance/scripts/packed-consumer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ writeFileSync(
name: "consumer",
type: "module",
private: true,
packageManager: "bun@1.4.1",
packageManager: "bun@1.4.4",
overrides: {
"@codelitdev/platform": platformTarball,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/platform/scripts/packed-consumer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ writeFileSync(
name: "consumer",
type: "module",
private: true,
packageManager: "bun@1.4.1",
packageManager: "bun@1.4.4",
},
null,
2,
Expand Down
2 changes: 1 addition & 1 deletion templates/saas-product/.github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.4.1
bun-version: 1.4.4
# `platform-cli create` intentionally does not resolve dependencies.
# Bootstrap the product lockfile on its first run; all subsequent CI
# installs are immutable and use the frozen lockfile below.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.4.1
bun-version: 1.4.4
# `platform-cli create` intentionally does not resolve dependencies.
# Bootstrap the product lockfile on its first run; all subsequent CI
# installs are immutable and use the frozen lockfile below.
Expand Down
2 changes: 1 addition & 1 deletion templates/saas-product/apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@
"@types/swagger-ui-express": "^4.1.8",
"drizzle-kit": "0.31.10",
"typescript": "5.9.3",
"@types/bun": "1.4.1"
"@types/bun": "1.4.4"
}
}
2 changes: 1 addition & 1 deletion templates/saas-product/apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"dependencies": {
"@codelitdev/design-system": "workspace:*",
"@codelitdev/observability": "workspace:*",
"next": "16.3.6",
"next": "16.4.3",
"posthog-js": "^1.427.2",
"react": "19.2.8",
"react-dom": "19.2.8"
Expand Down
6 changes: 3 additions & 3 deletions templates/saas-product/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"private": true,
"version": "0.0.0",
"type": "module",
"packageManager": "bun@1.4.1",
"packageManager": "bun@1.4.4",
"engines": {
"bun": ">=1.4.1"
"bun": ">=1.4.4"
},
"workspaces": [
"apps/*",
Expand All @@ -25,7 +25,7 @@
},
"devDependencies": {
"@biomejs/biome": "2.5.12",
"@types/bun": "1.4.1"
"@types/bun": "1.4.4"
},
"scripts": {
"lint": "bun run --workspaces --if-present lint",
Expand Down
Loading