Skip to content
Merged
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
153 changes: 79 additions & 74 deletions extensions/ql-vscode/src/remote-queries/run-remote-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,19 @@ export interface QlPack {
*/
const QUERY_PACK_NAME = 'codeql-remote/query';

export interface GeneratedQueryPack {
base64Pack: string,
language: string
}

/**
* Two possibilities:
* 1. There is no qlpack.yml in this directory. Assume this is a lone query and generate a synthetic qlpack for it.
* 2. There is a qlpack.yml in this directory. Assume this is a query pack and use the yml to pack the query before uploading it.
*
* @returns the entire qlpack as a base64 string.
*/
async function generateQueryPack(cliServer: cli.CodeQLCliServer, queryFile: string, queryPackDir: string): Promise<{
base64Pack: string,
language: string
}> {
async function generateQueryPack(cliServer: cli.CodeQLCliServer, queryFile: string, queryPackDir: string): Promise<GeneratedQueryPack> {
const originalPackRoot = await findPackRoot(queryFile);
const packRelativePath = path.relative(originalPackRoot, queryFile);
const targetQueryFileName = path.join(queryPackDir, packRelativePath);
Expand Down Expand Up @@ -181,7 +183,6 @@ export async function prepareRemoteQueryRun(
cliServer: cli.CodeQLCliServer,
credentials: Credentials,
uri: Uri | undefined,
queryPackDir: string,
progress: ProgressCallback,
token: CancellationToken,
) {
Expand Down Expand Up @@ -225,7 +226,17 @@ export async function prepareRemoteQueryRun(
throw new UserCancellationException('Cancelled');
}

const { base64Pack, language } = await generateQueryPack(cliServer, queryFile, queryPackDir);
const { remoteQueryDir, queryPackDir } = await createRemoteQueriesTempDirectory();

let pack: GeneratedQueryPack;

try {
pack = await generateQueryPack(cliServer, queryFile, queryPackDir);
} finally {
await remoteQueryDir.cleanup();
}

const { base64Pack, language } = pack;

if (token.isCancellationRequested) {
throw new UserCancellationException('Cancelled');
Expand Down Expand Up @@ -266,87 +277,81 @@ export async function runRemoteQuery(
} or later.`);
}

const { remoteQueryDir, queryPackDir } = await createRemoteQueriesTempDirectory();
try {
const {
actionBranch,
base64Pack,
repoSelection,
queryFile,
queryMetadata,
controllerRepo,
queryStartTime,
language,
} = await prepareRemoteQueryRun(cliServer, credentials, uri, queryPackDir, progress, token);
const {
actionBranch,
base64Pack,
repoSelection,
queryFile,
queryMetadata,
controllerRepo,
queryStartTime,
language,
} = await prepareRemoteQueryRun(cliServer, credentials, uri, progress, token);

if (isVariantAnalysisLiveResultsEnabled()) {
const queryName = getQueryName(queryMetadata, queryFile);
const variantAnalysisLanguage = parseVariantAnalysisQueryLanguage(language);
if (variantAnalysisLanguage === undefined) {
throw new UserCancellationException(`Found unsupported language: ${language}`);
}
if (isVariantAnalysisLiveResultsEnabled()) {
const queryName = getQueryName(queryMetadata, queryFile);
const variantAnalysisLanguage = parseVariantAnalysisQueryLanguage(language);
if (variantAnalysisLanguage === undefined) {
throw new UserCancellationException(`Found unsupported language: ${language}`);
}

const queryText = await fs.readFile(queryFile, 'utf8');

const variantAnalysisSubmission: VariantAnalysisSubmission = {
startTime: queryStartTime,
actionRepoRef: actionBranch,
controllerRepoId: controllerRepo.id,
query: {
name: queryName,
filePath: queryFile,
pack: base64Pack,
language: variantAnalysisLanguage,
text: queryText,
},
databases: {
repositories: repoSelection.repositories,
repositoryLists: repoSelection.repositoryLists,
repositoryOwners: repoSelection.owners
}
};
const queryText = await fs.readFile(queryFile, 'utf8');

const variantAnalysisResponse = await ghApiClient.submitVariantAnalysis(
credentials,
variantAnalysisSubmission
);
const variantAnalysisSubmission: VariantAnalysisSubmission = {
startTime: queryStartTime,
actionRepoRef: actionBranch,
controllerRepoId: controllerRepo.id,
query: {
name: queryName,
filePath: queryFile,
pack: base64Pack,
language: variantAnalysisLanguage,
text: queryText,
},
databases: {
repositories: repoSelection.repositories,
repositoryLists: repoSelection.repositoryLists,
repositoryOwners: repoSelection.owners
}
};

const processedVariantAnalysis = processVariantAnalysis(variantAnalysisSubmission, variantAnalysisResponse);
const variantAnalysisResponse = await ghApiClient.submitVariantAnalysis(
credentials,
variantAnalysisSubmission
);

await variantAnalysisManager.onVariantAnalysisSubmitted(processedVariantAnalysis);
const processedVariantAnalysis = processVariantAnalysis(variantAnalysisSubmission, variantAnalysisResponse);

void logger.log(`Variant analysis:\n${JSON.stringify(processedVariantAnalysis, null, 2)}`);
await variantAnalysisManager.onVariantAnalysisSubmitted(processedVariantAnalysis);

void showAndLogInformationMessage(`Variant analysis ${processedVariantAnalysis.query.name} submitted for processing`);
void logger.log(`Variant analysis:\n${JSON.stringify(processedVariantAnalysis, null, 2)}`);

void commands.executeCommand('codeQL.openVariantAnalysisView', processedVariantAnalysis.id);
void commands.executeCommand('codeQL.monitorVariantAnalysis', processedVariantAnalysis);
void showAndLogInformationMessage(`Variant analysis ${processedVariantAnalysis.query.name} submitted for processing`);

return { variantAnalysis: processedVariantAnalysis };
} else {
const apiResponse = await runRemoteQueriesApiRequest(credentials, actionBranch, language, repoSelection, controllerRepo, base64Pack);
void commands.executeCommand('codeQL.openVariantAnalysisView', processedVariantAnalysis.id);
void commands.executeCommand('codeQL.monitorVariantAnalysis', processedVariantAnalysis);

if (!apiResponse) {
return;
}
return { variantAnalysis: processedVariantAnalysis };
} else {
const apiResponse = await runRemoteQueriesApiRequest(credentials, actionBranch, language, repoSelection, controllerRepo, base64Pack);

const workflowRunId = apiResponse.workflow_run_id;
const repositoryCount = apiResponse.repositories_queried.length;
const remoteQuery = await buildRemoteQueryEntity(
queryFile,
queryMetadata,
controllerRepo,
queryStartTime,
workflowRunId,
language,
repositoryCount);

// don't return the path because it has been deleted
return { query: remoteQuery };
if (!apiResponse) {
return;
}

} finally {
await remoteQueryDir.cleanup();
const workflowRunId = apiResponse.workflow_run_id;
const repositoryCount = apiResponse.repositories_queried.length;
const remoteQuery = await buildRemoteQueryEntity(
queryFile,
queryMetadata,
controllerRepo,
queryStartTime,
workflowRunId,
language,
repositoryCount);

// don't return the path because it has been deleted
return { query: remoteQuery };
}
}

Expand Down