Add plannotator extension v0.19.10
This commit is contained in:
432
extensions/plannotator/generated/pr-provider.ts
Normal file
432
extensions/plannotator/generated/pr-provider.ts
Normal file
@@ -0,0 +1,432 @@
|
||||
// @generated — DO NOT EDIT. Source: packages/shared/pr-provider.ts
|
||||
/**
|
||||
* Runtime-agnostic PR provider shared by Bun runtimes and Pi.
|
||||
*
|
||||
* Dispatches to platform-specific implementations (GitHub, GitLab)
|
||||
* based on the `platform` field in PRRef/PRMetadata.
|
||||
*
|
||||
* Same pattern as review-core.ts: a runtime interface abstracts subprocess
|
||||
* execution so the logic is reusable across Bun and Node/jiti.
|
||||
*/
|
||||
|
||||
import { checkGhAuth, getGhUser, fetchGhPR, fetchGhPRContext, fetchGhPRFileContent, submitGhPRReview, fetchGhPRViewedFiles, markGhFilesViewed, fetchGhPRStack, fetchGhPRList } from "./pr-github";
|
||||
import { checkGlAuth, getGlUser, fetchGlMR, fetchGlMRContext, fetchGlFileContent, submitGlMRReview } from "./pr-gitlab";
|
||||
|
||||
// --- Runtime Types ---
|
||||
|
||||
export interface CommandResult {
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
exitCode: number;
|
||||
}
|
||||
|
||||
export interface PRRuntime {
|
||||
runCommand: (
|
||||
cmd: string,
|
||||
args: string[],
|
||||
) => Promise<CommandResult>;
|
||||
runCommandWithInput?: (
|
||||
cmd: string,
|
||||
args: string[],
|
||||
input: string,
|
||||
) => Promise<CommandResult>;
|
||||
}
|
||||
|
||||
// --- Platform Types ---
|
||||
|
||||
export type Platform = "github" | "gitlab";
|
||||
|
||||
/** GitHub PR reference */
|
||||
export interface GithubPRRef {
|
||||
platform: "github";
|
||||
host: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
number: number;
|
||||
}
|
||||
|
||||
/** GitLab MR reference */
|
||||
export interface GitlabMRRef {
|
||||
platform: "gitlab";
|
||||
host: string;
|
||||
projectPath: string;
|
||||
iid: number;
|
||||
}
|
||||
|
||||
/** Discriminated union — auto-detected from URL */
|
||||
export type PRRef = GithubPRRef | GitlabMRRef;
|
||||
|
||||
/** GitHub PR metadata */
|
||||
export interface GithubPRMetadata {
|
||||
platform: "github";
|
||||
host: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
number: number;
|
||||
/** GraphQL node ID for the PR — used for markFileAsViewed mutations */
|
||||
prNodeId?: string;
|
||||
title: string;
|
||||
author: string;
|
||||
baseBranch: string;
|
||||
headBranch: string;
|
||||
/** Repository default branch, used to infer whether this PR targets another PR branch. */
|
||||
defaultBranch?: string;
|
||||
baseSha: string;
|
||||
headSha: string;
|
||||
/** Merge-base SHA — the common ancestor commit used to compute the PR diff. Differs from baseSha when the base branch has moved. */
|
||||
mergeBaseSha?: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
/** GitLab MR metadata */
|
||||
export interface GitlabMRMetadata {
|
||||
platform: "gitlab";
|
||||
host: string;
|
||||
projectPath: string;
|
||||
iid: number;
|
||||
title: string;
|
||||
author: string;
|
||||
baseBranch: string;
|
||||
headBranch: string;
|
||||
/** Project default branch, used to infer whether this MR targets another MR branch. */
|
||||
defaultBranch?: string;
|
||||
baseSha: string;
|
||||
headSha: string;
|
||||
/** Merge-base SHA — the common ancestor commit used to compute the MR diff. */
|
||||
mergeBaseSha?: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
/** Discriminated union — downstream gets type narrowing for free */
|
||||
export type PRMetadata = GithubPRMetadata | GitlabMRMetadata;
|
||||
|
||||
// --- PR Context Types (platform-agnostic) ---
|
||||
|
||||
export interface PRComment {
|
||||
id: string;
|
||||
author: string;
|
||||
body: string;
|
||||
createdAt: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface PRReview {
|
||||
id: string;
|
||||
author: string;
|
||||
state: string;
|
||||
body: string;
|
||||
submittedAt: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface PRCheck {
|
||||
name: string;
|
||||
status: string;
|
||||
conclusion: string | null;
|
||||
workflowName: string;
|
||||
detailsUrl: string;
|
||||
}
|
||||
|
||||
export interface PRLinkedIssue {
|
||||
number: number;
|
||||
url: string;
|
||||
repo: string;
|
||||
}
|
||||
|
||||
export interface PRThreadComment {
|
||||
id: string;
|
||||
author: string;
|
||||
body: string;
|
||||
createdAt: string;
|
||||
url: string;
|
||||
diffHunk?: string;
|
||||
}
|
||||
|
||||
export interface PRReviewThread {
|
||||
id: string;
|
||||
isResolved: boolean;
|
||||
isOutdated: boolean;
|
||||
path: string;
|
||||
line: number | null;
|
||||
startLine: number | null;
|
||||
diffSide: 'LEFT' | 'RIGHT' | null;
|
||||
comments: PRThreadComment[];
|
||||
}
|
||||
|
||||
export interface PRContext {
|
||||
body: string;
|
||||
state: string;
|
||||
isDraft: boolean;
|
||||
labels: Array<{ name: string; color: string }>;
|
||||
reviewDecision: string;
|
||||
mergeable: string;
|
||||
mergeStateStatus: string;
|
||||
comments: PRComment[];
|
||||
reviews: PRReview[];
|
||||
reviewThreads: PRReviewThread[];
|
||||
checks: PRCheck[];
|
||||
linkedIssues: PRLinkedIssue[];
|
||||
}
|
||||
|
||||
export interface PRReviewFileComment {
|
||||
path: string;
|
||||
line: number;
|
||||
side: "LEFT" | "RIGHT";
|
||||
body: string;
|
||||
start_line?: number;
|
||||
start_side?: "LEFT" | "RIGHT";
|
||||
}
|
||||
|
||||
export type PRDiffScope = "layer" | "full-stack";
|
||||
|
||||
export interface PRDiffScopeOption {
|
||||
id: PRDiffScope;
|
||||
label: string;
|
||||
description: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface PRStackInfo {
|
||||
isStacked: boolean;
|
||||
baseBranch: string;
|
||||
defaultBranch?: string;
|
||||
label: string;
|
||||
source: "branch-inferred" | "tree-discovered" | "github-native" | "gitlab-native" | "graphite" | "ghstack";
|
||||
}
|
||||
|
||||
export interface PRStackNode {
|
||||
branch: string;
|
||||
number?: number;
|
||||
title?: string;
|
||||
url?: string;
|
||||
isCurrent: boolean;
|
||||
isDefaultBranch: boolean;
|
||||
state?: 'open' | 'merged' | 'closed';
|
||||
}
|
||||
|
||||
export interface PRStackTree {
|
||||
nodes: PRStackNode[];
|
||||
}
|
||||
|
||||
export interface PRListItem {
|
||||
id: string;
|
||||
number: number;
|
||||
title: string;
|
||||
author: string;
|
||||
url: string;
|
||||
baseBranch: string;
|
||||
state: 'open' | 'closed' | 'merged';
|
||||
}
|
||||
|
||||
// --- Label Helpers ---
|
||||
// Accept either PRRef or PRMetadata (both have `platform` discriminant)
|
||||
|
||||
type HasPlatform = PRRef | PRMetadata;
|
||||
|
||||
/** "GitHub" or "GitLab" */
|
||||
export function getPlatformLabel(m: HasPlatform): string {
|
||||
return m.platform === "github" ? "GitHub" : "GitLab";
|
||||
}
|
||||
|
||||
/** "PR" or "MR" */
|
||||
export function getMRLabel(m: HasPlatform): string {
|
||||
return m.platform === "github" ? "PR" : "MR";
|
||||
}
|
||||
|
||||
/** "#123" or "!42" */
|
||||
export function getMRNumberLabel(m: HasPlatform): string {
|
||||
if (m.platform === "github") return `#${m.number}`;
|
||||
return `!${m.iid}`;
|
||||
}
|
||||
|
||||
/** "owner/repo" or "group/project" */
|
||||
export function getDisplayRepo(m: HasPlatform): string {
|
||||
if (m.platform === "github") return `${m.owner}/${m.repo}`;
|
||||
return m.projectPath;
|
||||
}
|
||||
|
||||
/** Reconstruct a PRRef from metadata */
|
||||
export function prRefFromMetadata(m: PRMetadata): PRRef {
|
||||
if (m.platform === "github") {
|
||||
return { platform: "github", host: m.host, owner: m.owner, repo: m.repo, number: m.number };
|
||||
}
|
||||
return { platform: "gitlab", host: m.host, projectPath: m.projectPath, iid: m.iid };
|
||||
}
|
||||
|
||||
export function isSameProject(a: PRRef, b: PRRef): boolean {
|
||||
if (a.platform !== b.platform) return false;
|
||||
if (a.platform === "github" && b.platform === "github") {
|
||||
return a.host === b.host && a.owner === b.owner && a.repo === b.repo;
|
||||
}
|
||||
if (a.platform === "gitlab" && b.platform === "gitlab") {
|
||||
return a.host === b.host && a.projectPath === b.projectPath;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** CLI tool name for the platform */
|
||||
export function getCliName(ref: PRRef): string {
|
||||
return ref.platform === "github" ? "gh" : "glab";
|
||||
}
|
||||
|
||||
/** Install URL for the platform CLI */
|
||||
export function getCliInstallUrl(ref: PRRef): string {
|
||||
return ref.platform === "github"
|
||||
? "https://cli.github.com"
|
||||
: "https://gitlab.com/gitlab-org/cli";
|
||||
}
|
||||
|
||||
/** Encode a file path for use in platform API URLs */
|
||||
export function encodeApiFilePath(filePath: string): string {
|
||||
return encodeURIComponent(filePath);
|
||||
}
|
||||
|
||||
// --- URL Parsing ---
|
||||
|
||||
/**
|
||||
* Parse a PR/MR URL into its components. Auto-detects platform.
|
||||
*
|
||||
* Handles:
|
||||
* - GitHub: https://github.com/owner/repo/pull/123[/files|/commits]
|
||||
* - GitHub Enterprise: https://ghe.company.com/owner/repo/pull/123
|
||||
* - GitLab: https://gitlab.com/group/subgroup/project/-/merge_requests/42[/diffs]
|
||||
* - Self-hosted GitLab: https://gitlab.mycompany.com/group/project/-/merge_requests/42
|
||||
*
|
||||
* GitLab is checked first because `/-/merge_requests/` is unambiguous,
|
||||
* while `/pull/` could theoretically appear on any host.
|
||||
*/
|
||||
export function parsePRUrl(url: string): PRRef | null {
|
||||
if (!url) return null;
|
||||
|
||||
// GitLab: https://{host}/{projectPath}/-/merge_requests/{iid}[/...]
|
||||
// Checked first — `/-/merge_requests/` is the most specific pattern.
|
||||
const glMatch = url.match(
|
||||
/^https?:\/\/([^/]+)\/(.+?)\/-\/merge_requests\/(\d+)/,
|
||||
);
|
||||
if (glMatch) {
|
||||
return {
|
||||
platform: "gitlab",
|
||||
host: glMatch[1],
|
||||
projectPath: glMatch[2],
|
||||
iid: parseInt(glMatch[3], 10),
|
||||
};
|
||||
}
|
||||
|
||||
// GitHub (including GHE): https://{host}/{owner}/{repo}/pull/{number}[/...]
|
||||
const ghMatch = url.match(
|
||||
/^https?:\/\/([^/]+)\/([^/]+)\/([^/]+)\/pull\/(\d+)/,
|
||||
);
|
||||
if (ghMatch) {
|
||||
return {
|
||||
platform: "github",
|
||||
host: ghMatch[1],
|
||||
owner: ghMatch[2],
|
||||
repo: ghMatch[3],
|
||||
number: parseInt(ghMatch[4], 10),
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// --- Dispatch Functions ---
|
||||
|
||||
export async function checkAuth(runtime: PRRuntime, ref: PRRef): Promise<void> {
|
||||
if (ref.platform === "github") return checkGhAuth(runtime, ref.host);
|
||||
return checkGlAuth(runtime, ref.host);
|
||||
}
|
||||
|
||||
export async function getUser(runtime: PRRuntime, ref: PRRef): Promise<string | null> {
|
||||
if (ref.platform === "github") return getGhUser(runtime, ref.host);
|
||||
return getGlUser(runtime, ref.host);
|
||||
}
|
||||
|
||||
export async function fetchPR(
|
||||
runtime: PRRuntime,
|
||||
ref: PRRef,
|
||||
): Promise<{ metadata: PRMetadata; rawPatch: string }> {
|
||||
if (ref.platform === "github") return fetchGhPR(runtime, ref);
|
||||
return fetchGlMR(runtime, ref);
|
||||
}
|
||||
|
||||
export async function fetchPRContext(
|
||||
runtime: PRRuntime,
|
||||
ref: PRRef,
|
||||
): Promise<PRContext> {
|
||||
if (ref.platform === "github") return fetchGhPRContext(runtime, ref);
|
||||
return fetchGlMRContext(runtime, ref);
|
||||
}
|
||||
|
||||
export async function fetchPRFileContent(
|
||||
runtime: PRRuntime,
|
||||
ref: PRRef,
|
||||
sha: string,
|
||||
filePath: string,
|
||||
): Promise<string | null> {
|
||||
if (ref.platform === "github") return fetchGhPRFileContent(runtime, ref, sha, filePath);
|
||||
return fetchGlFileContent(runtime, ref, sha, filePath);
|
||||
}
|
||||
|
||||
export async function submitPRReview(
|
||||
runtime: PRRuntime,
|
||||
ref: PRRef,
|
||||
headSha: string,
|
||||
action: "approve" | "comment",
|
||||
body: string,
|
||||
fileComments: PRReviewFileComment[],
|
||||
): Promise<void> {
|
||||
if (ref.platform === "github") return submitGhPRReview(runtime, ref, headSha, action, body, fileComments);
|
||||
return submitGlMRReview(runtime, ref, headSha, action, body, fileComments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch per-file "viewed" state for a PR.
|
||||
* GitHub: returns { filePath: isViewed } map.
|
||||
* GitLab: always returns {} (no server-side viewed state API).
|
||||
*/
|
||||
export async function fetchPRViewedFiles(
|
||||
runtime: PRRuntime,
|
||||
ref: PRRef,
|
||||
): Promise<Record<string, boolean>> {
|
||||
if (ref.platform === "github") return fetchGhPRViewedFiles(runtime, ref);
|
||||
return {}; // GitLab has no server-side viewed state
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark or unmark files as viewed in a PR.
|
||||
* GitHub: fires markFileAsViewed / unmarkFileAsViewed GraphQL mutations.
|
||||
* GitLab: no-op (no server-side viewed state API).
|
||||
*/
|
||||
export async function markPRFilesViewed(
|
||||
runtime: PRRuntime,
|
||||
ref: PRRef,
|
||||
prNodeId: string,
|
||||
filePaths: string[],
|
||||
viewed: boolean,
|
||||
): Promise<void> {
|
||||
if (ref.platform === "github") return markGhFilesViewed(runtime, ref, prNodeId, filePaths, viewed);
|
||||
// GitLab: no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the full stack tree for a stacked PR.
|
||||
* Walks up from the current PR to the default branch, resolving
|
||||
* PR numbers and titles for each intermediate branch.
|
||||
* Returns null if the PR is not stacked or the API call fails.
|
||||
*/
|
||||
export async function fetchPRStack(
|
||||
runtime: PRRuntime,
|
||||
ref: PRRef,
|
||||
metadata: PRMetadata,
|
||||
): Promise<PRStackTree | null> {
|
||||
if (ref.platform === "github") return fetchGhPRStack(runtime, ref, metadata);
|
||||
return null; // GitLab: not yet implemented
|
||||
}
|
||||
|
||||
export async function fetchPRList(
|
||||
runtime: PRRuntime,
|
||||
ref: PRRef,
|
||||
): Promise<PRListItem[]> {
|
||||
if (ref.platform === "github") return fetchGhPRList(runtime, ref);
|
||||
return []; // GitLab: not yet implemented
|
||||
}
|
||||
Reference in New Issue
Block a user