Skip to content

Commit 208efb5

Browse files
authored
Merge pull request #3079 from github/koesie10/update-github-databases
Add prompt for updating GitHub databases
2 parents 560008c + 4f988de commit 208efb5

File tree

6 files changed

+954
-18
lines changed

6 files changed

+954
-18
lines changed

extensions/ql-vscode/package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,19 @@
440440
"Never download a GitHub databases when a workspace is opened."
441441
],
442442
"description": "Ask to download a GitHub database when a workspace is opened."
443+
},
444+
"codeQL.githubDatabase.update": {
445+
"type": "string",
446+
"default": "ask",
447+
"enum": [
448+
"ask",
449+
"never"
450+
],
451+
"enumDescriptions": [
452+
"Ask to download an updated GitHub database when a new version is available.",
453+
"Never download an updated GitHub database when a new version is available."
454+
],
455+
"description": "Ask to download an updated GitHub database when a new version is available."
443456
}
444457
}
445458
},

extensions/ql-vscode/src/config.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,13 +788,23 @@ const GITHUB_DATABASE_DOWNLOAD = new Setting(
788788
const GitHubDatabaseDownloadValues = ["ask", "never"] as const;
789789
type GitHubDatabaseDownload = (typeof GitHubDatabaseDownloadValues)[number];
790790

791+
const GITHUB_DATABASE_UPDATE = new Setting("update", GITHUB_DATABASE_SETTING);
792+
793+
const GitHubDatabaseUpdateValues = ["ask", "never"] as const;
794+
type GitHubDatabaseUpdate = (typeof GitHubDatabaseUpdateValues)[number];
795+
791796
export interface GitHubDatabaseConfig {
792797
enable: boolean;
793798
download: GitHubDatabaseDownload;
799+
update: GitHubDatabaseUpdate;
794800
setDownload(
795801
value: GitHubDatabaseDownload,
796802
target?: ConfigurationTarget,
797803
): Promise<void>;
804+
setUpdate(
805+
value: GitHubDatabaseUpdate,
806+
target?: ConfigurationTarget,
807+
): Promise<void>;
798808
}
799809

800810
export class GitHubDatabaseConfigListener
@@ -817,10 +827,22 @@ export class GitHubDatabaseConfigListener
817827
return GitHubDatabaseDownloadValues.includes(value) ? value : "ask";
818828
}
819829

830+
public get update(): GitHubDatabaseUpdate {
831+
const value = GITHUB_DATABASE_UPDATE.getValue<GitHubDatabaseUpdate>();
832+
return GitHubDatabaseUpdateValues.includes(value) ? value : "ask";
833+
}
834+
820835
public async setDownload(
821836
value: GitHubDatabaseDownload,
822837
target: ConfigurationTarget = ConfigurationTarget.Workspace,
823838
): Promise<void> {
824839
await GITHUB_DATABASE_DOWNLOAD.updateValue(value, target);
825840
}
841+
842+
public async setUpdate(
843+
value: GitHubDatabaseUpdate,
844+
target: ConfigurationTarget = ConfigurationTarget.Workspace,
845+
): Promise<void> {
846+
await GITHUB_DATABASE_UPDATE.updateValue(value, target);
847+
}
826848
}

extensions/ql-vscode/src/databases/github-database-download.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export async function downloadDatabaseFromGitHub(
110110
*
111111
* @param languages The languages to join. These should be language identifiers, such as `csharp`.
112112
*/
113-
function joinLanguages(languages: string[]): string {
113+
export function joinLanguages(languages: string[]): string {
114114
const languageDisplayNames = languages
115115
.map((language) => getLanguageDisplayName(language))
116116
.sort();
@@ -130,8 +130,17 @@ function joinLanguages(languages: string[]): string {
130130
return result;
131131
}
132132

133-
async function promptForDatabases(
133+
type PromptForDatabasesOptions = {
134+
title?: string;
135+
placeHolder?: string;
136+
};
137+
138+
export async function promptForDatabases(
134139
databases: CodeqlDatabase[],
140+
{
141+
title = "Select databases to download",
142+
placeHolder = "Databases found in this repository",
143+
}: PromptForDatabasesOptions = {},
135144
): Promise<CodeqlDatabase[]> {
136145
if (databases.length === 1) {
137146
return databases;
@@ -152,8 +161,8 @@ async function promptForDatabases(
152161
.sort((a, b) => a.label.localeCompare(b.label));
153162

154163
const selectedItems = await window.showQuickPick(items, {
155-
title: "Select databases to download",
156-
placeHolder: "Databases found in this repository",
164+
title,
165+
placeHolder,
157166
ignoreFocusOut: true,
158167
canPickMany: true,
159168
});

extensions/ql-vscode/src/databases/github-database-module.ts

Lines changed: 80 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,26 @@ import { DisposableObject } from "../common/disposable-object";
33
import { App } from "../common/app";
44
import { findGitHubRepositoryForWorkspace } from "./github-repository-finder";
55
import { redactableError } from "../common/errors";
6-
import { asError, getErrorMessage } from "../common/helpers-pure";
6+
import { asError, assertNever, getErrorMessage } from "../common/helpers-pure";
77
import {
88
askForGitHubDatabaseDownload,
99
downloadDatabaseFromGitHub,
1010
} from "./github-database-download";
1111
import { GitHubDatabaseConfig, GitHubDatabaseConfigListener } from "../config";
1212
import { DatabaseManager } from "./local-databases";
1313
import { CodeQLCliServer } from "../codeql-cli/cli";
14-
import { listDatabases, ListDatabasesResult } from "./github-database-api";
14+
import {
15+
CodeqlDatabase,
16+
listDatabases,
17+
ListDatabasesResult,
18+
} from "./github-database-api";
19+
import {
20+
askForGitHubDatabaseUpdate,
21+
DatabaseUpdate,
22+
downloadDatabaseUpdateFromGitHub,
23+
isNewerDatabaseAvailable,
24+
} from "./github-database-updates";
25+
import { Octokit } from "@octokit/rest";
1526

1627
export class GithubDatabaseModule extends DisposableObject {
1728
private readonly config: GitHubDatabaseConfig;
@@ -79,16 +90,6 @@ export class GithubDatabaseModule extends DisposableObject {
7990

8091
const githubRepository = githubRepositoryResult.value;
8192

82-
const hasExistingDatabase = this.databaseManager.databaseItems.some(
83-
(db) =>
84-
db.origin?.type === "github" &&
85-
db.origin.repository ===
86-
`${githubRepository.owner}/${githubRepository.name}`,
87-
);
88-
if (hasExistingDatabase) {
89-
return;
90-
}
91-
9293
let result: ListDatabasesResult | undefined;
9394
try {
9495
result = await listDatabases(
@@ -130,6 +131,45 @@ export class GithubDatabaseModule extends DisposableObject {
130131
return;
131132
}
132133

134+
const updateStatus = isNewerDatabaseAvailable(
135+
databases,
136+
githubRepository.owner,
137+
githubRepository.name,
138+
this.databaseManager,
139+
);
140+
141+
switch (updateStatus.type) {
142+
case "upToDate":
143+
return;
144+
case "updateAvailable":
145+
await this.updateGitHubDatabase(
146+
octokit,
147+
githubRepository.owner,
148+
githubRepository.name,
149+
updateStatus.databaseUpdates,
150+
);
151+
break;
152+
case "noDatabase":
153+
await this.downloadGitHubDatabase(
154+
octokit,
155+
githubRepository.owner,
156+
githubRepository.name,
157+
databases,
158+
promptedForCredentials,
159+
);
160+
break;
161+
default:
162+
assertNever(updateStatus);
163+
}
164+
}
165+
166+
private async downloadGitHubDatabase(
167+
octokit: Octokit,
168+
owner: string,
169+
repo: string,
170+
databases: CodeqlDatabase[],
171+
promptedForCredentials: boolean,
172+
) {
133173
// If the user already had an access token, first ask if they even want to download the DB.
134174
if (!promptedForCredentials) {
135175
if (!(await askForGitHubDatabaseDownload(databases, this.config))) {
@@ -139,13 +179,39 @@ export class GithubDatabaseModule extends DisposableObject {
139179

140180
await downloadDatabaseFromGitHub(
141181
octokit,
142-
githubRepository.owner,
143-
githubRepository.name,
182+
owner,
183+
repo,
144184
databases,
145185
this.databaseManager,
146186
this.databaseStoragePath,
147187
this.cliServer,
148188
this.app.commands,
149189
);
150190
}
191+
192+
private async updateGitHubDatabase(
193+
octokit: Octokit,
194+
owner: string,
195+
repo: string,
196+
databaseUpdates: DatabaseUpdate[],
197+
): Promise<void> {
198+
if (this.config.update === "never") {
199+
return;
200+
}
201+
202+
if (!(await askForGitHubDatabaseUpdate(databaseUpdates, this.config))) {
203+
return;
204+
}
205+
206+
await downloadDatabaseUpdateFromGitHub(
207+
octokit,
208+
owner,
209+
repo,
210+
databaseUpdates,
211+
this.databaseManager,
212+
this.databaseStoragePath,
213+
this.cliServer,
214+
this.app.commands,
215+
);
216+
}
151217
}

0 commit comments

Comments
 (0)