Support Beta release channel (#591)
This commit is contained in:
@@ -837,6 +837,15 @@ export class PageObject {
|
|||||||
await this.page.getByRole("switch", { name: "Auto-update" }).click();
|
await this.page.getByRole("switch", { name: "Auto-update" }).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async changeReleaseChannel(channel: "stable" | "beta") {
|
||||||
|
// await page.getByRole('combobox').filter({ hasText: 'Stable' }).click();
|
||||||
|
// await page.getByRole('option', { name: 'Beta' }).dblclick();
|
||||||
|
await this.page.getByRole("combobox", { name: "Release Channel" }).click();
|
||||||
|
await this.page
|
||||||
|
.getByRole("option", { name: channel === "stable" ? "Stable" : "Beta" })
|
||||||
|
.click();
|
||||||
|
}
|
||||||
|
|
||||||
async clickTelemetryAccept() {
|
async clickTelemetryAccept() {
|
||||||
await this.page.getByTestId("telemetry-accept-button").click();
|
await this.page.getByTestId("telemetry-accept-button").click();
|
||||||
}
|
}
|
||||||
|
|||||||
22
e2e-tests/release_channel.spec.ts
Normal file
22
e2e-tests/release_channel.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { expect } from "@playwright/test";
|
||||||
|
import { test } from "./helpers/test_helper";
|
||||||
|
|
||||||
|
test("release channel - change from stable to beta and back", async ({
|
||||||
|
po,
|
||||||
|
}) => {
|
||||||
|
await po.goToSettingsTab();
|
||||||
|
|
||||||
|
// Change to beta channel
|
||||||
|
await po.changeReleaseChannel("beta");
|
||||||
|
await expect(
|
||||||
|
po.page.getByRole("button", { name: "Restart Dyad" }),
|
||||||
|
).toBeVisible();
|
||||||
|
await po.snapshotSettings();
|
||||||
|
|
||||||
|
// Change back to stable channel
|
||||||
|
await po.changeReleaseChannel("stable");
|
||||||
|
await expect(
|
||||||
|
po.page.getByRole("button", { name: "Download Stable" }),
|
||||||
|
).toBeVisible();
|
||||||
|
await po.snapshotSettings();
|
||||||
|
});
|
||||||
@@ -14,5 +14,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": false,
|
"enableAutoUpdate": false,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -14,5 +14,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -16,5 +16,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"selectedModel": {
|
||||||
|
"name": "auto",
|
||||||
|
"provider": "auto"
|
||||||
|
},
|
||||||
|
"providerSettings": {},
|
||||||
|
"telemetryConsent": "unset",
|
||||||
|
"telemetryUserId": "[UUID]",
|
||||||
|
"hasRunBefore": true,
|
||||||
|
"experiments": {},
|
||||||
|
"lastShownReleaseNotesVersion": "[scrubbed]",
|
||||||
|
"enableProLazyEditsMode": true,
|
||||||
|
"enableProSmartFilesContextMode": true,
|
||||||
|
"selectedChatMode": "build",
|
||||||
|
"enableAutoFixProblems": false,
|
||||||
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "beta",
|
||||||
|
"isTestMode": true
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"selectedModel": {
|
||||||
|
"name": "auto",
|
||||||
|
"provider": "auto"
|
||||||
|
},
|
||||||
|
"providerSettings": {},
|
||||||
|
"telemetryConsent": "unset",
|
||||||
|
"telemetryUserId": "[UUID]",
|
||||||
|
"hasRunBefore": true,
|
||||||
|
"experiments": {},
|
||||||
|
"lastShownReleaseNotesVersion": "[scrubbed]",
|
||||||
|
"enableProLazyEditsMode": true,
|
||||||
|
"enableProSmartFilesContextMode": true,
|
||||||
|
"selectedChatMode": "build",
|
||||||
|
"enableAutoFixProblems": false,
|
||||||
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
|
"isTestMode": true
|
||||||
|
}
|
||||||
@@ -13,5 +13,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -14,5 +14,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -13,5 +13,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -14,5 +14,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -13,5 +13,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -14,5 +14,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -23,5 +23,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -23,5 +23,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
@@ -23,5 +23,6 @@
|
|||||||
"selectedChatMode": "build",
|
"selectedChatMode": "build",
|
||||||
"enableAutoFixProblems": false,
|
"enableAutoFixProblems": false,
|
||||||
"enableAutoUpdate": true,
|
"enableAutoUpdate": true,
|
||||||
|
"releaseChannel": "stable",
|
||||||
"isTestMode": true
|
"isTestMode": true
|
||||||
}
|
}
|
||||||
76
src/components/ReleaseChannelSelector.tsx
Normal file
76
src/components/ReleaseChannelSelector.tsx
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import { useSettings } from "@/hooks/useSettings";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import { IpcClient } from "@/ipc/ipc_client";
|
||||||
|
import type { ReleaseChannel } from "@/lib/schemas";
|
||||||
|
|
||||||
|
export function ReleaseChannelSelector() {
|
||||||
|
const { settings, updateSettings } = useSettings();
|
||||||
|
|
||||||
|
if (!settings) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleReleaseChannelChange = (value: ReleaseChannel) => {
|
||||||
|
updateSettings({ releaseChannel: value });
|
||||||
|
if (value === "stable") {
|
||||||
|
toast("Using Stable release channel", {
|
||||||
|
description:
|
||||||
|
"You'll stay on your current version until a newer stable release is available, or you can manually downgrade now.",
|
||||||
|
action: {
|
||||||
|
label: "Download Stable",
|
||||||
|
onClick: () => {
|
||||||
|
IpcClient.getInstance().openExternalUrl("https://dyad.sh/download");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toast("Using Beta release channel", {
|
||||||
|
description:
|
||||||
|
"You will need to restart Dyad for your settings to take effect.",
|
||||||
|
action: {
|
||||||
|
label: "Restart Dyad",
|
||||||
|
onClick: () => {
|
||||||
|
IpcClient.getInstance().restartDyad();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-1">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<label
|
||||||
|
htmlFor="release-channel"
|
||||||
|
className="text-sm font-medium text-gray-700 dark:text-gray-300"
|
||||||
|
>
|
||||||
|
Release Channel
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
value={settings.releaseChannel}
|
||||||
|
onValueChange={handleReleaseChannelChange}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-32" id="release-channel">
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="stable">Stable</SelectItem>
|
||||||
|
<SelectItem value="beta">Beta</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
<p>Stable is recommended for most users. </p>
|
||||||
|
<p>Beta receives more frequent updates but may have more bugs.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -125,6 +125,9 @@ export type ContextPathResults = {
|
|||||||
smartContextAutoIncludes: ContextPathResult[];
|
smartContextAutoIncludes: ContextPathResult[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ReleaseChannelSchema = z.enum(["stable", "beta"]);
|
||||||
|
export type ReleaseChannel = z.infer<typeof ReleaseChannelSchema>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zod schema for user settings
|
* Zod schema for user settings
|
||||||
*/
|
*/
|
||||||
@@ -152,6 +155,7 @@ export const UserSettingsSchema = z.object({
|
|||||||
enableAutoFixProblems: z.boolean().optional(),
|
enableAutoFixProblems: z.boolean().optional(),
|
||||||
enableNativeGit: z.boolean().optional(),
|
enableNativeGit: z.boolean().optional(),
|
||||||
enableAutoUpdate: z.boolean(),
|
enableAutoUpdate: z.boolean(),
|
||||||
|
releaseChannel: ReleaseChannelSchema,
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// E2E TESTING ONLY.
|
// E2E TESTING ONLY.
|
||||||
|
|||||||
16
src/main.ts
16
src/main.ts
@@ -4,7 +4,7 @@ import { registerIpcHandlers } from "./ipc/ipc_host";
|
|||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import started from "electron-squirrel-startup";
|
import started from "electron-squirrel-startup";
|
||||||
import { updateElectronApp } from "update-electron-app";
|
import { updateElectronApp, UpdateSourceType } from "update-electron-app";
|
||||||
import log from "electron-log";
|
import log from "electron-log";
|
||||||
import { readSettings, writeSettings } from "./main/settings";
|
import { readSettings, writeSettings } from "./main/settings";
|
||||||
import { handleSupabaseOAuthReturn } from "./supabase_admin/supabase_return_handler";
|
import { handleSupabaseOAuthReturn } from "./supabase_admin/supabase_return_handler";
|
||||||
@@ -20,7 +20,19 @@ const logger = log.scope("main");
|
|||||||
// Check settings before enabling auto-update
|
// Check settings before enabling auto-update
|
||||||
const settings = readSettings();
|
const settings = readSettings();
|
||||||
if (settings.enableAutoUpdate) {
|
if (settings.enableAutoUpdate) {
|
||||||
updateElectronApp({ logger }); // additional configuration options available
|
// Technically we could just pass the releaseChannel directly to the host,
|
||||||
|
// but this is more explicit and falls back to stable if there's an unknown
|
||||||
|
// release channel.
|
||||||
|
const postfix = settings.releaseChannel === "beta" ? "beta" : "stable";
|
||||||
|
const host = `https://api.dyad.sh/v1/update/${postfix}`;
|
||||||
|
updateElectronApp({
|
||||||
|
logger,
|
||||||
|
updateSource: {
|
||||||
|
type: UpdateSourceType.ElectronPublicUpdateService,
|
||||||
|
repo: "dyad-sh/dyad",
|
||||||
|
host,
|
||||||
|
},
|
||||||
|
}); // additional configuration options available
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load environment variables from .env file
|
// Load environment variables from .env file
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ const DEFAULT_SETTINGS: UserSettings = {
|
|||||||
selectedChatMode: "build",
|
selectedChatMode: "build",
|
||||||
enableAutoFixProblems: false,
|
enableAutoFixProblems: false,
|
||||||
enableAutoUpdate: true,
|
enableAutoUpdate: true,
|
||||||
|
releaseChannel: "stable",
|
||||||
};
|
};
|
||||||
|
|
||||||
const SETTINGS_FILE = "user-settings.json";
|
const SETTINGS_FILE = "user-settings.json";
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { Switch } from "@/components/ui/switch";
|
|||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { AutoFixProblemsSwitch } from "@/components/AutoFixProblemsSwitch";
|
import { AutoFixProblemsSwitch } from "@/components/AutoFixProblemsSwitch";
|
||||||
import { AutoUpdateSwitch } from "@/components/AutoUpdateSwitch";
|
import { AutoUpdateSwitch } from "@/components/AutoUpdateSwitch";
|
||||||
|
import { ReleaseChannelSelector } from "@/components/ReleaseChannelSelector";
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
const [isResetDialogOpen, setIsResetDialogOpen] = useState(false);
|
const [isResetDialogOpen, setIsResetDialogOpen] = useState(false);
|
||||||
@@ -270,6 +271,10 @@ export function GeneralSettings({ appVersion }: { appVersion: string | null }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-4">
|
||||||
|
<ReleaseChannelSelector />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center text-sm text-gray-500 dark:text-gray-400 mt-4">
|
<div className="flex items-center text-sm text-gray-500 dark:text-gray-400 mt-4">
|
||||||
<span className="mr-2 font-medium">App Version:</span>
|
<span className="mr-2 font-medium">App Version:</span>
|
||||||
<span className="bg-gray-100 dark:bg-gray-700 px-2 py-0.5 rounded text-gray-800 dark:text-gray-200 font-mono">
|
<span className="bg-gray-100 dark:bg-gray-700 px-2 py-0.5 rounded text-gray-800 dark:text-gray-200 font-mono">
|
||||||
|
|||||||
Reference in New Issue
Block a user