forked from Vero-protocol/vero-guardian-dashboard
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgithubClient.ts
More file actions
128 lines (112 loc) · 3.25 KB
/
Copy pathgithubClient.ts
File metadata and controls
128 lines (112 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
type PRMetadata = {
hash: string;
title: string;
author: string;
url: string;
};
type JsonRecord = Record<string, unknown>;
type PullRequestNode = {
oid: string;
title: string;
url: string;
authorLogin?: string;
};
function asRecord(value: unknown): JsonRecord | undefined {
return typeof value === 'object' && value !== null && !Array.isArray(value)
? (value as JsonRecord)
: undefined;
}
function extractFirstPullRequest(value: unknown): PullRequestNode | undefined {
const root = asRecord(value);
const data = asRecord(root?.data);
const repository = asRecord(data?.repository);
const object = asRecord(repository?.object);
const associatedPullRequests = asRecord(object?.associatedPullRequests);
const edges = associatedPullRequests?.edges;
if (!Array.isArray(edges)) {
return undefined;
}
const firstEdge = asRecord(edges[0]);
const node = asRecord(firstEdge?.node);
if (
typeof node?.oid !== 'string' ||
typeof node.title !== 'string' ||
typeof node.url !== 'string'
) {
return undefined;
}
const author = asRecord(node.author);
const authorLogin = typeof author?.login === 'string' ? author.login : undefined;
return {
oid: node.oid,
title: node.title,
url: node.url,
authorLogin,
};
}
// GraphQL query to fetch PR details by commit SHA (prHash)
const PR_QUERY = `
query($owner: String!, $name: String!, $commitSha: String!) {
repository(owner: $owner, name: $name) {
object(expression: $commitSha) {
... on Commit {
associatedPullRequests(first: 1) {
edges {
node {
url
title
author {
login
}
oid
}
}
}
}
}
}
}
`;
/**
* Fetch PR metadata from GitHub GraphQL API using a commit hash.
* @param prHash - The commit SHA associated with the PR.
* @returns An object containing hash, title, author, and url.
*/
export async function fetchPRMetadata(prHash: string): Promise<PRMetadata> {
const token = process.env.GITHUB_TOKEN;
if (!token) {
throw new Error('GITHUB_TOKEN environment variable is not set');
}
// Repository details – adjust if the repo changes.
const owner = 'AugistineCreates';
const name = 'vero-guardian-dashboard';
const response = await fetch('https://api.github.com/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `bearer ${token}`,
},
body: JSON.stringify({
query: PR_QUERY,
variables: { owner, name, commitSha: prHash },
}),
});
if (!response.ok) {
// Handle rate limiting (HTTP 403 with "rate limit" in body)
const text = await response.text();
if (response.status === 403 && /rate limit/i.test(text)) {
throw new Error('GitHub API rate limit exceeded. Please try again later.');
}
throw new Error(`GitHub API request failed: ${response.status} ${response.statusText}`);
}
const pr = extractFirstPullRequest(await response.json());
if (!pr) {
throw new Error('No associated PR found for this commit hash');
}
return {
hash: pr.oid,
title: pr.title,
author: pr.authorLogin ?? 'unknown',
url: pr.url,
};
}