Merge pull request #1674 from github/aeisenberg/assert-version

Assert VSCode version is high enough
This commit is contained in:
Andrew Eisenberg
2022-11-15 10:51:42 -08:00
committed by GitHub
5 changed files with 63 additions and 7 deletions

View File

@@ -54,7 +54,7 @@ Alternatively, you can build the extension within VS Code via `Terminal > Run Bu
Before running any of the launch commands, be sure to have run the `build` command to ensure that the JavaScript is compiled and the resources are copied to the proper location.
We recommend that you keep `npm run watch` running in the backgound and you only need to re-run `npm run build` in the following situations:
We recommend that you keep `npm run watch` running in the background and you only need to re-run `npm run build` in the following situations:
1. on first checkout
2. whenever any of the non-TypeScript resources have changed
@@ -152,7 +152,7 @@ The CLI integration tests require the CodeQL standard libraries in order to run
#### Using a mock GitHub API server
Multi-Repo Variant Analyses (MRVA) rely on the GitHub API. In order to make development and testing easy, we have functionality that allows us to intercept requests to the GitHub API and provide mock responses.
Multi-Repo Variant Analyses (MRVA) rely on the GitHub API. In order to make development and testing easy, we have functionality that allows us to intercept requests to the GitHub API and provide mock responses.
##### Using a pre-recorded test scenario

View File

@@ -2,6 +2,8 @@
## [UNRELEASED]
- Warn users when their VS Code version is too old to support all features in the vscode-codeql extension. [#1674](https://github.com/github/vscode-codeql/pull/1674)
## 1.7.5 - 8 November 2022
- Fix a bug where the AST Viewer was not working unless the associated CodeQL library pack is in the workspace. [#1735](https://github.com/github/vscode-codeql/pull/1735)

View File

@@ -99,7 +99,7 @@ When the results are ready, they're displayed in the CodeQL Query Results view.
If there are any problems running a query, a notification is displayed in the bottom right corner of the application. In addition to the error message, the notification includes details of how to fix the problem.
### Keyboad navigation
### Keyboard navigation
If you wish to navigate the query results from your keyboard, you can bind shortcuts to the **CodeQL: Navigate Up/Down/Left/Right in Result Viewer** commands.

View File

@@ -16,7 +16,8 @@ import {
QuickPickItem,
Range,
workspace,
ProviderResult
ProviderResult,
version as vscodeVersion
} from 'vscode';
import { LanguageClient } from 'vscode-languageclient';
import * as os from 'os';
@@ -24,6 +25,7 @@ import * as fs from 'fs-extra';
import * as path from 'path';
import * as tmp from 'tmp-promise';
import { testExplorerExtensionId, TestHub } from 'vscode-test-adapter-api';
import * as semver from 'semver';
import { AstViewer } from './astViewer';
import * as archiveFilesystemProvider from './archive-filesystem-provider';
@@ -191,6 +193,13 @@ export interface CodeQLExtensionInterface {
readonly dispose: () => void;
}
// This is the minimum version of vscode that we _want_ to support. We want to update the language server library, but that
// requires 1.67 or later. If we change the minimum version in the package.json, then anyone on an older version of vscode
// silently be unable to upgrade. So, the solution is to first bump the minimum version here and release. Then
// bump the version in the package.json and release again. This way, anyone on an older version of vscode will get a warning
// before silently being refused to upgrade.
const MIN_VERSION = '1.67.0';
/**
* Returns the CodeQLExtensionInterface, or an empty object if the interface is not
* available after activation is complete. This will happen if there is no cli
@@ -226,6 +235,9 @@ export async function activate(ctx: ExtensionContext): Promise<CodeQLExtensionIn
void showAndLogErrorMessage(`Can't execute ${command}: waiting to finish loading CodeQL CLI.`);
}));
// Checking the vscode version should not block extension activation.
void assertVSCodeVersionGreaterThan(MIN_VERSION, ctx);
interface DistributionUpdateConfig {
isUserInitiated: boolean;
shouldDisplayMessageWhenNoUpdates: boolean;
@@ -1348,3 +1360,43 @@ function registerRemoteQueryTextProvider() {
},
});
}
const avoidVersionCheck = 'avoid-version-check-at-startup';
const lastVersionChecked = 'last-version-checked';
async function assertVSCodeVersionGreaterThan(minVersion: string, ctx: ExtensionContext) {
// Check if we should reset the version check.
const lastVersion = await ctx.globalState.get(lastVersionChecked);
await ctx.globalState.update(lastVersionChecked, vscodeVersion);
if (lastVersion !== minVersion) {
// In this case, the version has changed since the last time we checked.
// If the user has previously opted out of this check, then user has updated their
// vscode instance since then, so we should check again. Any future warning would
// be for a different version of vscode.
await ctx.globalState.update(avoidVersionCheck, false);
}
if (await ctx.globalState.get(avoidVersionCheck)) {
return;
}
try {
const parsedVersion = semver.parse(vscodeVersion);
const parsedMinVersion = semver.parse(minVersion);
if (!parsedVersion || !parsedMinVersion) {
void showAndLogWarningMessage(
`Could not do a version check of vscode because could not parse version number: actual vscode version ${vscodeVersion} or minimum supported vscode version ${minVersion}.`
);
return;
}
if (semver.lt(parsedVersion, parsedMinVersion)) {
const message = `The CodeQL extension requires VS Code version ${minVersion} or later. Current version is ${vscodeVersion}. Please update VS Code to get the latest features of CodeQL.`;
const result = await showBinaryChoiceDialog(message, false, 'OK', 'Don\'t show again');
if (!result) {
await ctx.globalState.update(avoidVersionCheck, true);
}
}
} catch (e) {
void showAndLogWarningMessage(`Could not do a version check because of an error: ${getErrorMessage(e)}`);
}
}

View File

@@ -110,15 +110,17 @@ async function internalShowAndLog(
* @param message The message to show.
* @param modal If true (the default), show a modal dialog box, otherwise dialog is non-modal and can
* be closed even if the user does not make a choice.
* @param yesTitle The text in the box indicating the affirmative choice.
* @param noTitle The text in the box indicating the negative choice.
*
* @return
* `true` if the user clicks 'Yes',
* `false` if the user clicks 'No' or cancels the dialog,
* `undefined` if the dialog is closed without the user making a choice.
*/
export async function showBinaryChoiceDialog(message: string, modal = true): Promise<boolean | undefined> {
const yesItem = { title: 'Yes', isCloseAffordance: false };
const noItem = { title: 'No', isCloseAffordance: true };
export async function showBinaryChoiceDialog(message: string, modal = true, yesTitle = 'Yes', noTitle = 'No'): Promise<boolean | undefined> {
const yesItem = { title: yesTitle, isCloseAffordance: false };
const noItem = { title: noTitle, isCloseAffordance: true };
const chosenItem = await Window.showInformationMessage(message, { modal }, yesItem, noItem);
if (!chosenItem) {
return undefined;