Skip to content

Commit a61935f

Browse files
committed
init
1 parent 91c93fc commit a61935f

3 files changed

Lines changed: 159 additions & 22 deletions

File tree

packages/app/app/components/Commits.vue

Lines changed: 88 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,55 @@ const props = defineProps<{
1212
repo: string;
1313
}>();
1414
15-
const data = await $fetch("/api/repo/commits", {
16-
query: {
17-
owner: props.owner,
18-
repo: props.repo,
19-
},
20-
});
15+
type BranchesResponse = {
16+
branches: string[];
17+
};
18+
19+
const [data, branchesResponse] = await Promise.all([
20+
$fetch("/api/repo/commits", {
21+
query: {
22+
owner: props.owner,
23+
repo: props.repo,
24+
},
25+
}),
26+
$fetch<BranchesResponse>("/api/repo/branches", {
27+
query: {
28+
owner: props.owner,
29+
repo: props.repo,
30+
},
31+
}).catch(() => null),
32+
]);
2133
2234
if (!data) {
2335
throw createError("Could not load Commits");
2436
}
2537
2638
const branch = shallowReactive(data);
39+
const selectedBranch = ref(branch.name);
40+
const availableBranches = ref<string[]>(
41+
branchesResponse?.branches?.length ? branchesResponse.branches : [branch.name],
42+
);
43+
44+
if (!availableBranches.value.includes(branch.name)) {
45+
availableBranches.value.unshift(branch.name);
46+
}
2747
2848
const commitsWithRelease = computed(() =>
2949
branch.target.history.nodes
30-
.filter((commit) =>
31-
commit.statusCheckRollup?.contexts.nodes.some(
32-
(context) => context.name === "Continuous Releases",
33-
),
34-
)
35-
.map((commit) => ({
36-
...commit,
37-
release: commit.statusCheckRollup.contexts.nodes.find(
50+
.flatMap((commit) => {
51+
const release = commit.statusCheckRollup?.contexts.nodes.find(
3852
(context) => context.name === "Continuous Releases",
39-
)!,
40-
})),
53+
);
54+
55+
return release
56+
? [
57+
{
58+
...commit,
59+
release,
60+
},
61+
]
62+
: [];
63+
}),
4164
);
4265
4366
const selectedCommit = shallowRef<
@@ -114,6 +137,39 @@ onBeforeUnmount(() => {
114137
// Pagination
115138
const fetching = ref(false);
116139
const fetchMoreForceDisabled = ref(!commitsWithRelease.value.length);
140+
const switchingBranch = ref(false);
141+
142+
async function loadBranch(branchName: string) {
143+
if (switchingBranch.value) {
144+
return;
145+
}
146+
147+
const previousBranch = branch.name;
148+
149+
try {
150+
switchingBranch.value = true;
151+
selectedCommit.value = null;
152+
153+
const result = await $fetch("/api/repo/commits", {
154+
query: {
155+
owner: props.owner,
156+
repo: props.repo,
157+
branch: branchName,
158+
},
159+
});
160+
161+
Object.assign(branch, result);
162+
fetchMoreForceDisabled.value = !commitsWithRelease.value.length;
163+
} catch (error) {
164+
selectedBranch.value = previousBranch;
165+
} finally {
166+
switchingBranch.value = false;
167+
}
168+
}
169+
170+
async function onBranchChange() {
171+
await loadBranch(selectedBranch.value);
172+
}
117173
118174
async function fetchMore() {
119175
if (!branch.target.history.pageInfo.hasNextPage) {
@@ -133,6 +189,7 @@ async function fetchMore() {
133189
query: {
134190
owner: props.owner,
135191
repo: props.repo,
192+
branch: selectedBranch.value,
136193
cursor,
137194
},
138195
});
@@ -159,10 +216,23 @@ async function fetchMore() {
159216

160217
<template>
161218
<div class="flex flex-col gap-6">
162-
<div class="text-center flex justify-center items-center gap-1 opacity-80">
219+
<div class="text-center flex justify-center items-center gap-2 opacity-80">
163220
Continuous Releases from
164221
<UIcon name="i-ph-git-branch" />
165-
{{ branch.name }}
222+
<select
223+
v-model="selectedBranch"
224+
class="px-2 py-1 rounded-md bg-transparent border border-gray-300 dark:border-gray-700 text-sm"
225+
:disabled="switchingBranch"
226+
@change="onBranchChange"
227+
>
228+
<option
229+
v-for="branchName of availableBranches"
230+
:key="branchName"
231+
:value="branchName"
232+
>
233+
{{ branchName }}
234+
</option>
235+
</select>
166236
</div>
167237

168238
<div class="flex flex-col gap-2">
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { z } from "zod";
2+
3+
const querySchema = z.object({
4+
owner: z.string(),
5+
repo: z.string(),
6+
});
7+
8+
export default defineEventHandler(async (event) => {
9+
try {
10+
const query = await getValidatedQuery(event, (data) =>
11+
querySchema.parse(data),
12+
);
13+
const installation = await useOctokitInstallation(
14+
event,
15+
query.owner,
16+
query.repo,
17+
);
18+
19+
const per_page = 100;
20+
const branches: string[] = [];
21+
let page = 1;
22+
23+
while (true) {
24+
const { data } = await installation.request("GET /repos/{owner}/{repo}/branches", {
25+
owner: query.owner,
26+
repo: query.repo,
27+
per_page,
28+
page,
29+
});
30+
31+
branches.push(...data.map((branch) => branch.name));
32+
33+
if (data.length < per_page) {
34+
break;
35+
}
36+
37+
page += 1;
38+
}
39+
40+
const { data: repo } = await installation.request("GET /repos/{owner}/{repo}", {
41+
owner: query.owner,
42+
repo: query.repo,
43+
});
44+
45+
const defaultBranch = repo.default_branch;
46+
const uniqueBranches = [...new Set(branches)];
47+
const sortedBranches = [
48+
defaultBranch,
49+
...uniqueBranches.filter((branch) => branch !== defaultBranch).sort(),
50+
];
51+
52+
return {
53+
defaultBranch,
54+
branches: sortedBranches,
55+
};
56+
} catch (error) {
57+
console.error("Error fetching repository branches:", error);
58+
return {
59+
error: true,
60+
message: (error as Error).message,
61+
defaultBranch: "main",
62+
branches: ["main"],
63+
};
64+
}
65+
});

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { z } from "zod";
33
const querySchema = z.object({
44
owner: z.string(),
55
repo: z.string(),
6+
branch: z.string().optional(),
67
cursor: z.string().optional(),
78
page: z.string().optional(),
89
per_page: z.string().optional().default("10"),
@@ -28,6 +29,7 @@ export default defineEventHandler(async (event) => {
2829
);
2930

3031
const defaultBranch = repo.default_branch;
32+
const targetBranch = query.branch || defaultBranch;
3133

3234
const page = query.page
3335
? Number.parseInt(query.page)
@@ -41,7 +43,7 @@ export default defineEventHandler(async (event) => {
4143
{
4244
owner: query.owner,
4345
repo: query.repo,
44-
sha: defaultBranch,
46+
sha: targetBranch,
4547
page,
4648
per_page,
4749
},
@@ -118,10 +120,10 @@ export default defineEventHandler(async (event) => {
118120
const nextPage = hasNextPage ? (page + 1).toString() : null;
119121

120122
return {
121-
id: `branch-${defaultBranch}`,
122-
name: defaultBranch,
123+
id: `branch-${targetBranch}`,
124+
name: targetBranch,
123125
target: {
124-
id: `target-${defaultBranch}`,
126+
id: `target-${targetBranch}`,
125127
history: {
126128
nodes: commitsWithStatuses,
127129
pageInfo: {

0 commit comments

Comments
 (0)