-
Notifications
You must be signed in to change notification settings - Fork 10
Add SBOM vex download to release overview #602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dd70478
6851da0
2b0b3b6
d73a8d9
1cbe4dc
f1868aa
392f36a
39e5480
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,7 +1,8 @@ | ||||||
| "use client"; | ||||||
|
|
||||||
| import { usePathname, useSearchParams } from "next/navigation"; | ||||||
| import { groupBy, shuffle } from "lodash"; | ||||||
| import { useRouter, useSearchParams } from "next/navigation"; | ||||||
| import { useRouter } from "next/navigation"; | ||||||
| import { useEffect, useMemo } from "react"; | ||||||
| import useSWR from "swr"; | ||||||
| import { QueryArtifactSelector } from "../../../../../../components/ArtifactSelector"; | ||||||
|
|
@@ -14,7 +15,7 @@ import CVERainbowBadge from "../../../../../../components/CVERainbowBadge"; | |||||
| import Page from "../../../../../../components/Page"; | ||||||
| import { RiskHistoryDistributionDiagram } from "../../../../../../components/RiskHistoryDistributionDiagram"; | ||||||
| import SeverityCard from "../../../../../../components/SeverityCard"; | ||||||
| import { Button } from "../../../../../../components/ui/button"; | ||||||
| import { AsyncButton, Button } from "../../../../../../components/ui/button"; | ||||||
| import { | ||||||
| Card, | ||||||
| CardContent, | ||||||
|
|
@@ -54,6 +55,11 @@ import { | |||||
| } from "../../../../../../utils/view"; | ||||||
| import useRouterQuery from "../../../../../../hooks/useRouterQuery"; | ||||||
| import Link from "next/link"; | ||||||
| import { toast } from "sonner"; | ||||||
| import { useActiveProject } from "@/hooks/useActiveProject"; | ||||||
| import { useActiveAsset } from "@/hooks/useActiveAsset"; | ||||||
| import { useActiveAssetVersion } from "@/hooks/useActiveAssetVersion"; | ||||||
| import { browserApiClient } from "../../../../../../services/devGuardApi"; | ||||||
|
|
||||||
| const OverviewPage = () => { | ||||||
| const search = useSearchParams(); | ||||||
|
|
@@ -185,6 +191,8 @@ const OverviewPage = () => { | |||||
| const [mode, setMode] = useViewMode("devguard-view-mode"); | ||||||
| const activeOrg = useActiveOrg(); | ||||||
| const projectMenu = useProjectMenu(); | ||||||
| const asset = useActiveAsset(); | ||||||
| const assetVersion = useActiveAssetVersion(); | ||||||
| const router = useRouter(); | ||||||
| const contentTree = useOrganization().contentTree; | ||||||
|
|
||||||
|
|
@@ -258,6 +266,35 @@ const OverviewPage = () => { | |||||
| return latestRiskHistory.sort(sorter).slice(0, 7); | ||||||
| }, [completeRiskHistory, mode]); | ||||||
|
|
||||||
| const selectedArtifact = useSearchParams()?.get("artifact") || undefined; | ||||||
| const pathname = usePathname(); | ||||||
|
||||||
|
|
||||||
| const downloadSBOMReport = async () => { | ||||||
| try { | ||||||
| const response = await browserApiClient( | ||||||
| `/organizations/${organizationSlug}/projects/${projectSlug}/releases/${releaseId}/sbom.json/`, | ||||||
| { method: "GET", signal: AbortSignal.timeout(60 * 8 * 1000) }, | ||||||
| ); | ||||||
| if (!response.ok) { | ||||||
| toast.error( | ||||||
| "Failed to download SBOM report. Please try again later.", | ||||||
| ); | ||||||
| return; | ||||||
| } | ||||||
| const blob = await response.blob(); | ||||||
| const url = window.URL.createObjectURL(blob); | ||||||
| const link = document.createElement("a"); | ||||||
| link.href = url; | ||||||
| // add download attribute to the link | ||||||
| link.download = `${releaseId}.json`; | ||||||
| document.body.appendChild(link); | ||||||
| link.click(); | ||||||
| document.body.removeChild(link); | ||||||
| } catch (error) { | ||||||
| toast.error("Failed to download SBOM. Please try again later."); | ||||||
| } | ||||||
| }; | ||||||
|
|
||||||
| if (releases?.data.length === 0) { | ||||||
| return ( | ||||||
| <Page title={project.name} Menu={projectMenu} Title={<ProjectTitle />}> | ||||||
|
|
@@ -282,10 +319,21 @@ const OverviewPage = () => { | |||||
|
|
||||||
| return ( | ||||||
| <Page title={project.name} Menu={projectMenu} Title={<ProjectTitle />}> | ||||||
| <div className="mb-4"> | ||||||
| <QueryArtifactSelector | ||||||
| artifacts={releases?.data?.map((r) => r.name) || []} | ||||||
| /> | ||||||
| <div className="mb-4 flex flex-row items-start justify-between"> | ||||||
| <div className="flex items-center gap-2"> | ||||||
| <QueryArtifactSelector | ||||||
| artifacts={releases?.data?.map((r) => r.name) || []} | ||||||
| /> | ||||||
| </div> | ||||||
| <div className="flex relative flex-col"> | ||||||
|
||||||
| <div className="flex relative flex-col"> | |
| <div className="flex flex-col"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The imports 'useActiveProject', 'useActiveAsset', and 'useActiveAssetVersion' are added but never used in the component. These unused imports should be removed to keep the code clean and avoid confusion.