Compare commits

...

4 Commits
main ... master

Author SHA1 Message Date
Michael Hohn
495b52661e add viewer configuration
Some checks failed
Run CLI tests / Find Nightly Release (push) Has been cancelled
Run CLI tests / Set Matrix for cli-test (push) Has been cancelled
Run CLI tests / CLI Test (push) Has been cancelled
Run CLI tests / Report failure on the default branch (push) Has been cancelled
Update Node version / Create PR (push) Has been cancelled
Release / Release (push) Has been cancelled
Release / Publish to VS Code Marketplace (push) Has been cancelled
Release / Publish to Open VSX Registry (push) Has been cancelled
Bump CLI version / Build (push) Has been cancelled
Code Scanning - CodeQL / codeql (push) Has been cancelled
2025-08-19 11:24:15 -07:00
Michael Hohn
9a6aa52a40 fix: reconciled status names between server/agent/vscode-codeql
Some checks failed
Update Node version / Create PR (push) Has been cancelled
Run CLI tests / Find Nightly Release (push) Has been cancelled
Run CLI tests / Set Matrix for cli-test (push) Has been cancelled
Run CLI tests / CLI Test (push) Has been cancelled
Run CLI tests / Report failure on the default branch (push) Has been cancelled
Code Scanning - CodeQL / codeql (push) Has been cancelled
Bump CLI version / Build (push) Has been cancelled
2025-03-14 12:45:36 -07:00
Michael Hohn
c106903f01 wip: update settings, push new images 2025-02-20 10:30:22 -08:00
Nicolas Will
d40cda150c WIP: standalone MRVA 2024-07-01 18:20:23 +02:00
18 changed files with 203 additions and 263 deletions

View File

@@ -111,4 +111,10 @@
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true, "editor.formatOnSave": true,
}, },
"github.copilot.advanced": {
},
"codeQL.variantAnalysis.enableGhecDr": true,
"github-enterprise.uri": "http://server:8080/"
} }

View File

@@ -120,7 +120,7 @@
"gulp-esbuild": "^0.12.0", "gulp-esbuild": "^0.12.0",
"gulp-replace": "^1.1.3", "gulp-replace": "^1.1.3",
"gulp-typescript": "^5.0.1", "gulp-typescript": "^5.0.1",
"husky": "^9.0.11", "husky": "^9.1.7",
"jest": "^29.0.3", "jest": "^29.0.3",
"jest-environment-jsdom": "^29.0.3", "jest-environment-jsdom": "^29.0.3",
"jest-runner-vscode": "^3.0.1", "jest-runner-vscode": "^3.0.1",
@@ -17688,12 +17688,12 @@
} }
}, },
"node_modules/husky": { "node_modules/husky": {
"version": "9.0.11", "version": "9.1.7",
"resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
"integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
"dev": true, "dev": true,
"bin": { "bin": {
"husky": "bin.mjs" "husky": "bin.js"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=18"

View File

@@ -339,13 +339,6 @@
"title": "Variant analysis", "title": "Variant analysis",
"order": 5, "order": 5,
"properties": { "properties": {
"codeQL.variantAnalysis.controllerRepo": {
"type": "string",
"default": "",
"pattern": "^$|^(?:[a-zA-Z0-9]+-)*[a-zA-Z0-9]+/[a-zA-Z0-9-_]+$",
"patternErrorMessage": "Please enter a valid GitHub repository",
"markdownDescription": "[For internal use only] The name of the GitHub repository in which the GitHub Actions workflow is run when using the \"Run Variant Analysis\" command. The repository should be of the form `<owner>/<repo>`)."
},
"codeQL.variantAnalysis.defaultResultsFilter": { "codeQL.variantAnalysis.defaultResultsFilter": {
"type": "string", "type": "string",
"default": "all", "default": "all",
@@ -1931,11 +1924,6 @@
{ {
"view": "codeQLEvalLogViewer", "view": "codeQLEvalLogViewer",
"contents": "Run the 'Show Evaluator Log (UI)' command on a CodeQL query run in the Query History view." "contents": "Run the 'Show Evaluator Log (UI)' command on a CodeQL query run in the Query History view."
},
{
"view": "codeQLVariantAnalysisRepositories",
"contents": "Set up a controller repository to start using variant analysis. [Learn more](https://codeql.github.com/docs/codeql-for-visual-studio-code/running-codeql-queries-at-scale-with-mrva#controller-repository) about controller repositories. \n[Set up controller repository](command:codeQLVariantAnalysisRepositories.setupControllerRepository)",
"when": "!config.codeQL.variantAnalysis.controllerRepo"
} }
] ]
}, },
@@ -2078,7 +2066,7 @@
"gulp-esbuild": "^0.12.0", "gulp-esbuild": "^0.12.0",
"gulp-replace": "^1.1.3", "gulp-replace": "^1.1.3",
"gulp-typescript": "^5.0.1", "gulp-typescript": "^5.0.1",
"husky": "^9.0.11", "husky": "^9.1.7",
"jest": "^29.0.3", "jest": "^29.0.3",
"jest-environment-jsdom": "^29.0.3", "jest-environment-jsdom": "^29.0.3",
"jest-runner-vscode": "^3.0.1", "jest-runner-vscode": "^3.0.1",

View File

@@ -290,7 +290,6 @@ export type DatabasePanelCommands = {
"codeQLVariantAnalysisRepositories.openConfigFile": () => Promise<void>; "codeQLVariantAnalysisRepositories.openConfigFile": () => Promise<void>;
"codeQLVariantAnalysisRepositories.addNewDatabase": () => Promise<void>; "codeQLVariantAnalysisRepositories.addNewDatabase": () => Promise<void>;
"codeQLVariantAnalysisRepositories.addNewList": () => Promise<void>; "codeQLVariantAnalysisRepositories.addNewList": () => Promise<void>;
"codeQLVariantAnalysisRepositories.setupControllerRepository": () => Promise<void>;
"codeQLVariantAnalysisRepositories.setSelectedItem": TreeViewContextSingleSelectionCommandFunction<DbTreeViewItem>; "codeQLVariantAnalysisRepositories.setSelectedItem": TreeViewContextSingleSelectionCommandFunction<DbTreeViewItem>;
"codeQLVariantAnalysisRepositories.setSelectedItemContextMenu": TreeViewContextSingleSelectionCommandFunction<DbTreeViewItem>; "codeQLVariantAnalysisRepositories.setSelectedItemContextMenu": TreeViewContextSingleSelectionCommandFunction<DbTreeViewItem>;

View File

@@ -112,7 +112,9 @@ export function hasEnterpriseUri(): boolean {
* Does the uri look like GHEC-DR? * Does the uri look like GHEC-DR?
*/ */
function isGhecDrUri(uri: Uri | undefined): boolean { function isGhecDrUri(uri: Uri | undefined): boolean {
return uri !== undefined && uri.authority.toLowerCase().endsWith(".ghe.com"); return (
uri !== undefined && !uri.authority.toLowerCase().endsWith("github.com")
);
} }
/** /**
@@ -591,27 +593,7 @@ export const NO_CACHE_CONTEXTUAL_QUERIES = new Setting(
// Settings for variant analysis // Settings for variant analysis
const VARIANT_ANALYSIS_SETTING = new Setting("variantAnalysis", ROOT_SETTING); const VARIANT_ANALYSIS_SETTING = new Setting("variantAnalysis", ROOT_SETTING);
/**
* The name of the "controller" repository that you want to use with the "Run Variant Analysis" command.
* Note: This command is only available for internal users.
*
* This setting should be a GitHub repository of the form `<owner>/<repo>`.
*/
const REMOTE_CONTROLLER_REPO = new Setting(
"controllerRepo",
VARIANT_ANALYSIS_SETTING,
);
export function getRemoteControllerRepo(): string | undefined {
return REMOTE_CONTROLLER_REPO.getValue<string>() || undefined;
}
export async function setRemoteControllerRepo(repo: string | undefined) {
await REMOTE_CONTROLLER_REPO.updateValue(repo, ConfigurationTarget.Global);
}
export interface VariantAnalysisConfig { export interface VariantAnalysisConfig {
controllerRepo: string | undefined;
showSystemDefinedRepositoryLists: boolean; showSystemDefinedRepositoryLists: boolean;
/** /**
* This uses a URL instead of a URI because the URL class is available in * This uses a URL instead of a URI because the URL class is available in
@@ -632,10 +614,6 @@ export class VariantAnalysisConfigListener
); );
} }
public get controllerRepo(): string | undefined {
return getRemoteControllerRepo();
}
public get showSystemDefinedRepositoryLists(): boolean { public get showSystemDefinedRepositoryLists(): boolean {
return !hasEnterpriseUri(); return !hasEnterpriseUri();
} }

View File

@@ -18,8 +18,6 @@ import type { DbManager } from "../db-manager";
import { DbTreeDataProvider } from "./db-tree-data-provider"; import { DbTreeDataProvider } from "./db-tree-data-provider";
import type { DbTreeViewItem } from "./db-tree-view-item"; import type { DbTreeViewItem } from "./db-tree-view-item";
import { getGitHubUrl } from "./db-tree-view-item-action"; import { getGitHubUrl } from "./db-tree-view-item-action";
import { getControllerRepo } from "../../variant-analysis/run-remote-query";
import { getErrorMessage } from "../../common/helpers-pure";
import type { DatabasePanelCommands } from "../../common/commands"; import type { DatabasePanelCommands } from "../../common/commands";
import type { App } from "../../common/app"; import type { App } from "../../common/app";
import { QueryLanguage } from "../../common/query-language"; import { QueryLanguage } from "../../common/query-language";
@@ -74,9 +72,6 @@ export class DbPanel extends DisposableObject {
this.addNewRemoteDatabase.bind(this), this.addNewRemoteDatabase.bind(this),
"codeQLVariantAnalysisRepositories.addNewList": "codeQLVariantAnalysisRepositories.addNewList":
this.addNewList.bind(this), this.addNewList.bind(this),
"codeQLVariantAnalysisRepositories.setupControllerRepository":
this.setupControllerRepository.bind(this),
"codeQLVariantAnalysisRepositories.setSelectedItem": "codeQLVariantAnalysisRepositories.setSelectedItem":
this.setSelectedItem.bind(this), this.setSelectedItem.bind(this),
"codeQLVariantAnalysisRepositories.setSelectedItemContextMenu": "codeQLVariantAnalysisRepositories.setSelectedItemContextMenu":
@@ -427,22 +422,4 @@ export class DbPanel extends DisposableObject {
await this.app.commands.execute("vscode.open", Uri.parse(githubUrl)); await this.app.commands.execute("vscode.open", Uri.parse(githubUrl));
} }
private async setupControllerRepository(): Promise<void> {
try {
// This will also validate that the controller repository is valid
await getControllerRepo(this.app.credentials);
} catch (e: unknown) {
if (e instanceof UserCancellationException) {
return;
}
void showAndLogErrorMessage(
this.app.logger,
`An error occurred while setting up the controller repository: ${getErrorMessage(
e,
)}`,
);
}
}
} }

View File

@@ -83,11 +83,6 @@ export class DbTreeDataProvider
} }
private createTree(): DbTreeViewItem[] { private createTree(): DbTreeViewItem[] {
// Returning an empty tree here will show the welcome view
if (!this.variantAnalysisConfig.controllerRepo) {
return [];
}
const dbItemsResult = this.dbManager.getDbItems(); const dbItemsResult = this.dbManager.getDbItems();
if (dbItemsResult.isFailure) { if (dbItemsResult.isFailure) {

View File

@@ -48,11 +48,6 @@ function mapVariantAnalysisDtoToDto(
): VariantAnalysisDto { ): VariantAnalysisDto {
return { return {
id: variantAnalysis.id, id: variantAnalysis.id,
controllerRepo: {
id: variantAnalysis.controllerRepo.id,
fullName: variantAnalysis.controllerRepo.fullName,
private: variantAnalysis.controllerRepo.private,
},
query: { query: {
name: variantAnalysis.query.name, name: variantAnalysis.query.name,
filePath: variantAnalysis.query.filePath, filePath: variantAnalysis.query.filePath,

View File

@@ -48,12 +48,12 @@ function mapVariantAnalysisToDomainModel(
): VariantAnalysis { ): VariantAnalysis {
return { return {
id: variantAnalysis.id, id: variantAnalysis.id,
controllerRepo: {
id: variantAnalysis.controllerRepo.id,
fullName: variantAnalysis.controllerRepo.fullName,
private: variantAnalysis.controllerRepo.private,
},
language: mapQueryLanguageToDomainModel(variantAnalysis.query.language), language: mapQueryLanguageToDomainModel(variantAnalysis.query.language),
controllerRepo: {
id: 0,
fullName: "",
private: false,
},
query: { query: {
name: variantAnalysis.query.name, name: variantAnalysis.query.name,
filePath: variantAnalysis.query.filePath, filePath: variantAnalysis.query.filePath,

View File

@@ -15,11 +15,6 @@ export interface QueryHistoryVariantAnalysisDto {
export interface VariantAnalysisDto { export interface VariantAnalysisDto {
id: number; id: number;
controllerRepo: {
id: number;
fullName: string;
private: boolean;
};
query: { query: {
name: string; name: string;
filePath: string; filePath: string;

View File

@@ -160,7 +160,7 @@ async function exportVariantAnalysisAnalysisResults(
expectedAnalysesResultsCount: number, expectedAnalysesResultsCount: number,
exportFormat: "gist" | "local", exportFormat: "gist" | "local",
commandManager: AppCommandManager, commandManager: AppCommandManager,
credentials: Credentials, _credentials: Credentials,
progress: ProgressCallback, progress: ProgressCallback,
token: CancellationToken, token: CancellationToken,
) { ) {
@@ -191,7 +191,6 @@ async function exportVariantAnalysisAnalysisResults(
markdownFiles, markdownFiles,
exportFormat, exportFormat,
commandManager, commandManager,
credentials,
progress, progress,
token, token,
); );
@@ -236,7 +235,6 @@ async function exportResults(
markdownFiles: MarkdownFile[], markdownFiles: MarkdownFile[],
exportFormat: "gist" | "local", exportFormat: "gist" | "local",
commandManager: AppCommandManager, commandManager: AppCommandManager,
credentials: Credentials,
progress?: ProgressCallback, progress?: ProgressCallback,
token?: CancellationToken, token?: CancellationToken,
) { ) {
@@ -249,7 +247,6 @@ async function exportResults(
description, description,
markdownFiles, markdownFiles,
commandManager, commandManager,
credentials,
progress, progress,
token, token,
); );
@@ -268,7 +265,6 @@ async function exportToGist(
description: string, description: string,
markdownFiles: MarkdownFile[], markdownFiles: MarkdownFile[],
commandManager: AppCommandManager, commandManager: AppCommandManager,
credentials: Credentials,
progress?: ProgressCallback, progress?: ProgressCallback,
token?: CancellationToken, token?: CancellationToken,
) { ) {
@@ -291,7 +287,7 @@ async function exportToGist(
{} as { [key: string]: { content: string } }, {} as { [key: string]: { content: string } },
); );
const gistUrl = await createGist(credentials, description, gistFiles); const gistUrl = await createGist(description, gistFiles);
if (gistUrl) { if (gistUrl) {
// This needs to use .then to ensure we aren't keeping the progress notification open. We shouldn't await the // This needs to use .then to ensure we aren't keeping the progress notification open. We shouldn't await the
// "Open gist" button click. // "Open gist" button click.

View File

@@ -1,5 +1,4 @@
import type { OctokitResponse } from "@octokit/types/dist-types"; import { getGitHubInstanceUrl } from "../../config";
import type { Credentials } from "../../common/authentication";
import type { VariantAnalysisSubmission } from "../shared/variant-analysis"; import type { VariantAnalysisSubmission } from "../shared/variant-analysis";
import type { import type {
VariantAnalysis, VariantAnalysis,
@@ -7,84 +6,142 @@ import type {
VariantAnalysisSubmissionRequest, VariantAnalysisSubmissionRequest,
} from "./variant-analysis"; } from "./variant-analysis";
import type { Repository } from "./repository"; import type { Repository } from "./repository";
import { extLogger } from "../../common/logging/vscode";
export async function submitVariantAnalysis( function getOctokitBaseUrl(): string {
credentials: Credentials, let apiUrl = getGitHubInstanceUrl().toString();
submissionDetails: VariantAnalysisSubmission, if (apiUrl.endsWith("/")) {
): Promise<VariantAnalysis> { apiUrl = apiUrl.slice(0, -1);
const octokit = await credentials.getOctokit(); }
if (apiUrl.startsWith("https://")) {
const { actionRepoRef, language, pack, databases, controllerRepoId } = apiUrl = apiUrl.replace("https://", "http://");
submissionDetails; }
return apiUrl;
const data: VariantAnalysisSubmissionRequest = {
action_repo_ref: actionRepoRef,
language,
query_pack: pack,
repositories: databases.repositories,
repository_lists: databases.repositoryLists,
repository_owners: databases.repositoryOwners,
};
const response: OctokitResponse<VariantAnalysis> = await octokit.request(
"POST /repositories/:controllerRepoId/code-scanning/codeql/variant-analyses",
{
controllerRepoId,
data,
},
);
return response.data;
} }
export async function submitVariantAnalysis(
submissionDetails: VariantAnalysisSubmission,
): Promise<VariantAnalysis> {
try {
console.log("Getting base URL...");
const baseUrl = getOctokitBaseUrl();
void extLogger.log(`Base URL: ${baseUrl}`);
const { actionRepoRef, language, pack, databases, controllerRepoId } =
submissionDetails;
const data: VariantAnalysisSubmissionRequest = {
action_repo_ref: actionRepoRef,
language,
query_pack: pack,
repositories: databases.repositories,
repository_lists: databases.repositoryLists,
repository_owners: databases.repositoryOwners,
};
void extLogger.log(
`Sending fetch request with data: ${JSON.stringify(data)}`,
);
void extLogger.log(
`Fetch request URL: ${baseUrl}/repositories/${controllerRepoId}/code-scanning/codeql/variant-analyses`,
);
const response = await fetch(
`${baseUrl}/repositories/${controllerRepoId}/code-scanning/codeql/variant-analyses`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
},
);
void extLogger.log(`Response status: ${response.status}`);
if (!response.ok) {
throw new Error(
`Error submitting variant analysis: ${response.statusText}`,
);
}
const responseData = await response.json();
void extLogger.log(`Response data: ${responseData}`);
return responseData;
} catch (error) {
void extLogger.log(`Error: ${error}`);
throw error;
}
}
export async function getVariantAnalysis( export async function getVariantAnalysis(
credentials: Credentials,
controllerRepoId: number, controllerRepoId: number,
variantAnalysisId: number, variantAnalysisId: number,
): Promise<VariantAnalysis> { ): Promise<VariantAnalysis> {
const octokit = await credentials.getOctokit(); const baseUrl = getOctokitBaseUrl();
const response: OctokitResponse<VariantAnalysis> = await octokit.request( const response = await fetch(
"GET /repositories/:controllerRepoId/code-scanning/codeql/variant-analyses/:variantAnalysisId", `${baseUrl}/repositories/${controllerRepoId}/code-scanning/codeql/variant-analyses/${variantAnalysisId}`,
{ {
controllerRepoId, method: "GET",
variantAnalysisId, headers: {
"Content-Type": "application/json",
},
}, },
); );
return response.data; if (!response.ok) {
throw new Error(`Error getting variant analysis: ${response.statusText}`);
}
return response.json();
} }
export async function getVariantAnalysisRepo( export async function getVariantAnalysisRepo(
credentials: Credentials,
controllerRepoId: number, controllerRepoId: number,
variantAnalysisId: number, variantAnalysisId: number,
repoId: number, repoId: number,
): Promise<VariantAnalysisRepoTask> { ): Promise<VariantAnalysisRepoTask> {
const octokit = await credentials.getOctokit(); const baseUrl = getOctokitBaseUrl();
const response: OctokitResponse<VariantAnalysisRepoTask> = const response = await fetch(
await octokit.request( `${baseUrl}/repositories/${controllerRepoId}/code-scanning/codeql/variant-analyses/${variantAnalysisId}/repositories/${repoId}`,
"GET /repositories/:controllerRepoId/code-scanning/codeql/variant-analyses/:variantAnalysisId/repositories/:repoId", {
{ method: "GET",
controllerRepoId, headers: {
variantAnalysisId, "Content-Type": "application/json",
repoId,
}, },
); },
);
return response.data; if (!response.ok) {
throw new Error(
`Error getting variant analysis repo: ${response.statusText}`,
);
}
return response.json();
} }
export async function getRepositoryFromNwo( export async function getRepositoryFromNwo(
credentials: Credentials,
owner: string, owner: string,
repo: string, repo: string,
): Promise<Repository> { ): Promise<Repository> {
const octokit = await credentials.getOctokit(); const baseUrl = getOctokitBaseUrl();
const response = await octokit.rest.repos.get({ owner, repo }); const response = await fetch(`${baseUrl}/repos/${owner}/${repo}`, {
return response.data as Repository; method: "GET",
headers: {
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error(`Error getting repository: ${response.statusText}`);
}
return response.json();
} }
/** /**
@@ -92,22 +149,29 @@ export async function getRepositoryFromNwo(
* Returns the URL of the created gist. * Returns the URL of the created gist.
*/ */
export async function createGist( export async function createGist(
credentials: Credentials,
description: string, description: string,
files: { [key: string]: { content: string } }, files: { [key: string]: { content: string } },
): Promise<string | undefined> { ): Promise<string | undefined> {
const octokit = await credentials.getOctokit(); const baseUrl = getOctokitBaseUrl();
const response = await octokit.request("POST /gists", {
description, const response = await fetch(`${baseUrl}/gists`, {
files, method: "POST",
public: false, headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
description,
files,
public: false,
}),
}); });
if (response.status >= 300) {
if (!response.ok) {
throw new Error( throw new Error(
`Error exporting variant analysis results: ${response.status} ${ `Error creating gist: ${response.status} ${response.statusText}`,
response?.data || ""
}`,
); );
} }
return response.data.html_url;
const data = await response.json();
return data.html_url;
} }

View File

@@ -1,5 +1,5 @@
import type { CancellationToken } from "vscode"; import type { CancellationToken } from "vscode";
import { Uri, window } from "vscode"; import { Uri } from "vscode";
import { join, sep, basename, relative } from "path"; import { join, sep, basename, relative } from "path";
import { dump, load } from "js-yaml"; import { dump, load } from "js-yaml";
import { copy, writeFile, readFile, mkdirp } from "fs-extra"; import { copy, writeFile, readFile, mkdirp } from "fs-extra";
@@ -7,26 +7,17 @@ import type { DirectoryResult } from "tmp-promise";
import { dir, tmpName } from "tmp-promise"; import { dir, tmpName } from "tmp-promise";
import { tmpDir } from "../tmp-dir"; import { tmpDir } from "../tmp-dir";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders"; import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import type { Credentials } from "../common/authentication";
import type { CodeQLCliServer } from "../codeql-cli/cli"; import type { CodeQLCliServer } from "../codeql-cli/cli";
import { extLogger } from "../common/logging/vscode"; import { extLogger } from "../common/logging/vscode";
import { import { getActionBranch } from "../config";
getActionBranch,
getRemoteControllerRepo,
setRemoteControllerRepo,
} from "../config";
import type { ProgressCallback } from "../common/vscode/progress"; import type { ProgressCallback } from "../common/vscode/progress";
import { UserCancellationException } from "../common/vscode/progress"; import { UserCancellationException } from "../common/vscode/progress";
import type { RequestError } from "@octokit/types/dist-types";
import type { QueryMetadata } from "../common/interface-types"; import type { QueryMetadata } from "../common/interface-types";
import { getErrorMessage, REPO_REGEX } from "../common/helpers-pure";
import { getRepositoryFromNwo } from "./gh-api/gh-api-client";
import type { RepositorySelection } from "./repository-selection"; import type { RepositorySelection } from "./repository-selection";
import { import {
getRepositorySelection, getRepositorySelection,
isValidSelection, isValidSelection,
} from "./repository-selection"; } from "./repository-selection";
import type { Repository } from "./shared/repository";
import type { DbManager } from "../databases/db-manager"; import type { DbManager } from "../databases/db-manager";
import { import {
getQlPackFilePath, getQlPackFilePath,
@@ -285,13 +276,11 @@ interface PreparedRemoteQuery {
base64Pack: string; base64Pack: string;
modelPacks: ModelPackDetails[]; modelPacks: ModelPackDetails[];
repoSelection: RepositorySelection; repoSelection: RepositorySelection;
controllerRepo: Repository;
queryStartTime: number; queryStartTime: number;
} }
export async function prepareRemoteQueryRun( export async function prepareRemoteQueryRun(
cliServer: CodeQLCliServer, cliServer: CodeQLCliServer,
credentials: Credentials,
qlPackDetails: QlPackDetails, qlPackDetails: QlPackDetails,
progress: ProgressCallback, progress: ProgressCallback,
token: CancellationToken, token: CancellationToken,
@@ -322,8 +311,6 @@ export async function prepareRemoteQueryRun(
message: "Determining controller repo", message: "Determining controller repo",
}); });
const controllerRepo = await getControllerRepo(credentials);
progress({ progress({
maxStep: 4, maxStep: 4,
step: 3, step: 3,
@@ -367,7 +354,6 @@ export async function prepareRemoteQueryRun(
base64Pack: generatedPack.base64Pack, base64Pack: generatedPack.base64Pack,
modelPacks: generatedPack.modelPacks, modelPacks: generatedPack.modelPacks,
repoSelection, repoSelection,
controllerRepo,
queryStartTime, queryStartTime,
}; };
} }
@@ -494,84 +480,6 @@ export function getQueryName(
return queryMetadata?.name ?? basename(queryFilePath); return queryMetadata?.name ?? basename(queryFilePath);
} }
export async function getControllerRepo(
credentials: Credentials,
): Promise<Repository> {
// Get the controller repo from the config, if it exists.
// If it doesn't exist, prompt the user to enter it, check
// whether the repo exists, and save the nwo to the config.
let shouldSetControllerRepo = false;
let controllerRepoNwo: string | undefined;
controllerRepoNwo = getRemoteControllerRepo();
if (!controllerRepoNwo || !REPO_REGEX.test(controllerRepoNwo)) {
void extLogger.log(
controllerRepoNwo
? "Invalid controller repository name."
: "No controller repository defined.",
);
controllerRepoNwo = await window.showInputBox({
title:
"Controller repository in which to run GitHub Actions workflows for variant analyses",
placeHolder: "<owner>/<repo>",
prompt:
"Enter the name of a GitHub repository in the format <owner>/<repo>. You can change this in the extension settings.",
ignoreFocusOut: true,
});
if (!controllerRepoNwo) {
throw new UserCancellationException("No controller repository entered.");
} else if (!REPO_REGEX.test(controllerRepoNwo)) {
// Check if user entered invalid input
throw new UserCancellationException(
"Invalid repository format. Must be a valid GitHub repository in the format <owner>/<repo>.",
);
}
shouldSetControllerRepo = true;
}
void extLogger.log(`Using controller repository: ${controllerRepoNwo}`);
const controllerRepo = await getControllerRepoFromApi(
credentials,
controllerRepoNwo,
);
if (shouldSetControllerRepo) {
void extLogger.log(
`Setting the controller repository as: ${controllerRepoNwo}`,
);
await setRemoteControllerRepo(controllerRepoNwo);
}
return controllerRepo;
}
async function getControllerRepoFromApi(
credentials: Credentials,
nwo: string,
): Promise<Repository> {
const [owner, repo] = nwo.split("/");
try {
const controllerRepo = await getRepositoryFromNwo(credentials, owner, repo);
void extLogger.log(`Controller repository ID: ${controllerRepo.id}`);
return {
id: controllerRepo.id,
fullName: controllerRepo.full_name,
private: controllerRepo.private,
};
} catch (e) {
if ((e as RequestError).status === 404) {
throw new Error(`Controller repository "${owner}/${repo}" not found`);
} else {
throw new Error(
`Error getting controller repository "${owner}/${repo}": ${getErrorMessage(
e,
)}`,
);
}
}
}
function removeWorkspaceRefs(qlpack: QlPackFile) { function removeWorkspaceRefs(qlpack: QlPackFile) {
if (!qlpack.dependencies) { if (!qlpack.dependencies) {
return; return;

View File

@@ -373,16 +373,19 @@ export class VariantAnalysisManager
); );
} }
// log to extLogger
void this.app.logger.log(
`Running variant analysis with query: ${queryName}, language: ${variantAnalysisLanguage}`,
);
const { const {
actionBranch, actionBranch,
base64Pack, base64Pack,
modelPacks, modelPacks,
repoSelection, repoSelection,
controllerRepo,
queryStartTime, queryStartTime,
} = await prepareRemoteQueryRun( } = await prepareRemoteQueryRun(
this.cliServer, this.cliServer,
this.app.credentials,
qlPackDetails, qlPackDetails,
progress, progress,
token, token,
@@ -399,12 +402,15 @@ export class VariantAnalysisManager
count: qlPackDetails.queryFiles.length, count: qlPackDetails.queryFiles.length,
}; };
// log that submitting
void this.app.logger.log("Submitting variant analysis");
const variantAnalysisSubmission: VariantAnalysisSubmission = { const variantAnalysisSubmission: VariantAnalysisSubmission = {
startTime: queryStartTime, startTime: queryStartTime,
actionRepoRef: actionBranch, actionRepoRef: actionBranch,
controllerRepoId: controllerRepo.id,
language: variantAnalysisLanguage, language: variantAnalysisLanguage,
pack: base64Pack, pack: base64Pack,
controllerRepoId: 0,
query: { query: {
name: queryName, name: queryName,
filePath: firstQueryFile, filePath: firstQueryFile,
@@ -422,7 +428,6 @@ export class VariantAnalysisManager
let variantAnalysisResponse: ApiVariantAnalysis; let variantAnalysisResponse: ApiVariantAnalysis;
try { try {
variantAnalysisResponse = await submitVariantAnalysis( variantAnalysisResponse = await submitVariantAnalysis(
this.app.credentials,
variantAnalysisSubmission, variantAnalysisSubmission,
); );
} catch (e: unknown) { } catch (e: unknown) {
@@ -431,9 +436,17 @@ export class VariantAnalysisManager
e instanceof RequestError && e instanceof RequestError &&
handleRequestError(e, this.config.githubUrl, this.app.logger) handleRequestError(e, this.config.githubUrl, this.app.logger)
) { ) {
// log
void this.app.logger.log(
`Error submitting variant analysis: ${getErrorMessage(e)}`,
);
return undefined; return undefined;
} }
// throwing
void this.app.logger.log(
`Error submitting variant analysis: ${getErrorMessage(e)}`,
);
throw e; throw e;
} }
@@ -806,8 +819,7 @@ export class VariantAnalysisManager
let repoTask: VariantAnalysisRepositoryTask; let repoTask: VariantAnalysisRepositoryTask;
try { try {
const repoTaskResponse = await getVariantAnalysisRepo( const repoTaskResponse = await getVariantAnalysisRepo(
this.app.credentials, 0,
variantAnalysis.controllerRepo.id,
variantAnalysis.id, variantAnalysis.id,
scannedRepo.repository.id, scannedRepo.repository.id,
); );

View File

@@ -62,7 +62,6 @@ export class VariantAnalysisMonitor extends DisposableObject {
try { try {
await this._monitorVariantAnalysis( await this._monitorVariantAnalysis(
variantAnalysis.id, variantAnalysis.id,
variantAnalysis.controllerRepo.id,
variantAnalysis.executionStartTime, variantAnalysis.executionStartTime,
variantAnalysis.query.name, variantAnalysis.query.name,
variantAnalysis.language, variantAnalysis.language,
@@ -74,7 +73,6 @@ export class VariantAnalysisMonitor extends DisposableObject {
private async _monitorVariantAnalysis( private async _monitorVariantAnalysis(
variantAnalysisId: number, variantAnalysisId: number,
controllerRepoId: number,
executionStartTime: number, executionStartTime: number,
queryName: string, queryName: string,
language: QueryLanguage, language: QueryLanguage,
@@ -97,11 +95,7 @@ export class VariantAnalysisMonitor extends DisposableObject {
let variantAnalysisSummary: ApiVariantAnalysis; let variantAnalysisSummary: ApiVariantAnalysis;
try { try {
variantAnalysisSummary = await getVariantAnalysis( variantAnalysisSummary = await getVariantAnalysis(0, variantAnalysisId);
this.app.credentials,
controllerRepoId,
variantAnalysisId,
);
} catch (e) { } catch (e) {
const errorMessage = getErrorMessage(e); const errorMessage = getErrorMessage(e);

View File

@@ -20,7 +20,7 @@ export default defineConfig({
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: { use: {
/* Base URL to use in actions like `await page.goto('/')`. */ /* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "http://localhost:8080", baseURL: "http://server:8080",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry", trace: "on-first-retry",

6
package-lock.json generated Normal file
View File

@@ -0,0 +1,6 @@
{
"name": "vscode-codeql",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

View File

@@ -0,0 +1,27 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"typescript.tsdk": "./extensions/ql-vscode/node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"terminal.integrated.env.linux": {
"LANG": "en-US",
"TZ": "UTC"
},
"terminal.integrated.env.osx": {
"LANG": "en-US",
"TZ": "UTC"
},
"terminal.integrated.env.windows": {
"LANG": "en-US",
"TZ": "UTC"
},
"github.copilot.advanced": {},
"github-enterprise.uri": "http://server:8080",
"sarif-viewer.connectToGithubCodeScanning": "off"
}
}