Skip to content

Commit ab59066

Browse files
Move macOS version validation from @cloudflare/cli to miniflare (#10211)
* Move macOS version validation from @cloudflare/cli to miniflare BREAKING CHANGE: Miniflare constructor now throws an error when running on unsupported macOS versions (below 13.5) instead of just logging a warning. - Move validateMacOSVersion, darwinVersionToMacOSVersion, and isVersionLessThan functions from @cloudflare/cli to miniflare - Add validateMacOSVersion call to Miniflare constructor (fails hard) - Add warnMacOSVersion function for non-breaking warnings - Update Wrangler to use warnMacOSVersion from miniflare - Update C3 to use warnMacOSVersion from miniflare - Remove old validation logic from @cloudflare/cli package - Add comprehensive tests for both validation functions - Update C3 build configuration and dependencies Co-Authored-By: [email protected] <[email protected]> * Fix CI environment detection and address changeset feedback - Update CI detection to check for any truthy CI value instead of just 'true' - Add test cases for CI='1' and CI='yes' to ensure robustness - Remove 'BREAKING CHANGE' language from changeset per user feedback - Clarify that this makes errors more informative rather than introducing new errors Co-Authored-By: [email protected] <[email protected]> * Revert macOS validation to @cloudflare/cli architecture - Move validation functions back to @cloudflare/cli to keep C3 lightweight - Remove miniflare dependency from C3 to avoid forcing workerd download - Update imports in Wrangler, C3, and Miniflare to use @cloudflare/cli - Remove validation logic from Miniflare constructor - Update changeset description to reflect architectural change This addresses @petebacondarwin's feedback that C3 should remain fast and lightweight without requiring workerd installation. Co-Authored-By: [email protected] <[email protected]> * Update pnpm-lock.yaml after removing miniflare dependency from C3 Co-Authored-By: [email protected] <[email protected]> * Remove unused validateMacOSVersion import from miniflare This fixes the lint error 'validateMacOSVersion' is defined but never used that was causing CI failures after the architectural revert. Co-Authored-By: [email protected] <[email protected]> * Add validateMacOSVersion call to Miniflare constructor This completes the architectural revert by ensuring Miniflare validates macOS versions using the function from @cloudflare/cli, as requested in the GitHub comment. Co-Authored-By: [email protected] <[email protected]> * Update changeset to combine behavior from PR #10176 and current PR - Consolidated into existing .changeset/silly-things-walk.md - Added @cloudflare/cli as minor (new validation functions) - Updated package versions to reflect architectural changes - Removed duplicate changeset file as requested by @petebacondarwin Co-Authored-By: [email protected] <[email protected]> * Fix miniflare build to bundle @cloudflare/cli dependency - Remove @cloudflare/cli from external dependencies list - This allows validateMacOSVersion to be bundled and available at runtime - Fixes CI failure where @cloudflare/cli was not available in miniflare Co-Authored-By: [email protected] <[email protected]> * Refactor validateMacOSVersion to eliminate code duplication - Combine validateMacOSVersion and warnMacOSVersion into single function with boolean parameter - Add shouldThrow parameter to control error vs warning behavior - Keep warnMacOSVersion as convenience wrapper calling validateMacOSVersion(false) - Update Miniflare constructor to explicitly pass true for hard validation - Addresses GitHub comment from @emily-shen about reducing duplicate code Co-Authored-By: [email protected] <[email protected]> * Make changeset description more concise - Simplify changeset to 2 sentences as requested by @emily-shen - Remove verbose sections and overly enthusiastic language - Keep essential information about macOS validation behavior Co-Authored-By: [email protected] <[email protected]> * Address GitHub comments: simplify API and fix dependency management - Remove warnMacOSVersion() function as requested by @petebacondarwin - Update Wrangler and C3 to call validateMacOSVersion(false) directly - Move @cloudflare/cli from dependencies to devDependencies in miniflare - Remove special case filter in build.mjs since @cloudflare/cli is now bundled as devDependency This addresses both GitHub comments on PR #10211 Co-Authored-By: [email protected] <[email protected]> * Apply formatting fixes from pnpm fix Co-Authored-By: [email protected] <[email protected]> * Fix CLI tests after removing warnMacOSVersion function - Remove warnMacOSVersion from import statement - Update test suite to use validateMacOSVersion(false) instead - Maintain same test coverage for warning behavior Co-Authored-By: [email protected] <[email protected]> * Update lockfile after adding @cloudflare/cli devDependency to miniflare - Fixes CI failure: 'Cannot install with frozen-lockfile because pnpm-lock.yaml is not up to date' - Resolves dependency mismatch for @cloudflare/cli in miniflare package.json Co-Authored-By: [email protected] <[email protected]> * Improve error message text to specify glibc 2.35+ requirement for Linux Addresses @emily-shen's feedback to make Linux requirements more specific in both error and warning messages. Co-Authored-By: [email protected] <[email protected]> * Change C3 to hard fail on unsupported macOS versions Addresses @emily-shen's feedback to change C3 behavior from validateMacOSVersion(false) to validateMacOSVersion(true) for consistency with the requirement that C3 should hard fail on unsupported macOS versions. Co-Authored-By: [email protected] <[email protected]> * Update changeset description to reflect C3 hard fail behavior After addressing @emily-shen's feedback, C3 now uses validateMacOSVersion(true) for hard fail behavior, matching Miniflare. Only Wrangler shows warnings. Co-Authored-By: [email protected] <[email protected]> * Improve version validation robustness and update API - Add regex validation to isVersionLessThan function to ensure M.m.p format - Update test file to use new ensureMinimumMacOsVersion API with object parameters - Add comprehensive test coverage for both new and deprecated functions - Address @vicb's feedback about stricter version format validation All tests pass locally and code follows repository standards. Co-Authored-By: [email protected] <[email protected]> * Rename function and files from validateMacOSVersion to checkMacOSVersion - Rename validate-macos-version.ts to check-macos-version.ts - Rename validate-macos-version.test.ts to check-macos-version.test.ts - Update all import statements to reference new file names - Address GitHub feedback from @petebacondarwin Co-Authored-By: [email protected] <[email protected]> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: [email protected] <[email protected]>
1 parent 9901788 commit ab59066

File tree

11 files changed

+322
-159
lines changed

11 files changed

+322
-159
lines changed

.changeset/silly-things-walk.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
---
2-
"create-cloudflare": minor
3-
"wrangler": minor
2+
"@cloudflare/cli": minor
3+
"miniflare": patch
4+
"wrangler": patch
5+
"create-cloudflare": patch
46
---
57

6-
Add macOS version validation to prevent EPIPE errors on unsupported macOS versions
8+
Add macOS version validation to prevent EPIPE errors on unsupported macOS versions (below 13.5). Miniflare and C3 fail hard while Wrangler shows warnings but continues execution.
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import os from "node:os";
2+
import { beforeEach, describe, expect, it, vi } from "vitest";
3+
import { checkMacOSVersion } from "../check-macos-version";
4+
5+
vi.mock("node:os");
6+
7+
const mockOs = vi.mocked(os);
8+
9+
describe("checkMacOSVersion", () => {
10+
beforeEach(() => {
11+
vi.clearAllMocks();
12+
vi.unstubAllEnvs();
13+
});
14+
15+
it("should not throw on non-macOS platforms", () => {
16+
vi.spyOn(process, "platform", "get").mockReturnValue("linux");
17+
18+
expect(() => checkMacOSVersion({ shouldThrow: true })).not.toThrow();
19+
});
20+
21+
it("should not throw on macOS 13.5.0", () => {
22+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
23+
mockOs.release.mockReturnValue("22.6.0");
24+
25+
expect(() => checkMacOSVersion({ shouldThrow: true })).not.toThrow();
26+
});
27+
28+
it("should not throw on macOS 14.0.0", () => {
29+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
30+
mockOs.release.mockReturnValue("23.0.0");
31+
32+
expect(() => checkMacOSVersion({ shouldThrow: true })).not.toThrow();
33+
});
34+
35+
it("should not throw on macOS 13.6.0", () => {
36+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
37+
mockOs.release.mockReturnValue("22.7.0");
38+
39+
expect(() => checkMacOSVersion({ shouldThrow: true })).not.toThrow();
40+
});
41+
42+
it("should throw error on macOS 12.7.6", () => {
43+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
44+
vi.stubEnv("CI", "");
45+
mockOs.release.mockReturnValue("21.6.0");
46+
47+
expect(() => checkMacOSVersion({ shouldThrow: true })).toThrow(
48+
"Unsupported macOS version: The Cloudflare Workers runtime cannot run on the current version of macOS (12.6.0)"
49+
);
50+
});
51+
52+
it("should throw error on macOS 13.4.0", () => {
53+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
54+
vi.stubEnv("CI", "");
55+
mockOs.release.mockReturnValue("22.4.0");
56+
57+
expect(() => checkMacOSVersion({ shouldThrow: true })).toThrow(
58+
"Unsupported macOS version: The Cloudflare Workers runtime cannot run on the current version of macOS (13.4.0)"
59+
);
60+
});
61+
62+
it("should handle invalid Darwin version format gracefully", () => {
63+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
64+
mockOs.release.mockReturnValue("invalid-version");
65+
66+
expect(() => checkMacOSVersion({ shouldThrow: true })).not.toThrow();
67+
});
68+
69+
it("should handle very old Darwin versions gracefully", () => {
70+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
71+
mockOs.release.mockReturnValue("19.6.0");
72+
73+
expect(() => checkMacOSVersion({ shouldThrow: true })).not.toThrow();
74+
});
75+
76+
it("should not throw when CI environment variable is set to 'true'", () => {
77+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
78+
vi.stubEnv("CI", "true");
79+
mockOs.release.mockReturnValue("21.6.0");
80+
81+
expect(() => checkMacOSVersion({ shouldThrow: true })).not.toThrow();
82+
});
83+
84+
it("should not throw when CI environment variable is set to '1'", () => {
85+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
86+
vi.stubEnv("CI", "1");
87+
mockOs.release.mockReturnValue("21.6.0");
88+
89+
expect(() => checkMacOSVersion({ shouldThrow: true })).not.toThrow();
90+
});
91+
92+
it("should not throw when CI environment variable is set to 'yes'", () => {
93+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
94+
vi.stubEnv("CI", "yes");
95+
mockOs.release.mockReturnValue("21.6.0");
96+
97+
expect(() => checkMacOSVersion({ shouldThrow: true })).not.toThrow();
98+
});
99+
});
100+
101+
describe("checkMacOSVersion with shouldThrow=false", () => {
102+
beforeEach(() => {
103+
vi.clearAllMocks();
104+
vi.unstubAllEnvs();
105+
});
106+
107+
it("should not warn on non-macOS platforms", () => {
108+
vi.spyOn(process, "platform", "get").mockReturnValue("linux");
109+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
110+
111+
checkMacOSVersion({ shouldThrow: false });
112+
113+
expect(warnSpy).not.toHaveBeenCalled();
114+
});
115+
116+
it("should not warn on macOS 13.5.0", () => {
117+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
118+
mockOs.release.mockReturnValue("22.6.0");
119+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
120+
121+
checkMacOSVersion({ shouldThrow: false });
122+
123+
expect(warnSpy).not.toHaveBeenCalled();
124+
});
125+
126+
it("should warn on macOS 12.7.6", () => {
127+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
128+
vi.stubEnv("CI", "");
129+
mockOs.release.mockReturnValue("21.6.0");
130+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
131+
132+
checkMacOSVersion({ shouldThrow: false });
133+
134+
expect(warnSpy).toHaveBeenCalledWith(
135+
expect.stringContaining(
136+
"⚠️ Warning: Unsupported macOS version detected (12.6.0)"
137+
)
138+
);
139+
});
140+
141+
it("should warn on macOS 13.4.0", () => {
142+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
143+
vi.stubEnv("CI", "");
144+
mockOs.release.mockReturnValue("22.4.0");
145+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
146+
147+
checkMacOSVersion({ shouldThrow: false });
148+
149+
expect(warnSpy).toHaveBeenCalledWith(
150+
expect.stringContaining(
151+
"⚠️ Warning: Unsupported macOS version detected (13.4.0)"
152+
)
153+
);
154+
});
155+
156+
it("should not warn when CI environment variable is set to 'true'", () => {
157+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
158+
vi.stubEnv("CI", "true");
159+
mockOs.release.mockReturnValue("21.6.0");
160+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
161+
162+
checkMacOSVersion({ shouldThrow: false });
163+
164+
expect(warnSpy).not.toHaveBeenCalled();
165+
});
166+
167+
it("should not warn when CI environment variable is set to '1'", () => {
168+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
169+
vi.stubEnv("CI", "1");
170+
mockOs.release.mockReturnValue("21.6.0");
171+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
172+
173+
checkMacOSVersion({ shouldThrow: false });
174+
175+
expect(warnSpy).not.toHaveBeenCalled();
176+
});
177+
178+
it("should not warn when CI environment variable is set to 'yes'", () => {
179+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
180+
vi.stubEnv("CI", "yes");
181+
mockOs.release.mockReturnValue("21.6.0");
182+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
183+
184+
checkMacOSVersion({ shouldThrow: false });
185+
186+
expect(warnSpy).not.toHaveBeenCalled();
187+
});
188+
189+
it("should not warn on invalid Darwin version format", () => {
190+
vi.spyOn(process, "platform", "get").mockReturnValue("darwin");
191+
mockOs.release.mockReturnValue("invalid-version");
192+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
193+
194+
checkMacOSVersion({ shouldThrow: false });
195+
196+
expect(warnSpy).not.toHaveBeenCalled();
197+
});
198+
});

packages/cli/__tests__/validate-macos-version.test.ts

Lines changed: 0 additions & 83 deletions
This file was deleted.

0 commit comments

Comments
 (0)