From 528bfd7fd5c61b57799ee9937df9680879f24a1b Mon Sep 17 00:00:00 2001 From: tiulpin Date: Thu, 25 Apr 2024 17:56:52 +0200 Subject: [PATCH] :zap: Allow using nightlies for development purposes --- .github/workflows/code-quality.yml | 1 + action.yaml | 5 +++++ common/qodana.ts | 13 +++++++++++-- scan/__tests__/main.test.ts | 3 ++- scan/dist/index.js | 28 +++++++++++++++------------ scan/src/main.ts | 2 +- scan/src/utils.ts | 31 ++++++++++++++++++++---------- vsts/QodanaScan/index.js | 22 ++++++++++++--------- vsts/QodanaScan/task.json | 8 ++++++++ vsts/src/utils.ts | 27 ++++++++++++++++++++------ 10 files changed, 99 insertions(+), 41 deletions(-) diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index e5719cb9..1276ed8c 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -29,5 +29,6 @@ jobs: with: args: --print-problems,--log-level,debug,--config,.github/qodana.yaml pr-mode: true + use-nightly: true env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} diff --git a/action.yaml b/action.yaml index 7744697e..fe3a60fe 100644 --- a/action.yaml +++ b/action.yaml @@ -65,6 +65,11 @@ inputs: description: 'Commit message for the commit with quick-fixes. Not used if `push-fixes` is set to `none`' required: false default: "🤖 Apply quick-fixes by Qodana" + use-nightly: + description: 'Use unstable Qodana CLI nightly' + required: false + default: "false" + deprecationMessage: 'This option is for development purposes only. Do not use it in production.' runs: using: 'node20' main: 'scan/dist/index.js' diff --git a/common/qodana.ts b/common/qodana.ts index 52091ab7..d0d6db1c 100644 --- a/common/qodana.ts +++ b/common/qodana.ts @@ -18,6 +18,7 @@ export const EXECUTABLE = 'qodana' export const VERSION = version export const COVERAGE_THRESHOLD = 50 + export function getQodanaSha256(arch: string, platform: string): string { switch (`${platform}_${arch}`) { case 'windows_x86_64': @@ -54,7 +55,11 @@ export function getProcessPlatformName(): string { /** * Gets Qodana CLI download URL from the GitHub Releases API. */ -export function getQodanaUrl(arch: string, platform: string): string { +export function getQodanaUrl( + arch: string, + platform: string, + nightly = false +): string { if (!SUPPORTED_PLATFORMS.includes(platform)) { throw new Error(`Unsupported platform: ${platform}`) } @@ -62,7 +67,8 @@ export function getQodanaUrl(arch: string, platform: string): string { throw new Error(`Unsupported architecture: ${arch}`) } const archive = platform === 'windows' ? 'zip' : 'tar.gz' - return `https://github.com/JetBrains/qodana-cli/releases/download/v${version}/qodana_${platform}_${arch}.${archive}` + const cli_version = nightly ? 'nightly' : `v${version}` + return `https://github.com/JetBrains/qodana-cli/releases/download/${cli_version}/qodana_${platform}_${arch}.${archive}` } // eslint-disable-next-line no-shadow -- shadowing is intentional here (ESLint bug) @@ -155,11 +161,13 @@ export function getQodanaScanArgs( } return cliArgs } + export const NONE = 'none' export const BRANCH = 'branch' export const PULL_REQUEST = 'pull-request' const PUSH_FIXES_TYPES = [NONE, BRANCH, PULL_REQUEST] export type PushFixesType = (typeof PUSH_FIXES_TYPES)[number] + /** * The context of the current run – described in action.yaml. */ @@ -180,6 +188,7 @@ export interface Inputs { githubToken: string pushFixes: PushFixesType commitMessage: string + useNightly: boolean } /** diff --git a/scan/__tests__/main.test.ts b/scan/__tests__/main.test.ts index b7bf4c87..fb18f98d 100644 --- a/scan/__tests__/main.test.ts +++ b/scan/__tests__/main.test.ts @@ -230,7 +230,8 @@ export function inputsDefaultFixture(): Inputs { postComment: true, githubToken: '', pushFixes: 'none', - commitMessage: '' + commitMessage: '', + useNightly: false } } diff --git a/scan/dist/index.js b/scan/dist/index.js index ba309017..1edd1b05 100644 --- a/scan/dist/index.js +++ b/scan/dist/index.js @@ -24344,7 +24344,7 @@ function getProcessArchName() { function getProcessPlatformName() { return process.platform === "win32" ? "windows" : process.platform; } -function getQodanaUrl(arch, platform) { +function getQodanaUrl(arch, platform, nightly = false) { if (!SUPPORTED_PLATFORMS.includes(platform)) { throw new Error(`Unsupported platform: ${platform}`); } @@ -24352,7 +24352,8 @@ function getQodanaUrl(arch, platform) { throw new Error(`Unsupported architecture: ${arch}`); } const archive = platform === "windows" ? "zip" : "tar.gz"; - return `https://github.com/JetBrains/qodana-cli/releases/download/v${version2}/qodana_${platform}_${arch}.${archive}`; + const cli_version = nightly ? "nightly" : `v${version2}`; + return `https://github.com/JetBrains/qodana-cli/releases/download/${cli_version}/qodana_${platform}_${arch}.${archive}`; } function isExecutionSuccessful(exitCode) { return Object.values(QodanaExitCode).includes(exitCode); @@ -126409,7 +126410,8 @@ var require_utils9 = __commonJS({ postComment: core2.getBooleanInput("post-pr-comment"), githubToken: core2.getInput("github-token"), pushFixes: core2.getInput("push-fixes"), - commitMessage: core2.getInput("commit-message") + commitMessage: core2.getInput("commit-message"), + useNightly: core2.getBooleanInput("use-nightly") }; } __name(getInputs, "getInputs"); @@ -126465,15 +126467,17 @@ var require_utils9 = __commonJS({ } __name(pushQuickFixes, "pushQuickFixes"); exports2.pushQuickFixes = pushQuickFixes; - function prepareAgent(args) { - return __awaiter3(this, void 0, void 0, function* () { + function prepareAgent(args_1) { + return __awaiter3(this, arguments, void 0, function* (args, useNightly = false) { const arch = (0, qodana_12.getProcessArchName)(); const platform = (0, qodana_12.getProcessPlatformName)(); - const expectedChecksum = (0, qodana_12.getQodanaSha256)(arch, platform); - const temp = yield tc.downloadTool((0, qodana_12.getQodanaUrl)(arch, platform)); - const actualChecksum = (0, qodana_12.sha256sum)(temp); - if (expectedChecksum !== actualChecksum) { - core2.setFailed((0, qodana_12.getQodanaSha256MismatchMessage)(expectedChecksum, actualChecksum)); + const temp = yield tc.downloadTool((0, qodana_12.getQodanaUrl)(arch, platform, useNightly)); + if (!useNightly) { + const expectedChecksum = (0, qodana_12.getQodanaSha256)(arch, platform); + const actualChecksum = (0, qodana_12.sha256sum)(temp); + if (expectedChecksum !== actualChecksum) { + core2.setFailed((0, qodana_12.getQodanaSha256MismatchMessage)(expectedChecksum, actualChecksum)); + } } let extractRoot; if (process.platform === "win32") { @@ -126481,7 +126485,7 @@ var require_utils9 = __commonJS({ } else { extractRoot = yield tc.extractTar(temp); } - core2.addPath(yield tc.cacheDir(extractRoot, qodana_12.EXECUTABLE, qodana_12.VERSION)); + core2.addPath(yield tc.cacheDir(extractRoot, qodana_12.EXECUTABLE, useNightly ? "nightly" : qodana_12.VERSION)); if (!(0, qodana_12.isNativeMode)(args)) { const exitCode = yield qodana(getInputs(), (0, qodana_12.getQodanaPullArgs)(args)); if (exitCode !== 0) { @@ -126841,7 +126845,7 @@ function main() { const restoreCachesPromise = (0, utils_1.restoreCaches)(inputs.cacheDir, inputs.primaryCacheKey, inputs.additionalCacheKey, inputs.useCaches); yield Promise.all([ (0, utils_1.putReaction)(utils_1.ANALYSIS_STARTED_REACTION, utils_1.ANALYSIS_FINISHED_REACTION), - (0, utils_1.prepareAgent)(inputs.args), + (0, utils_1.prepareAgent)(inputs.args, inputs.useNightly), restoreCachesPromise ]); const reservedCacheKey = yield restoreCachesPromise; diff --git a/scan/src/main.ts b/scan/src/main.ts index d52fd551..0a9ea803 100644 --- a/scan/src/main.ts +++ b/scan/src/main.ts @@ -66,7 +66,7 @@ async function main(): Promise { ) await Promise.all([ putReaction(ANALYSIS_STARTED_REACTION, ANALYSIS_FINISHED_REACTION), - prepareAgent(inputs.args), + prepareAgent(inputs.args, inputs.useNightly), restoreCachesPromise ]) const reservedCacheKey = await restoreCachesPromise diff --git a/scan/src/utils.ts b/scan/src/utils.ts index 7ea7db0a..43e1f9e0 100644 --- a/scan/src/utils.ts +++ b/scan/src/utils.ts @@ -30,6 +30,7 @@ import path from 'path' import * as fs from 'fs' import * as os from 'os' import {COMMIT_EMAIL, COMMIT_USER, prFixesBody} from './output' + export const ANALYSIS_FINISHED_REACTION = '+1' export const ANALYSIS_STARTED_REACTION = 'eyes' const REACTIONS = [ @@ -68,9 +69,11 @@ export function getInputs(): Inputs { postComment: core.getBooleanInput('post-pr-comment'), githubToken: core.getInput('github-token'), pushFixes: core.getInput('push-fixes'), - commitMessage: core.getInput('commit-message') + commitMessage: core.getInput('commit-message'), + useNightly: core.getBooleanInput('use-nightly') } } + /** * Runs the qodana command with the given arguments. * @param inputs the action inputs. @@ -141,17 +144,23 @@ export async function pushQuickFixes( /** * Prepares the agent for qodana scan: install Qodana CLI and pull the linter. * @param args qodana arguments + * @param useNightly whether to use a nightly version of Qodana CLI */ -export async function prepareAgent(args: string[]): Promise { +export async function prepareAgent( + args: string[], + useNightly = false +): Promise { const arch = getProcessArchName() const platform = getProcessPlatformName() - const expectedChecksum = getQodanaSha256(arch, platform) - const temp = await tc.downloadTool(getQodanaUrl(arch, platform)) - const actualChecksum = sha256sum(temp) - if (expectedChecksum !== actualChecksum) { - core.setFailed( - getQodanaSha256MismatchMessage(expectedChecksum, actualChecksum) - ) + const temp = await tc.downloadTool(getQodanaUrl(arch, platform, useNightly)) + if (!useNightly) { + const expectedChecksum = getQodanaSha256(arch, platform) + const actualChecksum = sha256sum(temp) + if (expectedChecksum !== actualChecksum) { + core.setFailed( + getQodanaSha256MismatchMessage(expectedChecksum, actualChecksum) + ) + } } let extractRoot if (process.platform === 'win32') { @@ -159,7 +168,9 @@ export async function prepareAgent(args: string[]): Promise { } else { extractRoot = await tc.extractTar(temp) } - core.addPath(await tc.cacheDir(extractRoot, EXECUTABLE, VERSION)) + core.addPath( + await tc.cacheDir(extractRoot, EXECUTABLE, useNightly ? 'nightly' : VERSION) + ) if (!isNativeMode(args)) { const exitCode = await qodana(getInputs(), getQodanaPullArgs(args)) if (exitCode !== 0) { diff --git a/vsts/QodanaScan/index.js b/vsts/QodanaScan/index.js index 1e201f3f..63ecc4ab 100644 --- a/vsts/QodanaScan/index.js +++ b/vsts/QodanaScan/index.js @@ -105,7 +105,7 @@ function getProcessArchName() { function getProcessPlatformName() { return process.platform === "win32" ? "windows" : process.platform; } -function getQodanaUrl(arch, platform) { +function getQodanaUrl(arch, platform, nightly = false) { if (!SUPPORTED_PLATFORMS.includes(platform)) { throw new Error(`Unsupported platform: ${platform}`); } @@ -113,7 +113,8 @@ function getQodanaUrl(arch, platform) { throw new Error(`Unsupported architecture: ${arch}`); } const archive = platform === "windows" ? "zip" : "tar.gz"; - return `https://github.com/JetBrains/qodana-cli/releases/download/v${version}/qodana_${platform}_${arch}.${archive}`; + const cli_version = nightly ? "nightly" : `v${version}`; + return `https://github.com/JetBrains/qodana-cli/releases/download/${cli_version}/qodana_${platform}_${arch}.${archive}`; } function isExecutionSuccessful(exitCode) { return Object.values(QodanaExitCode).includes(exitCode); @@ -5016,6 +5017,7 @@ var require_utils2 = __commonJS({ uploadResult: tl2.getBoolInput("uploadResult", false) || false, uploadSarif: tl2.getBoolInput("uploadSarif", false) || true, artifactName: tl2.getInput("artifactName", false) || "qodana-report", + useNightly: tl2.getBoolInput("useNightly", false) || false, // Not used by the Azure task postComment: false, additionalCacheKey: "", @@ -5043,15 +5045,17 @@ var require_utils2 = __commonJS({ }); } exports2.qodana = qodana; - function prepareAgent(args) { - return __awaiter2(this, void 0, void 0, function* () { + function prepareAgent(args_1) { + return __awaiter2(this, arguments, void 0, function* (args, useNightly = false) { const arch = (0, qodana_12.getProcessArchName)(); const platform = (0, qodana_12.getProcessPlatformName)(); - const expectedChecksum = (0, qodana_12.getQodanaSha256)(arch, platform); const temp = yield tool.downloadTool((0, qodana_12.getQodanaUrl)(arch, platform)); - const actualChecksum = (0, qodana_12.sha256sum)(temp); - if (expectedChecksum !== actualChecksum) { - setFailed((0, qodana_12.getQodanaSha256MismatchMessage)(expectedChecksum, actualChecksum)); + if (!useNightly) { + const expectedChecksum = (0, qodana_12.getQodanaSha256)(arch, platform); + const actualChecksum = (0, qodana_12.sha256sum)(temp); + if (expectedChecksum !== actualChecksum) { + setFailed((0, qodana_12.getQodanaSha256MismatchMessage)(expectedChecksum, actualChecksum)); + } } let extractRoot; if (process.platform === "win32") { @@ -5059,7 +5063,7 @@ var require_utils2 = __commonJS({ } else { extractRoot = yield tool.extractTar(temp); } - tool.prependPath(yield tool.cacheDir(extractRoot, qodana_12.EXECUTABLE, qodana_12.VERSION)); + tool.prependPath(yield tool.cacheDir(extractRoot, qodana_12.EXECUTABLE, useNightly ? "nightly" : qodana_12.VERSION)); if (!(0, qodana_12.isNativeMode)(args)) { const pull = yield qodana((0, qodana_12.getQodanaPullArgs)(args)); if (pull !== 0) { diff --git a/vsts/QodanaScan/task.json b/vsts/QodanaScan/task.json index 832cd9b4..09703bec 100644 --- a/vsts/QodanaScan/task.json +++ b/vsts/QodanaScan/task.json @@ -61,6 +61,14 @@ "defaultValue": "$(Agent.TempDirectory)/qodana/cache", "required": false, "helpMarkDown": "Directory to store Qodana caches" + }, + { + "name": "useNightly", + "type": "boolean", + "label": "Use unstable Qodana CLI nightly", + "defaultValue": false, + "required": false, + "helpMarkDown": "This option is for development purposes only. Do not use it in production." } ], "execution": { diff --git a/vsts/src/utils.ts b/vsts/src/utils.ts index 71a1224f..96b2bf71 100644 --- a/vsts/src/utils.ts +++ b/vsts/src/utils.ts @@ -37,6 +37,7 @@ export function getInputs(): Inputs { uploadResult: tl.getBoolInput('uploadResult', false) || false, uploadSarif: tl.getBoolInput('uploadSarif', false) || true, artifactName: tl.getInput('artifactName', false) || 'qodana-report', + useNightly: tl.getBoolInput('useNightly', false) || false, // Not used by the Azure task postComment: false, additionalCacheKey: '', @@ -73,15 +74,23 @@ export async function qodana(args: string[] = []): Promise { /** * Prepares the agent for qodana scan: install Qodana CLI and pull the linter. * @param args qodana arguments + * @param useNightly whether to use a nightly version of Qodana CLI */ -export async function prepareAgent(args: string[]): Promise { +export async function prepareAgent( + args: string[], + useNightly = false +): Promise { const arch = getProcessArchName() const platform = getProcessPlatformName() - const expectedChecksum = getQodanaSha256(arch, platform) const temp = await tool.downloadTool(getQodanaUrl(arch, platform)) - const actualChecksum = sha256sum(temp) - if (expectedChecksum !== actualChecksum) { - setFailed(getQodanaSha256MismatchMessage(expectedChecksum, actualChecksum)) + if (!useNightly) { + const expectedChecksum = getQodanaSha256(arch, platform) + const actualChecksum = sha256sum(temp) + if (expectedChecksum !== actualChecksum) { + setFailed( + getQodanaSha256MismatchMessage(expectedChecksum, actualChecksum) + ) + } } let extractRoot if (process.platform === 'win32') { @@ -89,7 +98,13 @@ export async function prepareAgent(args: string[]): Promise { } else { extractRoot = await tool.extractTar(temp) } - tool.prependPath(await tool.cacheDir(extractRoot, EXECUTABLE, VERSION)) + tool.prependPath( + await tool.cacheDir( + extractRoot, + EXECUTABLE, + useNightly ? 'nightly' : VERSION + ) + ) if (!isNativeMode(args)) { const pull = await qodana(getQodanaPullArgs(args)) if (pull !== 0) {