Files
openchamber/packages/web/server/lib/github-repo.js
T
Bohdan Triapitsyn 463e9ec4e3 Add GitHub integration for PRs, issues and AI PR description (#205)
* 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
2026-01-23 16:08:58 +02:00

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,
};
}