refactor(FN-1288): consolidate GitHub remote parsing in @fusion/core

- Replace dashboard calls to local getCurrentGitHubRepo helpers with getCurrentRepo from @fusion/core
- Update engine scheduler PR-monitor startup paths to use shared core repo resolution
- Remove duplicated remote parsing implementations from dashboard and engine packages
- Mark gap analysis finding 6.3 as resolved after centralizing parsing logic
This commit is contained in:
gsxdsm
2026-04-08 15:53:38 -07:00
parent 0304a3df20
commit 8aa77c8b77
6 changed files with 16 additions and 92 deletions

View File

@@ -2344,41 +2344,3 @@ export function parseGitHubBadgeUrl(url: string): { owner: string; repo: string
return { owner: parsed.owner, repo: parsed.repo };
}
/**
* Extract owner/repo from a GitHub remote URL or return null if not a GitHub remote.
* @deprecated Use parseRepoFromRemote from gh-cli.ts instead
*/
export function parseGitHubRemote(remoteUrl: string): { owner: string; repo: string } | null {
// Handle HTTPS: https://github.com/owner/repo.git or https://github.com/owner/repo
const httpsMatch = remoteUrl.match(/github\.com\/([^\/]+)\/([^\/\.]+)(?:\.git)?$/);
if (httpsMatch) {
return { owner: httpsMatch[1], repo: httpsMatch[2] };
}
// Handle SSH: git@github.com:owner/repo.git or git@github.com:owner/repo
const sshMatch = remoteUrl.match(/github\.com:([^\/]+)\/([^\/\.]+)(?:\.git)?$/);
if (sshMatch) {
return { owner: sshMatch[1], repo: sshMatch[2] };
}
return null;
}
/**
* Get the current GitHub remote owner/repo from the git config.
* @deprecated Use getCurrentRepo from gh-cli.ts instead
*/
export function getCurrentGitHubRepo(cwd: string): { owner: string; repo: string } | null {
const { execFileSync } = require("node:child_process");
try {
const remoteUrl = execFileSync("git", ["remote", "get-url", "origin"], {
cwd,
encoding: "utf-8",
stdio: ["pipe", "pipe", "ignore"],
}).trim();
return parseGitHubRemote(remoteUrl);
} catch {
return null;
}
}

View File

@@ -8,9 +8,9 @@ import { tmpdir } from "node:os";
import * as nodeFs from "node:fs";
import * as nodeChildProcess from "node:child_process";
import type { TaskStore, Column, MergeResult, ScheduleType, ActivityEventType, ModelPreset, AutomationStep, MessageType, ParticipantType, MessageCreateInput } from "@fusion/core";
import { COLUMNS, VALID_TRANSITIONS, GLOBAL_SETTINGS_KEYS, type BatchStatusEntry, type BatchStatusResponse, type BatchStatusResult, type IssueInfo, type PrInfo, type Task, isGhAuthenticated, AUTOMATION_PRESETS, AutomationStore, validateBackupSchedule, validateBackupRetention, validateBackupDir, syncBackupAutomation, exportSettings, importSettings, validateImportData, MessageStore, MEMORY_FILE_PATH } from "@fusion/core";
import { COLUMNS, VALID_TRANSITIONS, GLOBAL_SETTINGS_KEYS, type BatchStatusEntry, type BatchStatusResponse, type BatchStatusResult, type IssueInfo, type PrInfo, type Task, getCurrentRepo, isGhAuthenticated, AUTOMATION_PRESETS, AutomationStore, validateBackupSchedule, validateBackupRetention, validateBackupDir, syncBackupAutomation, exportSettings, importSettings, validateImportData, MessageStore, MEMORY_FILE_PATH } from "@fusion/core";
import type { ServerOptions } from "./server.js";
import { GitHubClient, getCurrentGitHubRepo, parseBadgeUrl } from "./github.js";
import { GitHubClient, parseBadgeUrl } from "./github.js";
import { githubRateLimiter } from "./github-poll.js";
import { terminalSessionManager } from "./terminal.js";
import { getTerminalService } from "./terminal-service.js";
@@ -4233,7 +4233,7 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
owner = o;
repo = r;
} else {
const gitRepo = getCurrentGitHubRepo(scopedStore.getRootDir());
const gitRepo = getCurrentRepo(scopedStore.getRootDir());
if (!gitRepo) {
throw badRequest("Could not determine GitHub repository. Set GITHUB_REPOSITORY env var or configure git remote.");
}
@@ -4520,7 +4520,7 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
owner = o;
repo = r;
} else {
const gitRepo = getCurrentGitHubRepo(scopedStore.getRootDir());
const gitRepo = getCurrentRepo(scopedStore.getRootDir());
if (!gitRepo) {
throw badRequest("Could not determine GitHub repository");
}
@@ -4644,7 +4644,7 @@ export function createApiRoutes(store: TaskStore, options?: ServerOptions): Rout
owner = o;
repo = r;
} else {
const gitRepo = getCurrentGitHubRepo(scopedStore.getRootDir());
const gitRepo = getCurrentRepo(scopedStore.getRootDir());
if (!gitRepo) {
throw badRequest("Could not determine GitHub repository");
}
@@ -10980,7 +10980,7 @@ function getDefaultGitHubRepo(store: TaskStore): { owner: string; repo: string }
}
const rootDir = typeof store.getRootDir === "function" ? store.getRootDir() : process.cwd();
return getCurrentGitHubRepo(rootDir);
return getCurrentRepo(rootDir);
}
function isBatchStatusStale(info: { lastCheckedAt?: string } | undefined, updatedAt?: string): boolean {
@@ -11022,7 +11022,7 @@ async function refreshPrInBackground(store: TaskStore, taskId: string, currentPr
owner = o;
repo = r;
} else {
const gitRepo = getCurrentGitHubRepo(store.getRootDir());
const gitRepo = getCurrentRepo(store.getRootDir());
if (!gitRepo) return; // Silent fail - can't determine repo
owner = gitRepo.owner;
repo = gitRepo.repo;
@@ -11066,7 +11066,7 @@ async function refreshIssueInBackground(
owner = o;
repo = r;
} else {
const gitRepo = getCurrentGitHubRepo(store.getRootDir());
const gitRepo = getCurrentRepo(store.getRootDir());
if (!gitRepo) return;
owner = gitRepo.owner;
repo = gitRepo.repo;

View File

@@ -13,7 +13,7 @@ import { getOrCreateProjectStore, evictAllProjectStores } from "./project-store-
import { getTerminalService, type TerminalSession, STALE_SESSION_THRESHOLD_MS } from "./terminal-service.js";
import { WebSocketServer, type WebSocket } from "ws";
import { terminalSessionManager } from "./terminal.js";
import { getCurrentGitHubRepo, parseBadgeUrl } from "./github.js";
import { parseBadgeUrl } from "./github.js";
import { WebSocketManager, type BadgeSnapshot } from "./websocket.js";
import type { BadgePubSub } from "./badge-pubsub.js";
import { createBadgePubSub, type BadgePubSubMessage } from "./badge-pubsub.js";