mirror of
https://github.com/MeshEnvy/mesh-forge.git
synced 2026-05-16 06:15:51 +02:00
Refactor CI failure handling in RepoPage and update error messages in formatBuildErrorSummary. Improved user feedback for build retries and adjusted UI logic to show CI failure state more accurately.
This commit is contained in:
@@ -32,7 +32,7 @@ export function buildFailurePresentation(summary: string | undefined): {
|
||||
if (/GitHub API failed:\s*5\d\d/.test(summary) || /GitHub API failed:\s*429/.test(summary)) {
|
||||
return {
|
||||
headline: 'GitHub was temporarily unavailable',
|
||||
body: 'Starting the build failed because GitHub returned an error or rate limit. Use Retry build — it often works on a second try.',
|
||||
body: 'Starting the build failed because GitHub returned an error or rate limit. Flash again — it often works on a second try.',
|
||||
}
|
||||
}
|
||||
if (/GitHub API failed:\s*4\d\d/.test(summary) && !summary.includes('422')) {
|
||||
@@ -50,7 +50,7 @@ export function buildFailurePresentation(summary: string | undefined): {
|
||||
return {
|
||||
headline: 'Build failed in CI',
|
||||
body:
|
||||
'Often a compile error, missing PlatformIO dependency, or bad env config in the repo. Fix the project if you can, then use Retry build. ' +
|
||||
'Transient CI issues also happen — retry is safe.',
|
||||
'Often a compile error, missing PlatformIO dependency, or bad env config in the repo. Fix the project if you can, then use Flash again. ' +
|
||||
'Transient CI issues also happen — trying again is safe.',
|
||||
}
|
||||
}
|
||||
|
||||
+42
-5
@@ -3,7 +3,7 @@ import { api } from "@/convex/_generated/api"
|
||||
import { sortTagNames } from "@/convex/lib/tagSemver"
|
||||
import { useAction, useMutation, useQuery } from "convex/react"
|
||||
import { Github, Link2, RefreshCw } from "lucide-react"
|
||||
import { useEffect, useLayoutEffect, useMemo, useState } from "react"
|
||||
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"
|
||||
import ReactMarkdown from "react-markdown"
|
||||
import { Link, useNavigate, useParams } from "react-router-dom"
|
||||
import rehypeRaw from "rehype-raw"
|
||||
@@ -158,6 +158,39 @@ export default function RepoPage() {
|
||||
const buildKey = resolvedSha && resolvedTargetEnv ? normalizeBuildKey(resolvedSha, resolvedTargetEnv) : null
|
||||
const build = useQuery(api.repoBuilds.getByBuildKey, buildKey ? { buildKey } : "skip")
|
||||
|
||||
/** Only show CI failure UI if this tab saw the build move into `failed` (not for stale failures on load). */
|
||||
const [witnessedCiFailure, setWitnessedCiFailure] = useState(false)
|
||||
const trackedBuildKeyRef = useRef<string | null>(null)
|
||||
const prevBuildStatusRef = useRef<string | "absent" | undefined>(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
if (!buildKey) {
|
||||
trackedBuildKeyRef.current = null
|
||||
setWitnessedCiFailure(false)
|
||||
prevBuildStatusRef.current = undefined
|
||||
return
|
||||
}
|
||||
|
||||
if (trackedBuildKeyRef.current !== buildKey) {
|
||||
trackedBuildKeyRef.current = buildKey
|
||||
setWitnessedCiFailure(false)
|
||||
prevBuildStatusRef.current = undefined
|
||||
}
|
||||
|
||||
if (build === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const status = build === null ? "absent" : build.status
|
||||
const prev = prevBuildStatusRef.current
|
||||
|
||||
if (status === "failed" && prev !== undefined && prev !== "failed") {
|
||||
setWitnessedCiFailure(true)
|
||||
}
|
||||
|
||||
prevBuildStatusRef.current = status
|
||||
}, [buildKey, build])
|
||||
|
||||
const [flashUrl, setFlashUrl] = useState<string | null>(null)
|
||||
const [flashPrep, setFlashPrep] = useState<"idle" | "loading" | "ready" | "error">("idle")
|
||||
|
||||
@@ -190,7 +223,7 @@ export default function RepoPage() {
|
||||
if (!effectiveRef || !resolvedSha || !resolvedTargetEnv) return
|
||||
if (build?.status === "failed" && build._id) {
|
||||
void retryBuild({ buildId: build._id })
|
||||
.then(() => toast.message("Re-queued build"))
|
||||
.then(() => toast.message("Starting a new build…"))
|
||||
.catch(e => toast.error(String(e)))
|
||||
return
|
||||
}
|
||||
@@ -263,7 +296,11 @@ export default function RepoPage() {
|
||||
!scanReady ||
|
||||
buildInProgress
|
||||
|
||||
const flashButtonLabel = build?.status === "failed" ? "Retry build" : buildInProgress ? "Building…" : "Flash"
|
||||
const flashButtonLabel = buildInProgress ? "Building…" : "Flash"
|
||||
|
||||
const showCiCard =
|
||||
build &&
|
||||
(build.status !== "failed" || witnessedCiFailure)
|
||||
|
||||
const targetPlaceholder = !hasRef
|
||||
? "--target--"
|
||||
@@ -368,7 +405,7 @@ export default function RepoPage() {
|
||||
</div>
|
||||
|
||||
<div className="max-w-2xl space-y-4">
|
||||
{build ? (
|
||||
{showCiCard ? (
|
||||
<div className="rounded-lg border border-slate-800 bg-slate-900/40 p-4 space-y-2 text-sm">
|
||||
<div className="flex flex-wrap gap-2 items-center">
|
||||
<span className="text-slate-500">CI</span>
|
||||
@@ -408,7 +445,7 @@ export default function RepoPage() {
|
||||
</summary>
|
||||
<pre className="mt-2 max-h-40 overflow-auto whitespace-pre-wrap wrap-break-word text-[11px] text-red-300/90">
|
||||
{build.errorSummary.length > 2500
|
||||
? `${build.errorSummary.slice(0, 2500)}…`
|
||||
? `…${build.errorSummary.slice(-2500)}`
|
||||
: build.errorSummary}
|
||||
</pre>
|
||||
</details>
|
||||
|
||||
Reference in New Issue
Block a user