feat: Report Bug button that creates Gitea issues
Adds a 'Report Bug' button to the web UI (top bar) that files an issue on Gitea via the daemon. The issue body is enriched with auto-collected context: nvcurve version, hostname, GPU name, applied offset summary, active profile, and a collapsed tail of the recent server log. Security model: - The Gitea token (nvcurve_bot, scope write:issue) is embedded as a built-in default so the feature works out of the box for every install of this public repo — no configuration required. - The token is only ever used server-side; it never reaches the browser, logs, or API responses. - The endpoint is behind the existing session auth when enabled, and rate-limited to one report per 5 minutes per client IP. - config.json can override gitea_url/gitea_repo/gitea_token (e.g. forks pointing at their own repo); gitea_token: '' disables it.
This commit is contained in:
1 parent
e89135ef94
commit
1bafbc80b5
6 files changed
+331
-2
No files matched your search
@@ -7,10 +7,13 @@ import {
|
||||
ChevronDown,
|
||||
LogOut,
|
||||
User,
|
||||
Bug,
|
||||
} from "lucide-react";
|
||||
import type { GpuInfo, MonitoringSample } from "../../types.js";
|
||||
import { fmt } from "../../utils/units.js";
|
||||
import { useCurveStore } from "../../store/curveStore.js";
|
||||
import { api } from "../../api/client.js";
|
||||
import { ReportBugDialog } from "../common/ReportBugDialog.js";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
|
||||
interface Props {
|
||||
@@ -43,8 +46,17 @@ export function StatusBar({
|
||||
const { availableGpus, selectedGpuIndex, setSelectedGpuIndex } =
|
||||
useCurveStore();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [bugReportConfigured, setBugReportConfigured] = useState(false);
|
||||
const [reportBugOpen, setReportBugOpen] = useState(false);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
api
|
||||
.reportBugStatus()
|
||||
.then((s) => setBugReportConfigured(s.configured))
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
if (
|
||||
@@ -169,8 +181,18 @@ export function StatusBar({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Right: user + connection status */}
|
||||
{/* Right: report bug + user + connection status */}
|
||||
<div className="flex items-center gap-3 shrink-0">
|
||||
{bugReportConfigured && (
|
||||
<button
|
||||
onClick={() => setReportBugOpen(true)}
|
||||
title="Report a bug (creates a Gitea issue)"
|
||||
className="flex items-center gap-1.5 px-2 py-1 rounded hover:bg-zinc-800 text-zinc-400 hover:text-zinc-200 transition-colors"
|
||||
>
|
||||
<Bug size={14} />
|
||||
<span className="hidden sm:inline text-xs">Report Bug</span>
|
||||
</button>
|
||||
)}
|
||||
{user && (
|
||||
<div className="flex items-center gap-1.5 text-zinc-400">
|
||||
<User size={14} className="text-zinc-500" />
|
||||
@@ -192,6 +214,9 @@ export function StatusBar({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{reportBugOpen && (
|
||||
<ReportBugDialog onClose={() => setReportBugOpen(false)} />
|
||||
)}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user