Skip to content

Commit 02e0e62

Browse files
committed
Fetch release branch badge data from GitHub
1 parent 254ed35 commit 02e0e62

1 file changed

Lines changed: 43 additions & 79 deletions

File tree

packages/app/server/api/repo/commits.get.ts

Lines changed: 43 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -23,58 +23,70 @@ interface ReleaseRow {
2323
packages: Set<string>;
2424
}
2525

26-
interface RepoBranchInfo {
27-
defaultBranch: string;
28-
pinnedSha: string | null;
29-
branchBySha: Map<string, string>;
26+
interface CommitMeta {
27+
message: string | null;
28+
branch: string | null;
3029
}
3130

32-
async function getCommitMessages(
31+
async function getCommitMetadata(
3332
installation: Awaited<ReturnType<typeof useOctokitInstallation>>,
3433
owner: string,
3534
repo: string,
3635
shas: string[],
3736
) {
38-
async function fetchCommitTitle(sha: string) {
37+
async function fetchCommitMeta(sha: string): Promise<CommitMeta> {
38+
let message: string | null = null;
39+
let branch: string | null = null;
40+
3941
try {
4042
const { data } = await installation.rest.repos.getCommit({
4143
owner,
4244
repo,
4345
ref: sha,
4446
});
45-
const message = data.commit?.message?.split("\n")[0]?.trim();
46-
if (message) {
47-
return message;
47+
const title = data.commit?.message?.split("\n")[0]?.trim();
48+
if (title) {
49+
message = title;
50+
}
51+
} catch {}
52+
53+
try {
54+
const { data } = await installation.request(
55+
"GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head",
56+
{
57+
owner,
58+
repo,
59+
commit_sha: sha,
60+
},
61+
);
62+
const branchName = (data as Array<{ name?: string }>)[0]?.name?.trim();
63+
if (branchName) {
64+
branch = branchName;
4865
}
49-
} catch {
50-
return null;
51-
}
66+
} catch {}
5267

53-
return null;
68+
return {
69+
message,
70+
branch,
71+
};
5472
}
5573

5674
const entries = await Promise.all(
5775
shas.map(async (sha) => {
58-
const message = await fetchCommitTitle(sha);
59-
return message ? ([sha, message] as const) : null;
76+
const meta = await fetchCommitMeta(sha);
77+
return [sha, meta] as const;
6078
}),
6179
);
6280

63-
return new Map(
64-
entries.filter((entry): entry is readonly [string, string] => !!entry),
65-
);
66-
}
67-
68-
function isPullRequestRef(ref: string) {
69-
return /^\d+$/.test(ref);
81+
return new Map(entries);
7082
}
7183

72-
async function getRepoBranchInfo(
84+
async function getDefaultBranchPinnedSha(
7385
event: H3Event,
7486
installation: Awaited<ReturnType<typeof useOctokitInstallation>>,
7587
owner: string,
7688
repo: string,
77-
) : Promise<RepoBranchInfo> {
89+
) {
7890
const {
7991
data: { default_branch: defaultBranch },
8092
} = await installation.rest.repos.get({
@@ -85,59 +97,10 @@ async function getRepoBranchInfo(
8597
const cursorBucket = useCursorsBucket(
8698
event as Parameters<typeof useCursorsBucket>[0],
8799
);
88-
const defaultCursor = await cursorBucket.getItem(
100+
const cursor = await cursorBucket.getItem(
89101
`${owner}:${repo}:${defaultBranch}`,
90102
);
91-
const pinnedSha = defaultCursor?.sha ?? null;
92-
93-
const binding = useBinding(event as Parameters<typeof useBinding>[0]);
94-
const prefix = `${useCursorsBucket.base}:${owner}:${repo}:`;
95-
const branchByShaCandidates = new Map<string, Set<string>>();
96-
let listCursor: string | undefined;
97-
98-
do {
99-
const response = await binding.list({
100-
cursor: listCursor,
101-
limit: 1000,
102-
prefix,
103-
} as any);
104-
105-
for (const object of response.objects) {
106-
const trimmed = object.key.slice(prefix.length);
107-
if (!trimmed || isPullRequestRef(trimmed)) {
108-
continue;
109-
}
110-
const cursor = await cursorBucket.getItem(`${owner}:${repo}:${trimmed}`);
111-
if (!cursor?.sha) {
112-
continue;
113-
}
114-
const existing = branchByShaCandidates.get(cursor.sha) ?? new Set();
115-
existing.add(trimmed);
116-
branchByShaCandidates.set(cursor.sha, existing);
117-
}
118-
119-
listCursor = response.truncated ? response.cursor : undefined;
120-
} while (listCursor);
121-
122-
const branchBySha = new Map<string, string>();
123-
for (const [sha, branches] of branchByShaCandidates) {
124-
const ordered = [...branches].sort((a, b) => {
125-
if (a === defaultBranch && b !== defaultBranch) {
126-
return -1;
127-
}
128-
if (b === defaultBranch && a !== defaultBranch) {
129-
return 1;
130-
}
131-
return a.localeCompare(b);
132-
});
133-
branchBySha.set(sha, ordered[0]!);
134-
}
135-
136-
return {
137-
defaultBranch,
138-
pinnedSha,
139-
branchBySha,
140-
};
103+
return cursor?.sha ?? null;
141104
}
142105

143106
function makeReleaseText(
@@ -220,7 +183,7 @@ export default defineEventHandler(async (event) => {
220183
query.owner,
221184
query.repo,
222185
);
223-
const { pinnedSha, branchBySha } = await getRepoBranchInfo(
186+
const pinnedSha = await getDefaultBranchPinnedSha(
224187
event,
225188
installation,
226189
query.owner,
@@ -250,7 +213,7 @@ export default defineEventHandler(async (event) => {
250213
const totalCount = releases.length;
251214
const totalPages = Math.max(1, Math.ceil(totalCount / perPage));
252215
const origin = getRequestURL(event).origin;
253-
const commitMessages = await getCommitMessages(
216+
const commitMetadata = await getCommitMetadata(
254217
installation,
255218
query.owner,
256219
query.repo,
@@ -266,14 +229,15 @@ export default defineEventHandler(async (event) => {
266229
nodes: pageItems.map((row) => {
267230
const abbreviatedOid = row.sha.slice(0, 7);
268231
const sortedPackages = [...row.packages].sort();
269-
const commitTitle = commitMessages.get(row.sha);
232+
const meta = commitMetadata.get(row.sha);
233+
const commitTitle = meta?.message ?? null;
270234
return {
271235
id: row.sha,
272236
oid: row.sha,
273237
abbreviatedOid,
274238
message: commitTitle ?? row.sha,
275239
unverified: !commitTitle,
276-
branch: branchBySha.get(row.sha) ?? null,
240+
branch: meta?.branch ?? null,
277241
authoredDate: new Date(row.uploadedAt).toISOString(),
278242
url: `https://github.com/${query.owner}/${query.repo}/commit/${row.sha}`,
279243
statusCheckRollup: {

0 commit comments

Comments
 (0)