diff --git a/express/frontend/src/lib/gitHub.ts b/express/frontend/src/lib/gitHub.ts index 991bacc..87323fa 100644 --- a/express/frontend/src/lib/gitHub.ts +++ b/express/frontend/src/lib/gitHub.ts @@ -113,6 +113,17 @@ export class GitHubRepoComm { return result.data; } + public readonly getBranches = AsyncCache.of(async () => { + const result = await this.request( + "GET /repos/{owner}/{repo}/branches", + { + ...this.baseOptions, + per_page: 100, + }, + ); + return result.data; + }); + public readonly getTags = AsyncCache.of(async () => { const result = await this.request("GET /repos/{owner}/{repo}/tags", { ...this.baseOptions, diff --git a/express/frontend/src/lib/ioBroker.ts b/express/frontend/src/lib/ioBroker.ts index ed63024..96f91f2 100644 --- a/express/frontend/src/lib/ioBroker.ts +++ b/express/frontend/src/lib/ioBroker.ts @@ -247,9 +247,12 @@ export interface CheckResults { errors: CheckResult[]; } -export async function checkAdapter(repoName: string) { - const { data } = await axios.get( - `${getApiUrl("repochecker/")}?url=${uc(`https://github.com/${repoName}`)}`, - ); +export async function checkAdapter(repoName: string, branchName?: string) { + const url = new URL(getApiUrl("repochecker/"), window.location.origin); + url.searchParams.set("url", `https://github.com/${repoName}`); + if (branchName) { + url.searchParams.set("branch", branchName); + } + const { data } = await axios.get(url.toString()); return data; } diff --git a/express/frontend/src/tools/AdapterCheck.tsx b/express/frontend/src/tools/AdapterCheck.tsx index 1f5fd75..d37355f 100644 --- a/express/frontend/src/tools/AdapterCheck.tsx +++ b/express/frontend/src/tools/AdapterCheck.tsx @@ -24,6 +24,7 @@ import { useEffect, useState } from "react"; import Chart from "react-google-charts"; import { useSearchParams } from "react-router-dom"; import { useUserToken } from "../contexts/UserContext"; +import { GitHubComm } from "../lib/gitHub"; import { checkAdapter, CheckResult, getMyAdapterRepos } from "../lib/ioBroker"; export const iconStyles = { @@ -95,6 +96,8 @@ export function AdapterCheck() { const [searchParams] = useSearchParams(); const [repoNames, setRepoNames] = useState([]); const [repoName, setRepoName] = useState(""); + const [branchNames, setBranchNames] = useState([]); + const [branchName, setBranchName] = useState(""); const [busy, setBusy] = useState(false); const [messages, setMessages] = useState([]); useEffect(() => { @@ -112,11 +115,38 @@ export function AdapterCheck() { } }, [repo]); + useEffect(() => { + setBranchName(""); + setBranchNames([]); + let cancelled = false; + const loadBranches = async () => { + const [owner, repo] = repoName.split("/"); + if (!owner || !repo) { + return; + } + + const gitHub = GitHubComm.forToken(token); + const branches = await gitHub.getRepo(owner, repo).getBranches(); + if (!cancelled) { + setBranchNames( + branches + .map((b) => b.name) + .filter((b) => !b.startsWith("dependabot/")), + ); + } + }; + loadBranches().catch(console.error); + + return () => { + cancelled = true; + }; + }, [repoName, token]); + const handleStartClick = async () => { setMessages([]); setBusy(true); try { - const results = await checkAdapter(repoName); + const results = await checkAdapter(repoName, branchName); const messages = results.errors.map((c) => new Message("error", c)); messages.push( ...results.warnings.map((c) => new Message("warning", c)), @@ -176,6 +206,24 @@ export function AdapterCheck() { )} /> + + option} + sx={{ width: 170 }} + inputValue={branchName} + onInputChange={(_e, value) => setBranchName(value)} + renderInput={(params) => ( + + )} + /> +