init claude-code
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { execFileNoThrow } from './execFileNoThrow.js'
|
||||
import { getBranch, getDefaultBranch, getIsGit } from './git.js'
|
||||
import { jsonParse } from './slowOperations.js'
|
||||
|
||||
export type PrReviewState =
|
||||
| 'approved'
|
||||
| 'pending'
|
||||
| 'changes_requested'
|
||||
| 'draft'
|
||||
| 'merged'
|
||||
| 'closed'
|
||||
|
||||
export type PrStatus = {
|
||||
number: number
|
||||
url: string
|
||||
reviewState: PrReviewState
|
||||
}
|
||||
|
||||
const GH_TIMEOUT_MS = 5000
|
||||
|
||||
/**
|
||||
* Derive review state from GitHub API values.
|
||||
* Draft PRs always show as 'draft' regardless of reviewDecision.
|
||||
* reviewDecision can be: APPROVED, CHANGES_REQUESTED, REVIEW_REQUIRED, or empty string.
|
||||
*/
|
||||
export function deriveReviewState(
|
||||
isDraft: boolean,
|
||||
reviewDecision: string,
|
||||
): PrReviewState {
|
||||
if (isDraft) return 'draft'
|
||||
switch (reviewDecision) {
|
||||
case 'APPROVED':
|
||||
return 'approved'
|
||||
case 'CHANGES_REQUESTED':
|
||||
return 'changes_requested'
|
||||
default:
|
||||
return 'pending'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch PR status for the current branch using `gh pr view`.
|
||||
* Returns null on any failure (gh not installed, no PR, not in git repo, etc).
|
||||
* Also returns null if the PR's head branch is the default branch (e.g., main/master).
|
||||
*/
|
||||
export async function fetchPrStatus(): Promise<PrStatus | null> {
|
||||
const isGit = await getIsGit()
|
||||
if (!isGit) return null
|
||||
|
||||
// Skip on the default branch — `gh pr view` returns the most recently
|
||||
// merged PR there, which is misleading.
|
||||
const [branch, defaultBranch] = await Promise.all([
|
||||
getBranch(),
|
||||
getDefaultBranch(),
|
||||
])
|
||||
if (branch === defaultBranch) return null
|
||||
|
||||
const { stdout, code } = await execFileNoThrow(
|
||||
'gh',
|
||||
[
|
||||
'pr',
|
||||
'view',
|
||||
'--json',
|
||||
'number,url,reviewDecision,isDraft,headRefName,state',
|
||||
],
|
||||
{ timeout: GH_TIMEOUT_MS, preserveOutputOnError: false },
|
||||
)
|
||||
|
||||
if (code !== 0 || !stdout.trim()) return null
|
||||
|
||||
try {
|
||||
const data = jsonParse(stdout) as {
|
||||
number: number
|
||||
url: string
|
||||
reviewDecision: string
|
||||
isDraft: boolean
|
||||
headRefName: string
|
||||
state: string
|
||||
}
|
||||
|
||||
// Don't show PR status for PRs from the default branch (e.g., main, master)
|
||||
// This can happen when someone opens a PR from main to another branch
|
||||
if (
|
||||
data.headRefName === defaultBranch ||
|
||||
data.headRefName === 'main' ||
|
||||
data.headRefName === 'master'
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Don't show PR status for merged or closed PRs — `gh pr view` returns
|
||||
// the most recently associated PR for a branch, which may be merged/closed.
|
||||
// The status line should only display open PRs.
|
||||
if (data.state === 'MERGED' || data.state === 'CLOSED') {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
number: data.number,
|
||||
url: data.url,
|
||||
reviewState: deriveReviewState(data.isDraft, data.reviewDecision),
|
||||
}
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user