feat(mirror): support GitHub PAT for private repo mirroring

Accept optional github_token in POST /api/mirror and inject it into
the git clone URL so private repos can be cloned without interactive auth.

Made-with: Cursor
This commit is contained in:
2026-03-09 18:05:09 -07:00
parent c00080bc67
commit ba4b94790c

View File

@@ -97,10 +97,11 @@ app.get('/health', (_req: Request, res: Response) => {
// ---------------------------------------------------------------------------
app.post('/api/mirror', async (req: Request, res: Response) => {
const { github_url, gitea_repo, project_name } = req.body as {
const { github_url, gitea_repo, project_name, github_token } = req.body as {
github_url?: string;
gitea_repo?: string; // e.g. "mark/opsos"
project_name?: string;
github_token?: string; // PAT for private repos
};
if (!github_url || !gitea_repo) {
@@ -132,8 +133,14 @@ app.post('/api/mirror', async (req: Request, res: Response) => {
console.log(`[mirror] Cloning ${github_url}${tmpDir}`);
fs.mkdirSync(tmpDir, { recursive: true });
// Build authenticated clone URL for private repos
let cloneUrl = github_url;
if (github_token) {
cloneUrl = github_url.replace('https://', `https://${github_token}@`);
}
// Mirror-clone the GitHub repo (preserves all branches + tags)
execSync(`git clone --mirror "${github_url}" "${tmpDir}/.git"`, {
execSync(`git clone --mirror "${cloneUrl}" "${tmpDir}/.git"`, {
stdio: 'pipe',
timeout: 120_000
});