* feat: integrate GitHub OAuth device flow across runtimes Add GitHub OAuth device flow endpoints across runtimes Introduce GitHubSettings UI panel and sidebar entry Persist GitHub auth state in per-runtime storage * feat: add GitHub PR status and PR description generation Show PR status for the current branch in the Git view Generate a pull request description from the diff between base and head Expose prStatus, prCreate, and prMerge APIs in web and desktop clients * feat: add GitHub PR ready for review Add API to mark pull requests as ready for review Show a Ready button for draft PRs and reflect status in UI Handle token expiration and GraphQL errors when marking ready
56 lines
1.7 KiB
JavaScript
56 lines
1.7 KiB
JavaScript
import { getRemoteUrl } from './git-service.js';
|
|
|
|
export const parseGitHubRemoteUrl = (raw) => {
|
|
if (typeof raw !== 'string') {
|
|
return null;
|
|
}
|
|
const value = raw.trim();
|
|
if (!value) {
|
|
return null;
|
|
}
|
|
|
|
// git@github.com:OWNER/REPO.git
|
|
if (value.startsWith('git@github.com:')) {
|
|
const rest = value.slice('git@github.com:'.length);
|
|
const cleaned = rest.endsWith('.git') ? rest.slice(0, -4) : rest;
|
|
const [owner, repo] = cleaned.split('/');
|
|
if (!owner || !repo) return null;
|
|
return { owner, repo, url: `https://github.com/${owner}/${repo}` };
|
|
}
|
|
|
|
// ssh://git@github.com/OWNER/REPO.git
|
|
if (value.startsWith('ssh://git@github.com/')) {
|
|
const rest = value.slice('ssh://git@github.com/'.length);
|
|
const cleaned = rest.endsWith('.git') ? rest.slice(0, -4) : rest;
|
|
const [owner, repo] = cleaned.split('/');
|
|
if (!owner || !repo) return null;
|
|
return { owner, repo, url: `https://github.com/${owner}/${repo}` };
|
|
}
|
|
|
|
// https://github.com/OWNER/REPO(.git)
|
|
try {
|
|
const url = new URL(value);
|
|
if (url.hostname !== 'github.com') {
|
|
return null;
|
|
}
|
|
const path = url.pathname.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
const cleaned = path.endsWith('.git') ? path.slice(0, -4) : path;
|
|
const [owner, repo] = cleaned.split('/');
|
|
if (!owner || !repo) return null;
|
|
return { owner, repo, url: `https://github.com/${owner}/${repo}` };
|
|
} catch {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
export async function resolveGitHubRepoFromDirectory(directory) {
|
|
const remoteUrl = await getRemoteUrl(directory).catch(() => null);
|
|
if (!remoteUrl) {
|
|
return { repo: null, remoteUrl: null };
|
|
}
|
|
return {
|
|
repo: parseGitHubRemoteUrl(remoteUrl),
|
|
remoteUrl,
|
|
};
|
|
}
|