diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d40d86775..088c5077d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,7 +10,7 @@ jobs: os: [ubuntu-latest, windows-latest] steps: - name: Checkout - uses: actions/checkout@v1 + uses: actions/checkout@v2 with: fetch-depth: 1 @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest, windows-latest] steps: - name: Checkout - uses: actions/checkout@v1 + uses: actions/checkout@v2 with: fetch-depth: 1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 24cf4c9e6..9b70582f5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,18 +27,12 @@ jobs: # TODO Share steps with the main workflow. steps: - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@v2 - uses: actions/setup-node@v1 with: node-version: '10.18.1' - # The checkout action does not fetch the master branch. - # Fetch the master branch so that we can base the version bump PR against master. - - name: Fetch master branch - run: | - git fetch --depth=1 origin master:master - - name: Build run: | cd build @@ -99,6 +93,13 @@ jobs: asset_name: ${{ format('vscode-codeql-{0}.vsix', steps.prepare-artifacts.outputs.ref_name) }} asset_content_type: application/zip + # The checkout action does not fetch the master branch. + # Fetch the master branch so that we can base the version bump PR against master. + - name: Fetch master branch + run: | + git fetch --depth=1 origin master:master + git checkout master + - name: Bump patch version id: bump-patch-version if: success() @@ -110,7 +111,7 @@ jobs: echo "::set-output name=next_version::$NEXT_VERSION" - name: Create version bump PR - uses: peter-evans/create-pull-request@c202684c928d4c9f18394b2ad11df905c5d8b40c # v2.1.2 + uses: peter-evans/create-pull-request@c7b64af0a489eae91f7890f2c1b63d13cc2d8ab7 # v2.4.2 if: success() with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/extensions/ql-vscode/CHANGELOG.md b/extensions/ql-vscode/CHANGELOG.md index d633c8600..7df629fd5 100644 --- a/extensions/ql-vscode/CHANGELOG.md +++ b/extensions/ql-vscode/CHANGELOG.md @@ -1,5 +1,10 @@ # CodeQL for Visual Studio Code: Changelog +## 1.0.6 - 28 February 2020 + +- Add command to restart query server. +- Enable support for future minor upgrades to the CodeQL CLI. + ## 1.0.5 - 13 February 2020 - Add an icon next to any failed query runs in the query history diff --git a/extensions/ql-vscode/package.json b/extensions/ql-vscode/package.json index e4d57e7aa..7870f58a8 100644 --- a/extensions/ql-vscode/package.json +++ b/extensions/ql-vscode/package.json @@ -32,6 +32,7 @@ "onCommand:codeQLDatabases.chooseDatabase", "onCommand:codeQLDatabases.setCurrentDatabase", "onCommand:codeQL.quickQuery", + "onCommand:codeQL.restartQueryServer", "onWebviewPanel:resultsView", "onFileSystem:codeql-zip-archive" ], @@ -219,6 +220,10 @@ "command": "codeQLQueryHistory.setLabel", "title": "Set Label" }, + { + "command": "codeQL.restartQueryServer", + "title": "CodeQL: Restart Query Server" + }, { "command": "codeQLTests.showOutputDifferences", "title": "CodeQL: Show Test Output Differences" diff --git a/extensions/ql-vscode/src/distribution.ts b/extensions/ql-vscode/src/distribution.ts index 83bcbb508..c7482525e 100644 --- a/extensions/ql-vscode/src/distribution.ts +++ b/extensions/ql-vscode/src/distribution.ts @@ -39,9 +39,9 @@ const DEFAULT_DISTRIBUTION_REPOSITORY_NAME = "codeql-cli-binaries"; * This applies to both extension-managed and CLI distributions. */ export const DEFAULT_DISTRIBUTION_VERSION_CONSTRAINT: VersionConstraint = { - description: "2.0.*", + description: "2.*.*", isVersionCompatible: (v: Version) => { - return v.majorVersion === 2 && v.minorVersion === 0 + return v.majorVersion === 2 && v.minorVersion >= 0 } } diff --git a/extensions/ql-vscode/src/extension.ts b/extensions/ql-vscode/src/extension.ts index 828572d85..474b0f67d 100644 --- a/extensions/ql-vscode/src/extension.ts +++ b/extensions/ql-vscode/src/extension.ts @@ -321,6 +321,13 @@ async function activateWithInstalledDistribution(ctx: ExtensionContext, distribu ctx.subscriptions.push(commands.registerCommand('codeQL.runQuery', async (uri: Uri | undefined) => await compileAndRunQuery(false, uri))); ctx.subscriptions.push(commands.registerCommand('codeQL.quickEval', async (uri: Uri | undefined) => await compileAndRunQuery(true, uri))); ctx.subscriptions.push(commands.registerCommand('codeQL.quickQuery', async () => displayQuickQuery(ctx, cliServer, databaseUI))); + ctx.subscriptions.push(commands.registerCommand('codeQL.restartQueryServer', async () => { + await qs.restartQueryServer(); + const response = await Window.showInformationMessage('CodeQL Query Server restarted.', 'Show Log'); + if (response === 'Show Log') { + qs.showLog(); + } + })); ctx.subscriptions.push(client.start()); } diff --git a/extensions/ql-vscode/src/logging.ts b/extensions/ql-vscode/src/logging.ts index 192de274e..a4a5d1591 100644 --- a/extensions/ql-vscode/src/logging.ts +++ b/extensions/ql-vscode/src/logging.ts @@ -6,6 +6,12 @@ export interface Logger { log(message: string): void; /** Writes the given log message, not followed by a newline. */ logWithoutTrailingNewline(message: string): void; + /** + * Reveal this channel in the UI. + * + * @param preserveFocus When `true` the channel will not take focus. + */ + show(preserveFocus?: boolean): void; } export type ProgressReporter = Progress<{ message: string }>; @@ -27,6 +33,10 @@ export class OutputChannelLogger extends DisposableObject implements Logger { logWithoutTrailingNewline(message: string) { this.outputChannel.append(message); } + + show(preserveFocus?: boolean) { + this.outputChannel.show(preserveFocus); + } } /** The global logger for the extension. */ diff --git a/extensions/ql-vscode/src/queryserver-client.ts b/extensions/ql-vscode/src/queryserver-client.ts index 74e427b33..e152fe0f1 100644 --- a/extensions/ql-vscode/src/queryserver-client.ts +++ b/extensions/ql-vscode/src/queryserver-client.ts @@ -58,7 +58,10 @@ export class QueryServerClient extends DisposableObject { super(); // When the query server configuration changes, restart the query server. if (config.onDidChangeQueryServerConfiguration !== undefined) { - this.push(config.onDidChangeQueryServerConfiguration(async () => await this.restartQueryServer(), this)); + this.push(config.onDidChangeQueryServerConfiguration(async () => { + this.logger.log('Restarting query server due to configuration changes...'); + await this.restartQueryServer(); + }, this)); } this.withProgressReporting = withProgressReporting; this.nextCallback = 0; @@ -79,12 +82,15 @@ export class QueryServerClient extends DisposableObject { } /** Restarts the query server by disposing of the current server process and then starting a new one. */ - private async restartQueryServer() { - this.logger.log('Restarting query server due to configuration changes...'); + async restartQueryServer() { this.stopQueryServer(); await this.startQueryServer(); } + async showLog() { + this.logger.show(); + } + /** Starts a new query server process, sending progress messages to the status bar. */ async startQueryServer() { // Use an arrow function to preserve the value of `this`. diff --git a/extensions/ql-vscode/test/pure-tests/query-test.ts b/extensions/ql-vscode/test/pure-tests/query-test.ts index 0b0b32a1d..af6ba4247 100644 --- a/extensions/ql-vscode/test/pure-tests/query-test.ts +++ b/extensions/ql-vscode/test/pure-tests/query-test.ts @@ -10,7 +10,7 @@ import { CancellationTokenSource } from 'vscode-jsonrpc'; import * as messages from '../../src/messages'; import * as qsClient from '../../src/queryserver-client'; import * as cli from '../../src/cli'; -import { ProgressReporter } from '../../src/logging'; +import { ProgressReporter, Logger } from '../../src/logging'; declare module "url" { @@ -75,8 +75,8 @@ const queryTestCases: QueryTestCase[] = [ } ]; -describe('using the query server', function () { - before(function () { +describe('using the query server', function() { + before(function() { if (process.env["CODEQL_PATH"] === undefined) { console.log('The environment variable CODEQL_PATH is not set. The query server tests, which require the CodeQL CLI, will be skipped.'); this.skip(); @@ -100,13 +100,14 @@ describe('using the query server', function () { } }); - it('should be able to start the query server', async function () { + it('should be able to start the query server', async function() { const consoleProgressReporter: ProgressReporter = { - report: (v: {message: string}) => console.log(`progress reporter says ${v.message}`) + report: (v: { message: string }) => console.log(`progress reporter says ${v.message}`) }; - const logger = { + const logger: Logger = { log: (s: string) => console.log('logger says', s), - logWithoutTrailingNewline: (s: string) => console.log('logger says', s) + logWithoutTrailingNewline: (s: string) => console.log('logger says', s), + show: () => { }, }; cliServer = new cli.CodeQLCliServer({ async getCodeQlPathWithoutVersionCheck(): Promise { @@ -137,7 +138,7 @@ describe('using the query server', function () { const evaluationSucceeded = new Checkpoint(); const parsedResults = new Checkpoint(); - it(`should be able to compile query ${queryName}`, async function () { + it(`should be able to compile query ${queryName}`, async function() { await queryServerStarted.done(); expect(fs.existsSync(queryTestCase.queryPath)).to.be.true; try { @@ -169,7 +170,7 @@ describe('using the query server', function () { } }); - it(`should be able to run query ${queryName}`, async function () { + it(`should be able to run query ${queryName}`, async function() { try { await compilationSucceeded.done(); const callbackId = qs.registerCallback(_res => { @@ -201,7 +202,7 @@ describe('using the query server', function () { }); const actualResultSets: ResultSets = {}; - it(`should be able to parse results of query ${queryName}`, async function () { + it(`should be able to parse results of query ${queryName}`, async function() { let fileReader: FileReader | undefined; try { await evaluationSucceeded.done(); @@ -222,7 +223,7 @@ describe('using the query server', function () { } }); - it(`should have correct results for query ${queryName}`, async function () { + it(`should have correct results for query ${queryName}`, async function() { await parsedResults.done(); expect(actualResultSets!).not.to.be.empty; expect(Object.keys(actualResultSets!).sort()).to.eql(Object.keys(queryTestCase.expectedResultSets).sort());