Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions frontend/src/apiDefinitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,3 +495,71 @@ export interface OSHScan {
task_id: number | null;
url: string | null;
}

// /api/log-detective
export interface LogDetectiveResultGroup {
packit_id: number;
analysis_id: string;
status: string;
chroot: string;
commit_sha: string;
log_detective_response: LogDetectiveResponse | null;
target_build: string | null;
run_ids: number[];
submitted_time: number | null;
}

// /api/log-detective/groups/$id
export interface LogDetectiveGroup {
packit_id: number;
submitted_time: number | null;
run_ids: number[];
log_detective_target_ids: number[];
pr_id: number | null;
issue_id: number | null;
branch_name: string | null;
release: string | null;
anitya_version: string | null;
anitya_project_id: number | null;
anitya_project_name: string | null;
anitya_package: string | null;
non_git_upstream: boolean;
project_url: string;
repo_name: string;
repo_namespace: string;
}

// /api/log-detective/$id
export interface LogDetectiveExplanation {
logprobs: unknown | null;
text: string;
}

export interface LogDetectiveResponse {
explanation: LogDetectiveExplanation;
response_certainty: number;
}

export interface LogDetectiveResult {
packit_id: number;
analysis_id: string;
branch_name: string | null;
chroot: string;
commit_sha: string;
run_ids: number[];
status: string;
log_detective_response: LogDetectiveResponse | null;
target_build: string | null;
submitted_time: number | null;
project_url: string;
pr_id: number | null;
issue_id: number | null;
release: string | null;
anitya_version: string | null;
anitya_project_id: number | null;
anitya_project_name: string | null;
anitya_package: string | null;
non_git_upstream: boolean;
repo_name: string;
repo_namespace: string;
}
3 changes: 3 additions & 0 deletions frontend/src/components/jobs/Jobs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ const Jobs = () => {
Koji Tagging Requests
</Link>
</NavItem>
<NavItem isActive={!!matchRoute(jobTypeObject("log-detective"))}>
<Link {...jobTypeObject("log-detective")}>Log Detective</Link>
</NavItem>
</NavList>
</Nav>
<PageSection hasBodyWrapper={false}>
Expand Down
128 changes: 128 additions & 0 deletions frontend/src/components/logdetective/LogDetectiveGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright Contributors to the Packit project.
// SPDX-License-Identifier: MIT

import {
Card,
CardBody,
Content,
DescriptionList,
DescriptionListDescription,
DescriptionListGroup,
DescriptionListTerm,
List,
ListItem,
PageSection,
Title,
} from "@patternfly/react-core";

import { useQuery } from "@tanstack/react-query";
import { Link } from "@tanstack/react-router";
import { logDetectiveGroupQueryOptions } from "../../queries/logdetective/logDetectiveGroupQuery";
import { Route as LogDetectiveGroupRoute } from "../../routes/jobs_/log-detective.group.$id";
import { ErrorConnection } from "../errors/ErrorConnection";
import { Preloader } from "../shared/Preloader";
import { Timestamp } from "../shared/Timestamp";
import { TriggerLink, TriggerSuffix } from "../trigger/TriggerLink";

export const LogDetectiveGroup = () => {
const { id } = LogDetectiveGroupRoute.useParams();

const { data, isError, isLoading } = useQuery(
logDetectiveGroupQueryOptions({ id }),
);

// If backend API is down
if (isError) {
return <ErrorConnection />;
}

if (data && "error" in data) {
return (
<PageSection hasBodyWrapper={false}>
<Card>
<CardBody>
<Title headingLevel="h1" size="lg">
Not Found.
</Title>
</CardBody>
</Card>
</PageSection>
);
}

return (
<>
<PageSection hasBodyWrapper={false}>
<Content>
<Content component="h1">Log Detective Group</Content>
<strong>
{data ? (
<TriggerLink trigger={data}>
<TriggerSuffix trigger={data} />
</TriggerLink>
) : (
<></>
)}
</strong>
</Content>
</PageSection>
<PageSection hasBodyWrapper={false}>
<Card>
{!data ? (
isLoading || data === undefined ? (
<Preloader />
) : (
<PageSection hasBodyWrapper={false}>
<Card>
<CardBody>
<Title headingLevel="h1" size="lg">
Not Found.
</Title>
</CardBody>
</Card>
</PageSection>
)
) : (
<CardBody>
<DescriptionList
columnModifier={{
default: "1Col",
sm: "2Col",
}}
>
<DescriptionListGroup>
<DescriptionListTerm>Submitted Time</DescriptionListTerm>
<DescriptionListDescription>
<Timestamp stamp={data.submitted_time} verbose={true} />
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>
Log Detective Targets
</DescriptionListTerm>
<DescriptionListDescription>
<List isPlain>
{data.log_detective_target_ids.map((targetId) => (
<ListItem key={targetId}>
<Link to={`/jobs/log-detective/${targetId}`}>
#{targetId}
</Link>
</ListItem>
))}
</List>
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>Run IDs</DescriptionListTerm>
<DescriptionListDescription>
{data.run_ids.join(", ")}
</DescriptionListDescription>
</DescriptionListGroup>
</DescriptionList>
</CardBody>
)}
</Card>
</PageSection>
</>
);
};
132 changes: 132 additions & 0 deletions frontend/src/components/logdetective/LogDetectiveResult.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright Contributors to the Packit project.
// SPDX-License-Identifier: MIT

import {
Card,
CardBody,
CodeBlock,
CodeBlockCode,
Content,
DescriptionList,
DescriptionListDescription,
DescriptionListGroup,
DescriptionListTerm,
PageSection,
Title,
} from "@patternfly/react-core";

import { useQuery } from "@tanstack/react-query";
import { logDetectiveResultQueryOptions } from "../../queries/logdetective/logDetectiveResultQuery";
import { Route as LogDetectiveRoute } from "../../routes/jobs_/log-detective.$id";
import { ErrorConnection } from "../errors/ErrorConnection";
import { Preloader } from "../shared/Preloader";
import { Timestamp } from "../shared/Timestamp";
import { StatusLabel } from "../statusLabels/StatusLabel";

export const LogDetectiveResult = () => {
const { id } = LogDetectiveRoute.useParams();

const { data, isError, isLoading } = useQuery(
logDetectiveResultQueryOptions({ id }),
);

// If backend API is down
if (isError) {
return <ErrorConnection />;
}

if (data && "error" in data) {
return (
<PageSection hasBodyWrapper={false}>
<Card>
<CardBody>
<Title headingLevel="h1" size="lg">
Not Found.
</Title>
</CardBody>
</Card>
</PageSection>
);
}

return (
<>
<PageSection hasBodyWrapper={false}>
<Content>
<Content component="h1">Log Detective Results</Content>
</Content>
</PageSection>
<PageSection hasBodyWrapper={false}>
<Card>
{!data ? (
isLoading || data === undefined ? (
<Preloader />
) : (
<PageSection hasBodyWrapper={false}>
<Card>
<CardBody>
<Title headingLevel="h1" size="lg">
Not Found.
</Title>
</CardBody>
</Card>
</PageSection>
)
) : (
<>
<CardBody>
<DescriptionList
columnModifier={{
default: "1Col",
sm: "2Col",
}}
>
<DescriptionListGroup>
<DescriptionListTerm>Packit ID</DescriptionListTerm>
<DescriptionListDescription>
{data.packit_id}
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>Analysis ID</DescriptionListTerm>
<DescriptionListDescription>
{data.analysis_id}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it could be beneficial to be able to go back to the koji/copr build view from here, but we can leave it as follow-up

</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>Status</DescriptionListTerm>
<DescriptionListDescription>
<StatusLabel status={data.status} />
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
<DescriptionListTerm>Submitted Time</DescriptionListTerm>
<DescriptionListDescription>
<Timestamp stamp={data.submitted_time} verbose={true} />
</DescriptionListDescription>
</DescriptionListGroup>
</DescriptionList>
</CardBody>
{data.log_detective_response?.explanation ? (
<CardBody>
<DescriptionList>
<DescriptionListGroup>
<DescriptionListTerm>Explanation</DescriptionListTerm>
<DescriptionListDescription>
<CodeBlock>
<CodeBlockCode>
{data.log_detective_response.explanation.text}
</CodeBlockCode>
</CodeBlock>
</DescriptionListDescription>
</DescriptionListGroup>
</DescriptionList>
</CardBody>
) : null}
</>
)}
</Card>
</PageSection>
</>
);
};
Loading
Loading