(sessionData: SessionResource)
| 377 | * @returns Validation result with status and repo information |
| 378 | */ |
| 379 | export async function validateSessionRepository(sessionData: SessionResource): Promise<RepoValidationResult> { |
| 380 | const currentParsed = await detectCurrentRepositoryWithHost(); |
| 381 | const currentRepo = currentParsed ? `${currentParsed.owner}/${currentParsed.name}` : null; |
| 382 | |
| 383 | const gitSource = sessionData.session_context.sources.find( |
| 384 | (source): source is GitSource => source.type === 'git_repository', |
| 385 | ); |
| 386 | |
| 387 | if (!gitSource?.url) { |
| 388 | // Session has no repo requirement |
| 389 | logForDebugging( |
| 390 | currentRepo |
| 391 | ? 'Session has no associated repository, proceeding without validation' |
| 392 | : 'Session has no repo requirement and not in git directory, proceeding', |
| 393 | ); |
| 394 | return { status: 'no_repo_required' }; |
| 395 | } |
| 396 | |
| 397 | const sessionParsed = parseGitRemote(gitSource.url); |
| 398 | const sessionRepo = sessionParsed |
| 399 | ? `${sessionParsed.owner}/${sessionParsed.name}` |
| 400 | : parseGitHubRepository(gitSource.url); |
| 401 | if (!sessionRepo) { |
| 402 | return { status: 'no_repo_required' }; |
| 403 | } |
| 404 | |
| 405 | logForDebugging(`Session is for repository: ${sessionRepo}, current repo: ${currentRepo ?? 'none'}`); |
| 406 | |
| 407 | if (!currentRepo) { |
| 408 | // Not in a git repo, but session requires one |
| 409 | return { |
| 410 | status: 'not_in_repo', |
| 411 | sessionRepo, |
| 412 | sessionHost: sessionParsed?.host, |
| 413 | currentRepo: null, |
| 414 | }; |
| 415 | } |
| 416 | |
| 417 | // Compare both owner/repo and host to avoid cross-instance mismatches. |
| 418 | // Strip ports before comparing hosts — SSH remotes omit the port while |
| 419 | // HTTPS remotes may include a non-standard port (e.g. ghe.corp.com:8443), |
| 420 | // which would cause a false mismatch. |
| 421 | const stripPort = (host: string): string => host.replace(/:\d+$/, ''); |
| 422 | const repoMatch = currentRepo.toLowerCase() === sessionRepo.toLowerCase(); |
| 423 | const hostMatch = |
| 424 | !currentParsed || |
| 425 | !sessionParsed || |
| 426 | stripPort(currentParsed.host.toLowerCase()) === stripPort(sessionParsed.host.toLowerCase()); |
| 427 | |
| 428 | if (repoMatch && hostMatch) { |
| 429 | return { |
| 430 | status: 'match', |
| 431 | sessionRepo, |
| 432 | currentRepo, |
| 433 | }; |
| 434 | } |
| 435 | |
| 436 | // Repo mismatch — keep sessionRepo/currentRepo as plain "owner/repo" so |
no test coverage detected