diff --git a/common/qodana.ts b/common/qodana.ts index dd41550c..5fcbd74f 100644 --- a/common/qodana.ts +++ b/common/qodana.ts @@ -10,6 +10,7 @@ export const FAIL_THRESHOLD_OUTPUT = export const QODANA_SARIF_NAME = 'qodana.sarif.json' export const QODANA_SHORT_SARIF_NAME = 'qodana-short.sarif.json' export const QODANA_REPORT_URL_NAME = 'qodana.cloud' +export const QODANA_OPEN_IN_IDE_NAME = 'open-in-ide.json' export const QODANA_LICENSES_MD = 'thirdPartySoftwareList.md' export const QODANA_LICENSES_JSON = 'thirdPartySoftwareList.json' diff --git a/scan/__tests__/main.test.ts b/scan/__tests__/main.test.ts index f8c513fe..4faf7f72 100644 --- a/scan/__tests__/main.test.ts +++ b/scan/__tests__/main.test.ts @@ -3,7 +3,9 @@ import {AnnotationProperties} from '@actions/core' import { getCoverageFromSarif, getQodanaScanArgs, - Inputs + Inputs, + QODANA_OPEN_IN_IDE_NAME, + QODANA_REPORT_URL_NAME } from '../../common/qodana' import { Annotation, @@ -11,7 +13,10 @@ import { parseSarif, toAnnotationProperties } from '../src/annotations' -import {getSummary, getCoverageStats} from '../src/output' +import {getSummary, getCoverageStats, getReportURL} from '../src/output' +import * as fs from 'fs' +import * as path from 'path' +import * as os from 'os' test('qodana scan command args', () => { const inputs = inputsDefaultFixture() @@ -95,6 +100,58 @@ test('check success conclusion for the Check', () => { expect(result).toEqual('success') }) +describe('getReportURL', () => { + let tempDir: string + + beforeEach(async () => { + // create a unique temporary directory for each test + tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'jest-')) + }) + + afterEach(async () => { + // cleanup - remove temporary directory + await fs.promises.rm(tempDir, {recursive: true}) + }) + + it('returns cloud URL if open in IDE file exists', async () => { + const url = 'http://cloud.url' + const data = {cloud: {url}} + const filepath = path.join(tempDir, QODANA_OPEN_IN_IDE_NAME) + await fs.promises.writeFile(filepath, JSON.stringify(data)) + console.log(JSON.stringify(data)) + + const result = getReportURL(tempDir) + + expect(result).toBe(url) + }) + + it('returns report URL if open in IDE file does not exist but report file exists', async () => { + const url = 'http://report.url' + const filepath = path.join(tempDir, QODANA_REPORT_URL_NAME) + await fs.promises.writeFile(filepath, url) + + const result = getReportURL(tempDir) + + expect(result).toBe(url) + }) + + it('returns empty string if no file exists', () => { + const result = getReportURL(tempDir) + + expect(result).toBe('') + }) + + it('returns empty string if open in IDE file exists but does not contain url', async () => { + const data = {cloud: {}} + const filepath = path.join(tempDir, QODANA_OPEN_IN_IDE_NAME) + await fs.promises.writeFile(filepath, JSON.stringify(data)) + + const result = getReportURL(tempDir) + + expect(result).toBe('') + }) +}) + export function outputEmptyFixture(): Annotation[] { return [] } diff --git a/scan/dist/index.js b/scan/dist/index.js index cd6d8227..1693e1a2 100644 --- a/scan/dist/index.js +++ b/scan/dist/index.js @@ -24693,6 +24693,7 @@ __export(qodana_exports, { PULL_REQUEST: () => PULL_REQUEST, QODANA_LICENSES_JSON: () => QODANA_LICENSES_JSON, QODANA_LICENSES_MD: () => QODANA_LICENSES_MD, + QODANA_OPEN_IN_IDE_NAME: () => QODANA_OPEN_IN_IDE_NAME, QODANA_REPORT_URL_NAME: () => QODANA_REPORT_URL_NAME, QODANA_SARIF_NAME: () => QODANA_SARIF_NAME, QODANA_SHORT_SARIF_NAME: () => QODANA_SHORT_SARIF_NAME, @@ -24827,7 +24828,7 @@ function sha256sum(file) { function getQodanaSha256MismatchMessage(expected, actual) { return `Downloaded Qodana CLI binary is corrupted. Expected SHA-256 checksum: ${expected}, actual checksum: ${actual}`; } -var import_crypto4, import_fs, SUPPORTED_PLATFORMS, SUPPORTED_ARCHS, FAIL_THRESHOLD_OUTPUT, QODANA_SARIF_NAME, QODANA_SHORT_SARIF_NAME, QODANA_REPORT_URL_NAME, QODANA_LICENSES_MD, QODANA_LICENSES_JSON, EXECUTABLE, VERSION, COVERAGE_THRESHOLD, QodanaExitCode, NONE, BRANCH, PULL_REQUEST; +var import_crypto4, import_fs, SUPPORTED_PLATFORMS, SUPPORTED_ARCHS, FAIL_THRESHOLD_OUTPUT, QODANA_SARIF_NAME, QODANA_SHORT_SARIF_NAME, QODANA_REPORT_URL_NAME, QODANA_OPEN_IN_IDE_NAME, QODANA_LICENSES_MD, QODANA_LICENSES_JSON, EXECUTABLE, VERSION, COVERAGE_THRESHOLD, QodanaExitCode, NONE, BRANCH, PULL_REQUEST; var init_qodana = __esm({ "../common/qodana.ts"() { "use strict"; @@ -24840,6 +24841,7 @@ var init_qodana = __esm({ QODANA_SARIF_NAME = "qodana.sarif.json"; QODANA_SHORT_SARIF_NAME = "qodana-short.sarif.json"; QODANA_REPORT_URL_NAME = "qodana.cloud"; + QODANA_OPEN_IN_IDE_NAME = "open-in-ide.json"; QODANA_LICENSES_MD = "thirdPartySoftwareList.md"; QODANA_LICENSES_JSON = "thirdPartySoftwareList.json"; EXECUTABLE = "qodana"; @@ -85056,7 +85058,7 @@ var require_output = __commonJS({ }); }; Object.defineProperty(exports2, "__esModule", { value: true }); - exports2.prFixesBody = exports2.getProblemPlural = exports2.getSummary = exports2.publishOutput = exports2.getCoverageStats = exports2.COMMIT_EMAIL = exports2.COMMIT_USER = void 0; + exports2.prFixesBody = exports2.getProblemPlural = exports2.getSummary = exports2.publishOutput = exports2.getReportURL = exports2.getCoverageStats = exports2.COMMIT_EMAIL = exports2.COMMIT_USER = void 0; var core2 = __importStar3(require_core()); var fs2 = __importStar3(require("fs")); var qodana_12 = (init_qodana(), __toCommonJS(qodana_exports)); @@ -85121,6 +85123,25 @@ ${c.freshLines} lines analyzed, ${c.freshCoveredLines} lines covered`; } __name(getCoverageStats, "getCoverageStats"); exports2.getCoverageStats = getCoverageStats; + function getReportURL(resultsDir) { + let reportUrlFile = `${resultsDir}/${qodana_12.QODANA_OPEN_IN_IDE_NAME}`; + if (fs2.existsSync(reportUrlFile)) { + const data = JSON.parse(fs2.readFileSync(reportUrlFile, { encoding: "utf8" })); + if (data && data.cloud && data.cloud.url) { + return data.cloud.url; + } + } else { + reportUrlFile = `${resultsDir}/${qodana_12.QODANA_REPORT_URL_NAME}`; + if (fs2.existsSync(reportUrlFile)) { + return fs2.readFileSync(`${resultsDir}/${qodana_12.QODANA_REPORT_URL_NAME}`, { + encoding: "utf8" + }); + } + } + return ""; + } + __name(getReportURL, "getReportURL"); + exports2.getReportURL = getReportURL; function publishOutput(failedByThreshold, resultsDir, useAnnotations, postComment, isPrMode, execute) { var _a, _b; return __awaiter3(this, void 0, void 0, function* () { @@ -85129,13 +85150,7 @@ ${c.freshLines} lines analyzed, ${c.freshCoveredLines} lines covered`; } try { const problems = (0, annotations_1.parseSarif)(`${resultsDir}/${qodana_12.QODANA_SARIF_NAME}`); - let reportUrl = ""; - const reportUrlFile = `${resultsDir}/${qodana_12.QODANA_REPORT_URL_NAME}`; - if (fs2.existsSync(reportUrlFile)) { - reportUrl = fs2.readFileSync(`${resultsDir}/${qodana_12.QODANA_REPORT_URL_NAME}`, { - encoding: "utf8" - }); - } + const reportUrl = getReportURL(resultsDir); const coverageInfo = getCoverageStats((0, qodana_12.getCoverageFromSarif)(`${resultsDir}/${qodana_12.QODANA_SHORT_SARIF_NAME}`), qodana_12.COVERAGE_THRESHOLD); let licensesInfo = ""; const licensesJson = `${resultsDir}/projectStructure/${qodana_12.QODANA_LICENSES_JSON}`; diff --git a/scan/src/output.ts b/scan/src/output.ts index f1f9410c..b46f522a 100644 --- a/scan/src/output.ts +++ b/scan/src/output.ts @@ -7,6 +7,7 @@ import { getCoverageFromSarif, QODANA_LICENSES_JSON, QODANA_LICENSES_MD, + QODANA_OPEN_IN_IDE_NAME, QODANA_REPORT_URL_NAME, QODANA_SARIF_NAME, QODANA_SHORT_SARIF_NAME, @@ -91,6 +92,24 @@ ${c.freshLines} lines analyzed, ${c.freshCoveredLines} lines covered` ) } +export function getReportURL(resultsDir: string): string { + let reportUrlFile = `${resultsDir}/${QODANA_OPEN_IN_IDE_NAME}` + if (fs.existsSync(reportUrlFile)) { + const data = JSON.parse(fs.readFileSync(reportUrlFile, {encoding: 'utf8'})) + if (data && data.cloud && data.cloud.url) { + return data.cloud.url + } + } else { + reportUrlFile = `${resultsDir}/${QODANA_REPORT_URL_NAME}` + if (fs.existsSync(reportUrlFile)) { + return fs.readFileSync(`${resultsDir}/${QODANA_REPORT_URL_NAME}`, { + encoding: 'utf8' + }) + } + } + return '' +} + /** * Publish Qodana results to GitHub: comment, job summary, annotations. * @param failedByThreshold flag if the Qodana failThreshold was reached. @@ -113,13 +132,7 @@ export async function publishOutput( } try { const problems = parseSarif(`${resultsDir}/${QODANA_SARIF_NAME}`) - let reportUrl = '' - const reportUrlFile = `${resultsDir}/${QODANA_REPORT_URL_NAME}` - if (fs.existsSync(reportUrlFile)) { - reportUrl = fs.readFileSync(`${resultsDir}/${QODANA_REPORT_URL_NAME}`, { - encoding: 'utf8' - }) - } + const reportUrl = getReportURL(resultsDir) const coverageInfo = getCoverageStats( getCoverageFromSarif(`${resultsDir}/${QODANA_SHORT_SARIF_NAME}`), COVERAGE_THRESHOLD diff --git a/vsts/QodanaScan/index.js b/vsts/QodanaScan/index.js index 147950ec..c9a3d3ec 100644 --- a/vsts/QodanaScan/index.js +++ b/vsts/QodanaScan/index.js @@ -61,6 +61,7 @@ __export(qodana_exports, { PULL_REQUEST: () => PULL_REQUEST, QODANA_LICENSES_JSON: () => QODANA_LICENSES_JSON, QODANA_LICENSES_MD: () => QODANA_LICENSES_MD, + QODANA_OPEN_IN_IDE_NAME: () => QODANA_OPEN_IN_IDE_NAME, QODANA_REPORT_URL_NAME: () => QODANA_REPORT_URL_NAME, QODANA_SARIF_NAME: () => QODANA_SARIF_NAME, QODANA_SHORT_SARIF_NAME: () => QODANA_SHORT_SARIF_NAME, @@ -195,7 +196,7 @@ function sha256sum(file) { function getQodanaSha256MismatchMessage(expected, actual) { return `Downloaded Qodana CLI binary is corrupted. Expected SHA-256 checksum: ${expected}, actual checksum: ${actual}`; } -var import_crypto, import_fs, SUPPORTED_PLATFORMS, SUPPORTED_ARCHS, FAIL_THRESHOLD_OUTPUT, QODANA_SARIF_NAME, QODANA_SHORT_SARIF_NAME, QODANA_REPORT_URL_NAME, QODANA_LICENSES_MD, QODANA_LICENSES_JSON, EXECUTABLE, VERSION, COVERAGE_THRESHOLD, QodanaExitCode, NONE, BRANCH, PULL_REQUEST; +var import_crypto, import_fs, SUPPORTED_PLATFORMS, SUPPORTED_ARCHS, FAIL_THRESHOLD_OUTPUT, QODANA_SARIF_NAME, QODANA_SHORT_SARIF_NAME, QODANA_REPORT_URL_NAME, QODANA_OPEN_IN_IDE_NAME, QODANA_LICENSES_MD, QODANA_LICENSES_JSON, EXECUTABLE, VERSION, COVERAGE_THRESHOLD, QodanaExitCode, NONE, BRANCH, PULL_REQUEST; var init_qodana = __esm({ "../common/qodana.ts"() { "use strict"; @@ -208,6 +209,7 @@ var init_qodana = __esm({ QODANA_SARIF_NAME = "qodana.sarif.json"; QODANA_SHORT_SARIF_NAME = "qodana-short.sarif.json"; QODANA_REPORT_URL_NAME = "qodana.cloud"; + QODANA_OPEN_IN_IDE_NAME = "open-in-ide.json"; QODANA_LICENSES_MD = "thirdPartySoftwareList.md"; QODANA_LICENSES_JSON = "thirdPartySoftwareList.json"; EXECUTABLE = "qodana";