Merge pull request #1567 from github/koesie10/set-repo-results-message
Implement message for setting download status
This commit is contained in:
@@ -2,7 +2,11 @@ import * as sarif from 'sarif';
|
||||
import { AnalysisResults } from '../remote-queries/shared/analysis-result';
|
||||
import { AnalysisSummary, RemoteQueryResult } from '../remote-queries/shared/remote-query-result';
|
||||
import { RawResultSet, ResultRow, ResultSetSchema, Column, ResolvableLocationValue } from './bqrs-cli-types';
|
||||
import { VariantAnalysis } from '../remote-queries/shared/variant-analysis';
|
||||
import {
|
||||
VariantAnalysis,
|
||||
VariantAnalysisScannedRepositoryResult,
|
||||
VariantAnalysisScannedRepositoryState,
|
||||
} from '../remote-queries/shared/variant-analysis';
|
||||
|
||||
/**
|
||||
* This module contains types and code that are shared between
|
||||
@@ -436,8 +440,20 @@ export interface SetVariantAnalysisMessage {
|
||||
variantAnalysis: VariantAnalysis;
|
||||
}
|
||||
|
||||
export interface SetRepoResultsMessage {
|
||||
t: 'setRepoResults';
|
||||
repoResults: VariantAnalysisScannedRepositoryResult[];
|
||||
}
|
||||
|
||||
export interface SetRepoStatesMessage {
|
||||
t: 'setRepoStates';
|
||||
repoStates: VariantAnalysisScannedRepositoryState[];
|
||||
}
|
||||
|
||||
export type ToVariantAnalysisMessage =
|
||||
| SetVariantAnalysisMessage;
|
||||
| SetVariantAnalysisMessage
|
||||
| SetRepoResultsMessage
|
||||
| SetRepoStatesMessage;
|
||||
|
||||
export type FromVariantAnalysisMessage =
|
||||
| ViewLoadedMsg;
|
||||
|
||||
@@ -82,6 +82,18 @@ export interface VariantAnalysisSkippedRepository {
|
||||
private?: boolean,
|
||||
}
|
||||
|
||||
export enum VariantAnalysisScannedRepositoryDownloadStatus {
|
||||
Pending = 'pending',
|
||||
InProgress = 'inProgress',
|
||||
Succeeded = 'succeeded',
|
||||
Failed = 'failed',
|
||||
}
|
||||
|
||||
export interface VariantAnalysisScannedRepositoryState {
|
||||
repositoryId: number;
|
||||
downloadStatus: VariantAnalysisScannedRepositoryDownloadStatus;
|
||||
}
|
||||
|
||||
export interface VariantAnalysisScannedRepositoryResult {
|
||||
repositoryId: number;
|
||||
interpretedResults?: AnalysisAlert[];
|
||||
|
||||
@@ -11,7 +11,11 @@ import {
|
||||
VariantAnalysisRepoTask,
|
||||
VariantAnalysisScannedRepository as ApiVariantAnalysisScannedRepository
|
||||
} from './gh-api/variant-analysis';
|
||||
import { VariantAnalysis } from './shared/variant-analysis';
|
||||
import {
|
||||
VariantAnalysis,
|
||||
VariantAnalysisScannedRepositoryDownloadStatus,
|
||||
VariantAnalysisScannedRepositoryState
|
||||
} from './shared/variant-analysis';
|
||||
import { getErrorMessage } from '../pure/helpers-pure';
|
||||
import { VariantAnalysisView } from './variant-analysis-view';
|
||||
import { VariantAnalysisViewManager } from './variant-analysis-view-manager';
|
||||
@@ -52,17 +56,20 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
this.views.delete(view.variantAnalysisId);
|
||||
}
|
||||
|
||||
public getView(variantAnalysisId: number): VariantAnalysisView | undefined {
|
||||
return this.views.get(variantAnalysisId);
|
||||
}
|
||||
|
||||
private async onVariantAnalysisUpdated(variantAnalysis: VariantAnalysis | undefined): Promise<void> {
|
||||
if (!variantAnalysis) {
|
||||
return;
|
||||
}
|
||||
|
||||
const view = this.views.get(variantAnalysis.id);
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
await this.getView(variantAnalysis.id)?.updateView(variantAnalysis);
|
||||
}
|
||||
|
||||
await view.updateView(variantAnalysis);
|
||||
private async onRepoStateUpdated(variantAnalysisId: number, repoState: VariantAnalysisScannedRepositoryState): Promise<void> {
|
||||
await this.getView(variantAnalysisId)?.updateRepoState(repoState);
|
||||
}
|
||||
|
||||
public async monitorVariantAnalysis(
|
||||
@@ -77,11 +84,19 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
variantAnalysisSummary: VariantAnalysisApiResponse,
|
||||
cancellationToken: CancellationToken
|
||||
): Promise<void> {
|
||||
const repoState = {
|
||||
repositoryId: scannedRepo.repository.id,
|
||||
downloadStatus: VariantAnalysisScannedRepositoryDownloadStatus.Pending,
|
||||
};
|
||||
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
|
||||
const credentials = await Credentials.initialize(this.ctx);
|
||||
if (!credentials) { throw Error('Error authenticating with GitHub'); }
|
||||
|
||||
if (cancellationToken && cancellationToken.isCancellationRequested) {
|
||||
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Failed;
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -93,10 +108,16 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
variantAnalysisSummary.id,
|
||||
scannedRepo.repository.id
|
||||
);
|
||||
} catch (e) {
|
||||
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Failed;
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysisSummary.id}. Error: ${getErrorMessage(e)}`);
|
||||
}
|
||||
catch (e) { throw new Error(`Could not download the results for variant analysis with id: ${variantAnalysisSummary.id}. Error: ${getErrorMessage(e)}`); }
|
||||
|
||||
if (repoTask.artifact_url) {
|
||||
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.InProgress;
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
|
||||
const resultDirectory = path.join(
|
||||
this.ctx.globalStorageUri.fsPath,
|
||||
'variant-analyses',
|
||||
@@ -117,5 +138,8 @@ export class VariantAnalysisManager extends DisposableObject implements VariantA
|
||||
fs.mkdirSync(resultDirectory, { recursive: true });
|
||||
await fs.writeFile(storagePath, JSON.stringify(result, null, 2), 'utf8');
|
||||
}
|
||||
|
||||
repoState.downloadStatus = VariantAnalysisScannedRepositoryDownloadStatus.Succeeded;
|
||||
await this.onRepoStateUpdated(variantAnalysisSummary.id, repoState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { AbstractWebview, WebviewPanelConfig } from '../abstract-webview';
|
||||
import { WebviewMessage } from '../interface-utils';
|
||||
import { logger } from '../logging';
|
||||
import { VariantAnalysisViewInterface, VariantAnalysisViewManager } from './variant-analysis-view-manager';
|
||||
import { VariantAnalysis } from './shared/variant-analysis';
|
||||
import { VariantAnalysis, VariantAnalysisScannedRepositoryState } from './shared/variant-analysis';
|
||||
import { FromVariantAnalysisMessage, ToVariantAnalysisMessage } from '../pure/interface-types';
|
||||
|
||||
export class VariantAnalysisView extends AbstractWebview<ToVariantAnalysisMessage, FromVariantAnalysisMessage> implements VariantAnalysisViewInterface {
|
||||
@@ -32,6 +32,17 @@ export class VariantAnalysisView extends AbstractWebview<ToVariantAnalysisMessag
|
||||
});
|
||||
}
|
||||
|
||||
public async updateRepoState(repoState: VariantAnalysisScannedRepositoryState): Promise<void> {
|
||||
if (!this.isShowingPanel) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.postMessage({
|
||||
t: 'setRepoStates',
|
||||
repoStates: [repoState],
|
||||
});
|
||||
}
|
||||
|
||||
protected getPanelConfig(): WebviewPanelConfig {
|
||||
return {
|
||||
viewId: 'variantAnalysisView',
|
||||
|
||||
@@ -3,7 +3,10 @@ import React from 'react';
|
||||
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
||||
|
||||
import { VariantAnalysisContainer } from '../../view/variant-analysis/VariantAnalysisContainer';
|
||||
import { VariantAnalysisRepoStatus } from '../../remote-queries/shared/variant-analysis';
|
||||
import {
|
||||
VariantAnalysisRepoStatus,
|
||||
VariantAnalysisScannedRepositoryDownloadStatus,
|
||||
} from '../../remote-queries/shared/variant-analysis';
|
||||
import { AnalysisAlert, AnalysisRawResults } from '../../remote-queries/shared/analysis-result';
|
||||
|
||||
import analysesResults from '../remote-queries/data/analysesResultsMessage.json';
|
||||
@@ -62,6 +65,14 @@ Canceled.args = {
|
||||
status: VariantAnalysisRepoStatus.Canceled,
|
||||
};
|
||||
|
||||
export const SucceededDownloading = Template.bind({});
|
||||
SucceededDownloading.args = {
|
||||
...Pending.args,
|
||||
status: VariantAnalysisRepoStatus.Succeeded,
|
||||
resultCount: 198,
|
||||
downloadStatus: VariantAnalysisScannedRepositoryDownloadStatus.InProgress,
|
||||
};
|
||||
|
||||
export const InterpretedResults = Template.bind({});
|
||||
InterpretedResults.args = {
|
||||
...Pending.args,
|
||||
|
||||
@@ -2,7 +2,11 @@ import * as React from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { VSCodeBadge, VSCodeCheckbox } from '@vscode/webview-ui-toolkit/react';
|
||||
import { isCompletedAnalysisRepoStatus, VariantAnalysisRepoStatus } from '../../remote-queries/shared/variant-analysis';
|
||||
import {
|
||||
isCompletedAnalysisRepoStatus,
|
||||
VariantAnalysisRepoStatus,
|
||||
VariantAnalysisScannedRepositoryDownloadStatus
|
||||
} from '../../remote-queries/shared/variant-analysis';
|
||||
import { formatDecimal } from '../../pure/number';
|
||||
import { Codicon, ErrorIcon, LoadingIcon, SuccessIcon, WarningIcon } from '../common';
|
||||
import { Repository } from '../../remote-queries/shared/repository';
|
||||
@@ -62,6 +66,7 @@ export type RepoRowProps = {
|
||||
// Only fullName is required
|
||||
repository: Partial<Repository> & Pick<Repository, 'fullName'>;
|
||||
status?: VariantAnalysisRepoStatus;
|
||||
downloadStatus?: VariantAnalysisScannedRepositoryDownloadStatus;
|
||||
resultCount?: number;
|
||||
|
||||
interpretedResults?: AnalysisAlert[];
|
||||
@@ -71,6 +76,7 @@ export type RepoRowProps = {
|
||||
export const RepoRow = ({
|
||||
repository,
|
||||
status,
|
||||
downloadStatus,
|
||||
resultCount,
|
||||
interpretedResults,
|
||||
rawResults,
|
||||
@@ -99,6 +105,7 @@ export const RepoRow = ({
|
||||
{status === VariantAnalysisRepoStatus.InProgress && <LoadingIcon label="In progress" />}
|
||||
{!status && <WarningIcon />}
|
||||
</span>
|
||||
{downloadStatus === VariantAnalysisScannedRepositoryDownloadStatus.InProgress && <LoadingIcon label="Downloading" />}
|
||||
</TitleContainer>
|
||||
{isExpanded && status &&
|
||||
<AnalyzedRepoItemContent status={status} interpretedResults={interpretedResults} rawResults={rawResults} />}
|
||||
|
||||
@@ -5,10 +5,9 @@ import { ToVariantAnalysisMessage } from '../../pure/interface-types';
|
||||
import {
|
||||
VariantAnalysis as VariantAnalysisDomainModel,
|
||||
VariantAnalysisQueryLanguage,
|
||||
VariantAnalysisRepoStatus, VariantAnalysisScannedRepositoryResult,
|
||||
VariantAnalysisRepoStatus, VariantAnalysisScannedRepositoryResult, VariantAnalysisScannedRepositoryState,
|
||||
VariantAnalysisStatus
|
||||
} from '../../remote-queries/shared/variant-analysis';
|
||||
import { VariantAnalysisContainer } from './VariantAnalysisContainer';
|
||||
import { VariantAnalysisHeader } from './VariantAnalysisHeader';
|
||||
import { VariantAnalysisOutcomePanels } from './VariantAnalysisOutcomePanels';
|
||||
import { VariantAnalysisLoading } from './VariantAnalysisLoading';
|
||||
@@ -200,7 +199,46 @@ const repositoryResults: VariantAnalysisScannedRepositoryResult[] = [
|
||||
}
|
||||
];
|
||||
|
||||
function getContainerContents(variantAnalysis: VariantAnalysisDomainModel) {
|
||||
type Props = {
|
||||
variantAnalysis?: VariantAnalysisDomainModel;
|
||||
repoStates?: VariantAnalysisScannedRepositoryState[];
|
||||
repoResults?: VariantAnalysisScannedRepositoryResult[];
|
||||
}
|
||||
|
||||
export function VariantAnalysis({
|
||||
variantAnalysis: initialVariantAnalysis = variantAnalysis,
|
||||
repoStates: initialRepoStates = [],
|
||||
repoResults: initialRepoResults = repositoryResults,
|
||||
}: Props): JSX.Element {
|
||||
const [variantAnalysis, setVariantAnalysis] = useState<VariantAnalysisDomainModel>(initialVariantAnalysis);
|
||||
const [repoStates, setRepoStates] = useState<VariantAnalysisScannedRepositoryState[]>(initialRepoStates);
|
||||
const [repoResults, setRepoResults] = useState<VariantAnalysisScannedRepositoryResult[]>(initialRepoResults);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('message', (evt: MessageEvent) => {
|
||||
if (evt.origin === window.origin) {
|
||||
const msg: ToVariantAnalysisMessage = evt.data;
|
||||
if (msg.t === 'setVariantAnalysis') {
|
||||
setVariantAnalysis(msg.variantAnalysis);
|
||||
} else if (msg.t === 'setRepoResults') {
|
||||
setRepoResults(oldRepoResults => {
|
||||
const newRepoIds = msg.repoResults.map(r => r.repositoryId);
|
||||
return [...oldRepoResults.filter(v => !newRepoIds.includes(v.repositoryId)), ...msg.repoResults];
|
||||
});
|
||||
} else if (msg.t === 'setRepoStates') {
|
||||
setRepoStates(oldRepoStates => {
|
||||
const newRepoIds = msg.repoStates.map(r => r.repositoryId);
|
||||
return [...oldRepoStates.filter(v => !newRepoIds.includes(v.repositoryId)), ...msg.repoStates];
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// sanitize origin
|
||||
const origin = evt.origin.replace(/\n|\r/g, '');
|
||||
console.error(`Invalid event origin ${origin}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (variantAnalysis.actionsWorkflowRunId === undefined) {
|
||||
return <VariantAnalysisLoading />;
|
||||
}
|
||||
@@ -218,39 +256,9 @@ function getContainerContents(variantAnalysis: VariantAnalysisDomainModel) {
|
||||
/>
|
||||
<VariantAnalysisOutcomePanels
|
||||
variantAnalysis={variantAnalysis}
|
||||
repositoryResults={repositoryResults}
|
||||
repositoryStates={repoStates}
|
||||
repositoryResults={repoResults}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
type Props = {
|
||||
variantAnalysis?: VariantAnalysisDomainModel;
|
||||
}
|
||||
|
||||
export function VariantAnalysis({
|
||||
variantAnalysis: initialVariantAnalysis = variantAnalysis,
|
||||
}: Props): JSX.Element {
|
||||
const [variantAnalysis, setVariantAnalysis] = useState<VariantAnalysisDomainModel>(initialVariantAnalysis);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('message', (evt: MessageEvent) => {
|
||||
if (evt.origin === window.origin) {
|
||||
const msg: ToVariantAnalysisMessage = evt.data;
|
||||
if (msg.t === 'setVariantAnalysis') {
|
||||
setVariantAnalysis(msg.variantAnalysis);
|
||||
}
|
||||
} else {
|
||||
// sanitize origin
|
||||
const origin = evt.origin.replace(/\n|\r/g, '');
|
||||
console.error(`Invalid event origin ${origin}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<VariantAnalysisContainer>
|
||||
{getContainerContents(variantAnalysis)}
|
||||
</VariantAnalysisContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import * as React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { VariantAnalysis, VariantAnalysisScannedRepositoryResult } from '../../remote-queries/shared/variant-analysis';
|
||||
import { RepoRow } from './RepoRow';
|
||||
import {
|
||||
VariantAnalysis,
|
||||
VariantAnalysisScannedRepositoryResult,
|
||||
VariantAnalysisScannedRepositoryState
|
||||
} from '../../remote-queries/shared/variant-analysis';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
const Container = styled.div`
|
||||
@@ -12,13 +16,23 @@ const Container = styled.div`
|
||||
|
||||
export type VariantAnalysisAnalyzedReposProps = {
|
||||
variantAnalysis: VariantAnalysis;
|
||||
repositoryStates?: VariantAnalysisScannedRepositoryState[];
|
||||
repositoryResults?: VariantAnalysisScannedRepositoryResult[];
|
||||
}
|
||||
|
||||
export const VariantAnalysisAnalyzedRepos = ({
|
||||
variantAnalysis,
|
||||
repositoryStates,
|
||||
repositoryResults,
|
||||
}: VariantAnalysisAnalyzedReposProps) => {
|
||||
const repositoryStateById = useMemo(() => {
|
||||
const map = new Map<number, VariantAnalysisScannedRepositoryState>();
|
||||
repositoryStates?.forEach((repository) => {
|
||||
map.set(repository.repositoryId, repository);
|
||||
});
|
||||
return map;
|
||||
}, [repositoryStates]);
|
||||
|
||||
const repositoryResultsById = useMemo(() => {
|
||||
const map = new Map<number, VariantAnalysisScannedRepositoryResult>();
|
||||
repositoryResults?.forEach((repository) => {
|
||||
@@ -30,6 +44,7 @@ export const VariantAnalysisAnalyzedRepos = ({
|
||||
return (
|
||||
<Container>
|
||||
{variantAnalysis.scannedRepos?.map(repository => {
|
||||
const state = repositoryStateById.get(repository.repository.id);
|
||||
const results = repositoryResultsById.get(repository.repository.id);
|
||||
|
||||
return (
|
||||
@@ -37,6 +52,7 @@ export const VariantAnalysisAnalyzedRepos = ({
|
||||
key={repository.repository.id}
|
||||
repository={repository.repository}
|
||||
status={repository.analysisStatus}
|
||||
downloadStatus={state?.downloadStatus}
|
||||
resultCount={repository.resultCount}
|
||||
interpretedResults={results?.interpretedResults}
|
||||
rawResults={results?.rawResults}
|
||||
|
||||
@@ -2,13 +2,18 @@ import * as React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { VSCodeBadge, VSCodePanels, VSCodePanelTab, VSCodePanelView } from '@vscode/webview-ui-toolkit/react';
|
||||
import { formatDecimal } from '../../pure/number';
|
||||
import { VariantAnalysis, VariantAnalysisScannedRepositoryResult } from '../../remote-queries/shared/variant-analysis';
|
||||
import {
|
||||
VariantAnalysis,
|
||||
VariantAnalysisScannedRepositoryResult,
|
||||
VariantAnalysisScannedRepositoryState
|
||||
} from '../../remote-queries/shared/variant-analysis';
|
||||
import { VariantAnalysisAnalyzedRepos } from './VariantAnalysisAnalyzedRepos';
|
||||
import { Alert } from '../common';
|
||||
import { VariantAnalysisSkippedRepositoriesTab } from './VariantAnalysisSkippedRepositoriesTab';
|
||||
|
||||
export type VariantAnalysisOutcomePanelProps = {
|
||||
variantAnalysis: VariantAnalysis;
|
||||
repositoryStates?: VariantAnalysisScannedRepositoryState[];
|
||||
repositoryResults?: VariantAnalysisScannedRepositoryResult[];
|
||||
};
|
||||
|
||||
@@ -34,6 +39,7 @@ const WarningsContainer = styled.div`
|
||||
|
||||
export const VariantAnalysisOutcomePanels = ({
|
||||
variantAnalysis,
|
||||
repositoryStates,
|
||||
repositoryResults,
|
||||
}: VariantAnalysisOutcomePanelProps) => {
|
||||
const noCodeqlDbRepos = variantAnalysis.skippedRepos?.noCodeqlDbRepos;
|
||||
@@ -64,7 +70,11 @@ export const VariantAnalysisOutcomePanels = ({
|
||||
return (
|
||||
<>
|
||||
{warnings}
|
||||
<VariantAnalysisAnalyzedRepos variantAnalysis={variantAnalysis} repositoryResults={repositoryResults} />
|
||||
<VariantAnalysisAnalyzedRepos
|
||||
variantAnalysis={variantAnalysis}
|
||||
repositoryStates={repositoryStates}
|
||||
repositoryResults={repositoryResults}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -89,7 +99,13 @@ export const VariantAnalysisOutcomePanels = ({
|
||||
<VSCodeBadge appearance="secondary">{formatDecimal(noCodeqlDbRepos.repositoryCount)}</VSCodeBadge>
|
||||
</Tab>
|
||||
)}
|
||||
<VSCodePanelView><VariantAnalysisAnalyzedRepos variantAnalysis={variantAnalysis} repositoryResults={repositoryResults} /></VSCodePanelView>
|
||||
<VSCodePanelView>
|
||||
<VariantAnalysisAnalyzedRepos
|
||||
variantAnalysis={variantAnalysis}
|
||||
repositoryStates={repositoryStates}
|
||||
repositoryResults={repositoryResults}
|
||||
/>
|
||||
</VSCodePanelView>
|
||||
{notFoundRepos?.repositoryCount &&
|
||||
<VSCodePanelView>
|
||||
<VariantAnalysisSkippedRepositoriesTab
|
||||
|
||||
Reference in New Issue
Block a user