feat: link tasks to github references (#1471)
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import type { Repository } from "@/lib/types/http";
|
||||
|
||||
export type TaskPullRequestLinkTarget = {
|
||||
id: string;
|
||||
title: string;
|
||||
repositoryId?: string;
|
||||
repositories?: Array<{ repository_id: string }>;
|
||||
};
|
||||
|
||||
export type GitHubPRRepoRef = {
|
||||
owner: string;
|
||||
repo: string;
|
||||
repositoryId: string;
|
||||
};
|
||||
|
||||
export type ParsedPullRequestURL = {
|
||||
owner: string;
|
||||
repo: string;
|
||||
number: number;
|
||||
url: string;
|
||||
};
|
||||
|
||||
export function githubReposForTask(
|
||||
task: TaskPullRequestLinkTarget,
|
||||
repositories: Repository[],
|
||||
): GitHubPRRepoRef[] {
|
||||
const repoIds = new Set((task.repositories ?? []).map((repo) => repo.repository_id));
|
||||
if (task.repositoryId) repoIds.add(task.repositoryId);
|
||||
|
||||
return repositories
|
||||
.filter((repo) => repoIds.has(repo.id) && repo.provider === "github")
|
||||
.map((repo) => ({
|
||||
owner: repo.provider_owner,
|
||||
repo: repo.provider_name,
|
||||
repositoryId: repo.id,
|
||||
}))
|
||||
.filter((repo) => repo.owner && repo.repo);
|
||||
}
|
||||
|
||||
export function parseGitHubPullRequestURL(input: string): ParsedPullRequestURL | null {
|
||||
const match = input
|
||||
.trim()
|
||||
.match(/^(?:https?:\/\/)?github\.com\/([^/\s]+)\/([^/\s]+)\/pull\/(\d+)(?:[/?#].*)?$/i);
|
||||
if (!match) return null;
|
||||
const [, owner, repo, number] = match;
|
||||
const parsedNumber = Number(number);
|
||||
if (!Number.isSafeInteger(parsedNumber) || parsedNumber <= 0) return null;
|
||||
return {
|
||||
owner,
|
||||
repo,
|
||||
number: parsedNumber,
|
||||
url: `https://github.com/${owner}/${repo}/pull/${parsedNumber}`,
|
||||
};
|
||||
}
|
||||
|
||||
function positivePullRequestNumber(input: string): string | null {
|
||||
const number = input.replace(/^#/, "");
|
||||
if (!/^\d+$/.test(number)) return null;
|
||||
const parsedNumber = Number(number);
|
||||
if (!Number.isSafeInteger(parsedNumber) || parsedNumber <= 0) return null;
|
||||
return String(parsedNumber);
|
||||
}
|
||||
|
||||
export function pullRequestPayload(input: string, githubRepos: GitHubPRRepoRef[]) {
|
||||
const trimmed = input.trim();
|
||||
const inferredNumber = positivePullRequestNumber(trimmed);
|
||||
const inferredRepo = inferredNumber && githubRepos.length === 1 ? githubRepos[0] : null;
|
||||
if (inferredRepo && inferredNumber) {
|
||||
return {
|
||||
pr_url: `https://github.com/${inferredRepo.owner}/${inferredRepo.repo}/pull/${inferredNumber}`,
|
||||
repository_id: inferredRepo.repositoryId,
|
||||
};
|
||||
}
|
||||
|
||||
const parsed = parseGitHubPullRequestURL(trimmed);
|
||||
const matchingRepo = parsed
|
||||
? githubRepos.find(
|
||||
(repo) =>
|
||||
repo.owner.toLowerCase() === parsed.owner.toLowerCase() &&
|
||||
repo.repo.toLowerCase() === parsed.repo.toLowerCase(),
|
||||
)
|
||||
: null;
|
||||
|
||||
return {
|
||||
pr_url: parsed?.url ?? trimmed,
|
||||
repository_id: matchingRepo?.repositoryId,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user