* Detect PR for workspace's current branch via `gh pr view`.
(workspaceId: string)
| 313 | * Detect PR for workspace's current branch via `gh pr view`. |
| 314 | */ |
| 315 | private async detectWorkspacePR(workspaceId: string): Promise<void> { |
| 316 | if (!this.client || !this.isActive) return; |
| 317 | |
| 318 | // Mark as loading |
| 319 | const existing = this.workspacePRCache.get(workspaceId); |
| 320 | this.workspacePRCache.set(workspaceId, { |
| 321 | prLink: existing?.prLink ?? null, |
| 322 | status: existing?.status, |
| 323 | loading: true, |
| 324 | fetchedAt: Date.now(), |
| 325 | }); |
| 326 | this.workspacePRSubscriptions.bump(workspaceId); |
| 327 | |
| 328 | try { |
| 329 | // Run gh pr view without URL - detects PR for current branch |
| 330 | const result = await this.client.workspace.executeBash({ |
| 331 | workspaceId, |
| 332 | script: `gh pr view --json number,url,state,mergeable,mergeStateStatus,title,isDraft,headRefName,baseRefName,statusCheckRollup 2>/dev/null || echo '{"no_pr":true}'`, |
| 333 | // gh requires the runtime environment for devcontainer workspaces where |
| 334 | // the CLI / auth may only exist inside the container. |
| 335 | options: repoRootBashOptions(15), |
| 336 | }); |
| 337 | |
| 338 | if (!this.isActive) return; |
| 339 | |
| 340 | if (!result.success || !result.data.success) { |
| 341 | const existing = this.workspacePRCache.get(workspaceId); |
| 342 | this.workspacePRCache.set(workspaceId, { |
| 343 | prLink: existing?.prLink ?? null, |
| 344 | status: existing?.status, |
| 345 | error: "Failed to run gh CLI", |
| 346 | loading: false, |
| 347 | fetchedAt: Date.now(), |
| 348 | }); |
| 349 | this.workspacePRSubscriptions.bump(workspaceId); |
| 350 | return; |
| 351 | } |
| 352 | |
| 353 | const output = result.data.output; |
| 354 | if (output) { |
| 355 | const parsed = JSON.parse(output) as Record<string, unknown>; |
| 356 | |
| 357 | if ("no_pr" in parsed) { |
| 358 | // No PR for this branch |
| 359 | this.workspacePRCache.set(workspaceId, { |
| 360 | prLink: null, |
| 361 | loading: false, |
| 362 | fetchedAt: Date.now(), |
| 363 | }); |
| 364 | } else { |
| 365 | // Parse PR link from URL |
| 366 | const prUrl = parsed.url as string; |
| 367 | const prLinkBase = parseGitHubPRUrl(prUrl); |
| 368 | |
| 369 | if (!prLinkBase) { |
| 370 | this.workspacePRCache.set(workspaceId, { |
| 371 | prLink: null, |
| 372 | error: "Invalid PR URL from gh CLI", |
no test coverage detected