Commit with GitHub user email (needed for vercel deployment)
This commit is contained in:
@@ -171,6 +171,89 @@ export function GitHubConnector({ appId, folderName }: GitHubConnectorProps) {
|
||||
}
|
||||
};
|
||||
|
||||
if (!settings?.githubSettings.secrets?.accessToken) {
|
||||
return (
|
||||
<div className="mt-4 w-full">
|
||||
{" "}
|
||||
<Button
|
||||
onClick={handleConnectToGithub}
|
||||
className="cursor-pointer w-full py-6 flex justify-center items-center gap-2 text-lg"
|
||||
size="lg"
|
||||
variant="outline"
|
||||
disabled={isConnectingToGithub || !appId} // Also disable if appId is null
|
||||
>
|
||||
Connect to GitHub
|
||||
<Github className="h-5 w-5" />
|
||||
{isConnectingToGithub && (
|
||||
<svg
|
||||
className="animate-spin h-5 w-5 ml-2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle
|
||||
className="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="4"
|
||||
></circle>
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
></path>
|
||||
</svg>
|
||||
)}
|
||||
</Button>
|
||||
{/* GitHub Connection Status/Instructions */}
|
||||
{(githubUserCode || githubStatusMessage || githubError) && (
|
||||
<div className="mt-6 p-4 border rounded-md bg-gray-50 dark:bg-gray-700/50 border-gray-200 dark:border-gray-600">
|
||||
<h4 className="font-medium mb-2">GitHub Connection</h4>
|
||||
{githubError && (
|
||||
<p className="text-red-600 dark:text-red-400 mb-2">
|
||||
Error: {githubError}
|
||||
</p>
|
||||
)}
|
||||
{githubUserCode && githubVerificationUri && (
|
||||
<div className="mb-2">
|
||||
<p>
|
||||
1. Go to:
|
||||
<a
|
||||
href={githubVerificationUri} // Make it a direct link
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
IpcClient.getInstance().openExternalUrl(
|
||||
githubVerificationUri
|
||||
);
|
||||
}}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="ml-1 text-blue-600 hover:underline dark:text-blue-400"
|
||||
>
|
||||
{githubVerificationUri}
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
2. Enter code:
|
||||
<strong className="ml-1 font-mono text-lg tracking-wider bg-gray-200 dark:bg-gray-600 px-2 py-0.5 rounded">
|
||||
{githubUserCode}
|
||||
</strong>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{githubStatusMessage && (
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">
|
||||
{githubStatusMessage}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (app?.githubOrg && app?.githubRepo) {
|
||||
const handleSyncToGithub = async () => {
|
||||
setIsSyncing(true);
|
||||
@@ -244,9 +327,7 @@ export function GitHubConnector({ appId, folderName }: GitHubConnectorProps) {
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (settings?.githubSettings.secrets) {
|
||||
} else {
|
||||
return (
|
||||
<div className="mt-4 w-full border border-gray-200 rounded-md p-4">
|
||||
<p>Set up your GitHub repo</p>
|
||||
@@ -290,85 +371,4 @@ export function GitHubConnector({ appId, folderName }: GitHubConnectorProps) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-4 w-full">
|
||||
{" "}
|
||||
<Button
|
||||
onClick={handleConnectToGithub}
|
||||
className="cursor-pointer w-full py-6 flex justify-center items-center gap-2 text-lg"
|
||||
size="lg"
|
||||
variant="outline"
|
||||
disabled={isConnectingToGithub || !appId} // Also disable if appId is null
|
||||
>
|
||||
Connect to GitHub
|
||||
<Github className="h-5 w-5" />
|
||||
{isConnectingToGithub && (
|
||||
<svg
|
||||
className="animate-spin h-5 w-5 ml-2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle
|
||||
className="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="4"
|
||||
></circle>
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
></path>
|
||||
</svg>
|
||||
)}
|
||||
</Button>
|
||||
{/* GitHub Connection Status/Instructions */}
|
||||
{(githubUserCode || githubStatusMessage || githubError) && (
|
||||
<div className="mt-6 p-4 border rounded-md bg-gray-50 dark:bg-gray-700/50 border-gray-200 dark:border-gray-600">
|
||||
<h4 className="font-medium mb-2">GitHub Connection</h4>
|
||||
{githubError && (
|
||||
<p className="text-red-600 dark:text-red-400 mb-2">
|
||||
Error: {githubError}
|
||||
</p>
|
||||
)}
|
||||
{githubUserCode && githubVerificationUri && (
|
||||
<div className="mb-2">
|
||||
<p>
|
||||
1. Go to:
|
||||
<a
|
||||
href={githubVerificationUri} // Make it a direct link
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
IpcClient.getInstance().openExternalUrl(
|
||||
githubVerificationUri
|
||||
);
|
||||
}}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="ml-1 text-blue-600 hover:underline dark:text-blue-400"
|
||||
>
|
||||
{githubVerificationUri}
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
2. Enter code:
|
||||
<strong className="ml-1 font-mono text-lg tracking-wider bg-gray-200 dark:bg-gray-600 px-2 py-0.5 rounded">
|
||||
{githubUserCode}
|
||||
</strong>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{githubStatusMessage && (
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">
|
||||
{githubStatusMessage}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import { getEnvVar } from "../utils/read_env";
|
||||
import { readSettings } from "../../main/settings";
|
||||
import { Worker } from "worker_threads";
|
||||
import fixPath from "fix-path";
|
||||
import { getGitAuthor } from "../utils/git_author";
|
||||
|
||||
// Needed, otherwise electron in MacOS/Linux will not be able
|
||||
// to find "npm".
|
||||
@@ -346,10 +347,7 @@ export function registerAppHandlers() {
|
||||
fs: fs,
|
||||
dir: fullAppPath,
|
||||
message: "Init from react vite template",
|
||||
author: {
|
||||
name: "Dyad",
|
||||
email: "dyad@example.com",
|
||||
},
|
||||
author: await getGitAuthor(),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error in background app initialization:", error);
|
||||
@@ -708,10 +706,7 @@ export function registerAppHandlers() {
|
||||
fs,
|
||||
dir: appPath,
|
||||
message: `Reverted all changes back to version ${previousVersionId}`,
|
||||
author: {
|
||||
name: "Dyad",
|
||||
email: "hi@dyad.sh",
|
||||
},
|
||||
author: await getGitAuthor(),
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
@@ -845,10 +840,7 @@ export function registerAppHandlers() {
|
||||
fs,
|
||||
dir: appPath,
|
||||
message: `Updated ${filePath}`,
|
||||
author: {
|
||||
name: "Dyad",
|
||||
email: "hi@dyad.sh",
|
||||
},
|
||||
author: await getGitAuthor(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { getDyadAppPath } from "../../paths/paths";
|
||||
import { db } from "../../db";
|
||||
import { apps } from "../../db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { GithubUser } from "../../lib/schemas";
|
||||
|
||||
// --- GitHub Device Flow Constants ---
|
||||
// TODO: Fetch this securely, e.g., from environment variables or a config file
|
||||
@@ -38,6 +39,37 @@ let currentFlowState: DeviceFlowState | null = null;
|
||||
|
||||
// --- Helper Functions ---
|
||||
|
||||
/**
|
||||
* Fetches the GitHub username of the currently authenticated user (using the stored access token).
|
||||
* @returns {Promise<string|null>} The GitHub username, or null if not authenticated or on error.
|
||||
*/
|
||||
export async function getGithubUser(): Promise<GithubUser | null> {
|
||||
const settings = readSettings();
|
||||
const email = settings.githubUser?.email;
|
||||
if (email) return { email };
|
||||
try {
|
||||
const accessToken = settings.githubSettings?.secrets?.accessToken;
|
||||
if (!accessToken) return null;
|
||||
const res = await fetch("https://api.github.com/user/emails", {
|
||||
headers: { Authorization: `Bearer ${accessToken}` },
|
||||
});
|
||||
if (!res.ok) return null;
|
||||
const emails = await res.json();
|
||||
const email = emails.find((e: any) => e.primary)?.email;
|
||||
if (!email) return null;
|
||||
|
||||
writeSettings({
|
||||
githubUser: {
|
||||
email,
|
||||
},
|
||||
});
|
||||
return { email };
|
||||
} catch (err) {
|
||||
console.error("[GitHub Handler] Failed to get GitHub username:", err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// function event.sender.send(channel: string, data: any) {
|
||||
// if (currentFlowState?.window && !currentFlowState.window.isDestroyed()) {
|
||||
// currentFlowState.window.webContents.send(channel, data);
|
||||
|
||||
@@ -5,6 +5,8 @@ import fs from "node:fs";
|
||||
import { getDyadAppPath } from "../../paths/paths";
|
||||
import path from "node:path";
|
||||
import git from "isomorphic-git";
|
||||
import { getGithubUser } from "../handlers/github_handlers";
|
||||
import { getGitAuthor } from "../utils/git_author";
|
||||
|
||||
export function getDyadWriteTags(fullResponse: string): {
|
||||
path: string;
|
||||
@@ -210,10 +212,7 @@ export async function processFullResponseActions(
|
||||
message: chatSummary
|
||||
? `[dyad] ${chatSummary} - ${changes.join(", ")}`
|
||||
: `[dyad] ${changes.join(", ")}`,
|
||||
author: {
|
||||
name: "Dyad AI",
|
||||
email: "dyad-ai@example.com",
|
||||
},
|
||||
author: await getGitAuthor(),
|
||||
});
|
||||
console.log(`Successfully committed changes: ${changes.join(", ")}`);
|
||||
return { updatedFiles: true };
|
||||
|
||||
15
src/ipc/utils/git_author.ts
Normal file
15
src/ipc/utils/git_author.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { getGithubUser } from "../handlers/github_handlers";
|
||||
|
||||
export async function getGitAuthor() {
|
||||
const user = await getGithubUser();
|
||||
const author = user
|
||||
? {
|
||||
name: `[dyad]`,
|
||||
email: user.email,
|
||||
}
|
||||
: {
|
||||
name: "[dyad]",
|
||||
email: "git@dyad.sh",
|
||||
};
|
||||
return author;
|
||||
}
|
||||
@@ -74,6 +74,11 @@ export const GitHubSettingsSchema = z.object({
|
||||
});
|
||||
export type GitHubSettings = z.infer<typeof GitHubSettingsSchema>;
|
||||
|
||||
export const GithubUserSchema = z.object({
|
||||
email: z.string(),
|
||||
});
|
||||
export type GithubUser = z.infer<typeof GithubUserSchema>;
|
||||
|
||||
/**
|
||||
* Zod schema for user settings
|
||||
*/
|
||||
@@ -82,6 +87,7 @@ export const UserSettingsSchema = z.object({
|
||||
providerSettings: z.record(z.string(), ProviderSettingSchema),
|
||||
runtimeMode: RuntimeModeSchema,
|
||||
githubSettings: GitHubSettingsSchema,
|
||||
githubUser: GithubUserSchema.optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@ import path from "node:path";
|
||||
import { getUserDataPath } from "../paths/paths";
|
||||
import { UserSettingsSchema, type UserSettings } from "../lib/schemas";
|
||||
import { safeStorage } from "electron";
|
||||
|
||||
const DEFAULT_SETTINGS: UserSettings = {
|
||||
selectedModel: {
|
||||
name: "auto",
|
||||
|
||||
Reference in New Issue
Block a user