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();
|
||||
}
|
||||
|
||||
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() {
|
||||
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",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": false,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,5 +14,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,5 +16,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"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",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,5 +14,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -13,5 +13,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,5 +14,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -13,5 +13,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,5 +14,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -23,5 +23,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -23,5 +23,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -23,5 +23,6 @@
|
||||
"selectedChatMode": "build",
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"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[];
|
||||
};
|
||||
|
||||
export const ReleaseChannelSchema = z.enum(["stable", "beta"]);
|
||||
export type ReleaseChannel = z.infer<typeof ReleaseChannelSchema>;
|
||||
|
||||
/**
|
||||
* Zod schema for user settings
|
||||
*/
|
||||
@@ -152,6 +155,7 @@ export const UserSettingsSchema = z.object({
|
||||
enableAutoFixProblems: z.boolean().optional(),
|
||||
enableNativeGit: z.boolean().optional(),
|
||||
enableAutoUpdate: z.boolean(),
|
||||
releaseChannel: ReleaseChannelSchema,
|
||||
|
||||
////////////////////////////////
|
||||
// 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";
|
||||
// @ts-ignore
|
||||
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 { readSettings, writeSettings } from "./main/settings";
|
||||
import { handleSupabaseOAuthReturn } from "./supabase_admin/supabase_return_handler";
|
||||
@@ -20,7 +20,19 @@ const logger = log.scope("main");
|
||||
// Check settings before enabling auto-update
|
||||
const settings = readSettings();
|
||||
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
|
||||
|
||||
@@ -22,6 +22,7 @@ const DEFAULT_SETTINGS: UserSettings = {
|
||||
selectedChatMode: "build",
|
||||
enableAutoFixProblems: false,
|
||||
enableAutoUpdate: true,
|
||||
releaseChannel: "stable",
|
||||
};
|
||||
|
||||
const SETTINGS_FILE = "user-settings.json";
|
||||
|
||||
@@ -19,6 +19,7 @@ import { Switch } from "@/components/ui/switch";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { AutoFixProblemsSwitch } from "@/components/AutoFixProblemsSwitch";
|
||||
import { AutoUpdateSwitch } from "@/components/AutoUpdateSwitch";
|
||||
import { ReleaseChannelSelector } from "@/components/ReleaseChannelSelector";
|
||||
|
||||
export default function SettingsPage() {
|
||||
const [isResetDialogOpen, setIsResetDialogOpen] = useState(false);
|
||||
@@ -270,6 +271,10 @@ export function GeneralSettings({ appVersion }: { appVersion: string | null }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4">
|
||||
<ReleaseChannelSelector />
|
||||
</div>
|
||||
|
||||
<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="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