Skip to content

Commit 1086b02

Browse files
feat(details): add "merged in" tag on PRs
fixes #89, thanks Refined GitHub
1 parent 52de3ad commit 1086b02

File tree

4 files changed

+120
-17
lines changed

4 files changed

+120
-17
lines changed

src/lib/types.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,58 @@ export type Category = (typeof availableCategory)[number];
6161

6262
export type Issues = InstanceType<typeof Octokit>["rest"]["issues"];
6363
export type Pulls = InstanceType<typeof Octokit>["rest"]["pulls"];
64+
/**
65+
* The JSON API response for `https://github.com/{user}/{repo}/branch_commits/{sha}`
66+
*/
67+
export type BranchCommit = {
68+
/**
69+
* The branches for the given commit
70+
*/
71+
branches: {
72+
/**
73+
* The branch name
74+
* @example main
75+
*/
76+
branch: string;
77+
/**
78+
* The linked pull requests
79+
*/
80+
prs: {
81+
/**
82+
* The PR number
83+
* @example 16119
84+
*/
85+
number: number;
86+
/**
87+
* I have no clue honestly, `false` most often
88+
*/
89+
showPrefix: boolean;
90+
/**
91+
* The repository this PR is on
92+
*/
93+
repo: {
94+
/**
95+
* The repository name
96+
* @example svelte
97+
*/
98+
name: string;
99+
/**
100+
* The repository owner
101+
* @example sveltejs
102+
*/
103+
ownerLogin: string;
104+
};
105+
/**
106+
* The PR's node ID(?)
107+
*/
108+
globalRelayId: string;
109+
}[];
110+
}[];
111+
/**
112+
* A list of tags this commit appears in
113+
*/
114+
tags: string[];
115+
};
64116

65117
/**
66118
* The slug name for all the packages

src/routes/[pid=pid]/[org]/[repo]/[id=number]/+page.server.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { error, redirect } from "@sveltejs/kit";
22
import { githubCache } from "$lib/server/github-cache";
3+
import type { BranchCommit } from "$lib/types";
34

4-
export async function load({ params }) {
5+
export async function load({ params, fetch }) {
56
const { pid: type, org, repo, id } = params;
67
const numId = +id; // id is already validated by the route matcher
78

@@ -27,6 +28,31 @@ export async function load({ params }) {
2728
? ("discussion" as const)
2829
: ("pull" as const)
2930
},
30-
item
31+
item,
32+
mergedTagName: new Promise<string | undefined>((resolve, reject) => {
33+
// Credit to Refined GitHub: https://github.com/refined-github/refined-github/blob/main/source/features/closing-remarks.tsx
34+
// Get the merged PR's sha, otherwise it is not a proper target for this
35+
if (!("merged" in item.info)) {
36+
resolve(undefined);
37+
return;
38+
}
39+
const sha = item.info.merge_commit_sha;
40+
if (!sha) {
41+
resolve(undefined);
42+
return;
43+
}
44+
// Fetch the merge commit's info
45+
fetch(`https://github.com/${org}/${repo}/branch_commits/${sha}`, {
46+
headers: {
47+
Accept: "application/json"
48+
}
49+
})
50+
.then(res => res.json() as Promise<BranchCommit>)
51+
.then(({ tags }) =>
52+
// The info is right here after a little filtering :D
53+
resolve(tags.findLast(tag => !tag.includes("nightly") && /\d[.]\d/.test(tag)))
54+
)
55+
.catch(reject);
56+
})
3157
};
3258
}

src/routes/[pid=pid]/[org]/[repo]/[id=number]/+page.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@
2626
{commits}
2727
{files}
2828
{linkedEntities}
29+
mergedTagName={data.mergedTagName}
2930
/>

src/routes/[pid=pid]/[org]/[repo]/[id=number]/PageRenderer.svelte

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
ChevronLeft,
2727
FileDiff,
2828
GitCommitVertical,
29+
Info,
2930
Lock,
3031
MessagesSquare
3132
} from "@lucide/svelte";
@@ -42,6 +43,7 @@
4243
PullRequestDetails
4344
} from "$lib/server/github-cache";
4445
import * as Accordion from "$lib/components/ui/accordion";
46+
import * as Alert from "$lib/components/ui/alert";
4547
import * as Avatar from "$lib/components/ui/avatar";
4648
import { Badge } from "$lib/components/ui/badge";
4749
import { Button } from "$lib/components/ui/button";
@@ -129,9 +131,10 @@
129131
commits: PullRequestDetails["commits"];
130132
files: PullRequestDetails["files"];
131133
linkedEntities: LinkedItem[];
134+
mergedTagName: Promise<string | undefined>;
132135
};
133136
134-
let { metadata, info, comments, commits, files, linkedEntities }: Props = $props();
137+
let { metadata, info, comments, commits, files, linkedEntities, mergedTagName }: Props = $props();
135138
136139
let rightPartInfo = $derived<{ title: string; value: string }[]>([
137140
...("answer_chosen_at" in info && info.answer_chosen_at
@@ -363,11 +366,9 @@
363366
</div>
364367
<div class="mt-4 flex flex-col gap-4">
365368
<!-- Info -->
366-
<div
367-
class="mb-8 flex w-full flex-col justify-center gap-8 *:h-fit *:rounded-md *:border md:flex-row"
368-
>
369+
<div class="mb-8 flex w-full flex-col justify-center gap-8 *:h-fit md:flex-row">
369370
<!-- Left part - body -->
370-
<div class="flex-1 bg-muted/30">
371+
<div class="flex-1 rounded-md border bg-muted/30">
371372
<!-- Author -->
372373
<div
373374
class="inline-flex w-full flex-col gap-1 border-b bg-muted/60 px-4 py-2 xs:flex-row xs:items-center xs:gap-0"
@@ -409,17 +410,40 @@
409410
</div>
410411
</div>
411412
<!-- Right part - info -->
412-
<div class="px-4 pb-3 md:w-2/5 md:max-w-xs md:min-w-72">
413-
<h4 class="-mx-4 mb-4 border-b bg-muted/40 px-4 pt-2 pb-1 text-xl font-semibold">Info</h4>
414-
{#each rightPartInfo as { title, value }, i (title)}
415-
{#if i > 0}
416-
<Separator class="my-2" />
413+
<div class="flex flex-col gap-4 md:w-2/5 md:max-w-xs md:min-w-72">
414+
<div class="rounded-md border px-4 pb-3">
415+
<h4 class="-mx-4 mb-4 border-b bg-muted/40 px-4 pt-2 pb-1 text-xl font-semibold">Info</h4>
416+
{#each rightPartInfo as { title, value }, i (title)}
417+
{#if i > 0}
418+
<Separator class="my-2" />
419+
{/if}
420+
<div class="flex items-center justify-between gap-2">
421+
<span class="font-medium">{title}</span>
422+
<span class="text-right text-muted-foreground">{value}</span>
423+
</div>
424+
{/each}
425+
</div>
426+
{#await mergedTagName then tagName}
427+
{#if tagName}
428+
<Alert.Root class="rounded-md border-green-500 bg-green-400/10">
429+
<Info class="size-4" />
430+
<Alert.Description class="inline text-foreground">
431+
This pull request was merged in
432+
<Button
433+
variant="link"
434+
href="https://github.com/{metadata.org}/{metadata.repo}/releases/tag/{tagName}"
435+
target="_blank"
436+
class="group h-auto gap-0.5 p-0 text-green-500 has-[>svg]:px-0"
437+
>
438+
{tagName}
439+
<ArrowUpRight
440+
class="-translate-x-2 opacity-0 transition group-hover:translate-x-0 group-hover:opacity-100"
441+
/>
442+
</Button>
443+
</Alert.Description>
444+
</Alert.Root>
417445
{/if}
418-
<div class="flex items-center justify-between gap-2">
419-
<span class="font-medium">{title}</span>
420-
<span class="text-right text-muted-foreground">{value}</span>
421-
</div>
422-
{/each}
446+
{/await}
423447
</div>
424448
</div>
425449
<!-- Comments -->

0 commit comments

Comments
 (0)