Skip to content

Commit

Permalink
♻️ Refactor getting arch / platform and add more docs tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tiulpin committed Nov 30, 2022
1 parent c90adc2 commit 76238ce
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 168 deletions.
80 changes: 37 additions & 43 deletions common/qodana.ts
Expand Up @@ -3,14 +3,16 @@
import {createHash} from 'crypto'
import {readFileSync} from 'fs'

export const SUPPORTED_PLATFORMS = ['windows', 'linux', 'darwin']
export const SUPPORTED_ARCHS = ['x86_64', 'arm64']
export const FAIL_THRESHOLD_OUTPUT =
'The number of problems exceeds the failThreshold'
export const QODANA_SARIF_NAME = 'qodana.sarif.json'
export const QODANA_SHORT_SARIF_NAME = 'qodana-short.sarif.json'
export const VERSION = '2022.2.4'
export const EXECUTABLE = 'qodana'
export function getQodanaSha256(archiveName: string): string {
switch (archiveName) {
export function getQodanaSha256(arch: string, platform: string): string {
switch (`${platform}_${arch}`) {
case 'windows_x86_64':
return '343c7a5e16263ffff12933b96cb6647af338faf3e001b5b66e90b225cd81755b'
case 'windows_arm64':
Expand All @@ -24,39 +26,36 @@ export function getQodanaSha256(archiveName: string): string {
case 'darwin_arm64':
return 'f69c832feb2c223bfa209fc38262e8559e049dca48ca7b387f7aa19b8fa6d637'
default:
throw new Error(`Qodana CLI does not exist for ${archiveName}`)
throw new Error(`Qodana CLI does not exist for ${platform}_${arch}`)
}
}

/**
* Returns the message when Qodana binary is corrupted.
* @param expected expected sha256 checksum
* @param actual actual sha256 checksum
* Returns the architecture name suitable for the published Qodana CLI archive name.
*/
export function getQodanaSha256MismatchMessage(
expected: string,
actual: string
): string {
return `Downloaded Qodana CLI binary is corrupted. Expected SHA-256 checksum: ${expected}, actual checksum: ${actual}`
export function getProcessArchName(): string {
return process.arch === 'x64' ? 'x86_64' : 'arm64'
}

export function getQodanaArchiveName(arch = '', platform = ''): string {
if (arch === '') {
arch = process.arch === 'x64' ? 'x86_64' : 'arm64'
}
if (platform === '') {
platform = process.platform
/**
* Returns the platform name suitable for the published Qodana CLI archive name.
*/
export function getProcessPlatformName(): string {
return process.platform === 'win32' ? 'windows' : process.platform
}

/**
* Gets Qodana CLI download URL from the GitHub Releases API.
*/
export function getQodanaUrl(arch: string, platform: string): string {
if (!SUPPORTED_PLATFORMS.includes(platform)) {
throw new Error(`Unsupported platform: ${platform}`)
}
switch (platform) {
case 'win32':
return `windows_${arch}`
case 'linux':
return `linux_${arch}`
case 'darwin':
return `darwin_${arch}`
default:
throw new Error(`Unsupported platform: ${platform}`)
if (!SUPPORTED_ARCHS.includes(arch)) {
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}`
}

// eslint-disable-next-line no-shadow -- shadowing is intentional here (ESLint bug)
Expand All @@ -74,23 +73,6 @@ export function isExecutionSuccessful(exitCode: number): boolean {
return Object.values(QodanaExitCode).includes(exitCode)
}

/**
* Gets Qodana CLI download URL from the GitHub Releases API.
*/
export function getQodanaUrl(arch = '', platform = ''): string {
if (arch === '') {
arch = process.arch === 'x64' ? 'x86_64' : 'arm64'
}
if (platform === '') {
platform = process.platform
}
const archive = platform === 'win32' ? 'zip' : 'tar.gz'
return `https://github.com/JetBrains/qodana-cli/releases/download/v${VERSION}/qodana_${getQodanaArchiveName(
arch,
platform
)}.${archive}`
}

/**
* Finds the wanted argument value in the given args, if there is one.
* @param argShort the short argument name.
Expand Down Expand Up @@ -182,3 +164,15 @@ export function sha256sum(file: string): string {
hash.update(readFileSync(file))
return hash.digest('hex')
}

/**
* Returns the message when Qodana binary is corrupted.
* @param expected expected sha256 checksum
* @param actual actual sha256 checksum
*/
export function getQodanaSha256MismatchMessage(
expected: string,
actual: string
): string {
return `Downloaded Qodana CLI binary is corrupted. Expected SHA-256 checksum: ${expected}, actual checksum: ${actual}`
}
66 changes: 44 additions & 22 deletions scan/__tests__/main.test.ts
Expand Up @@ -6,8 +6,9 @@ import {
getQodanaScanArgs,
Inputs,
getQodanaUrl,
getQodanaArchiveName,
VERSION
VERSION,
SUPPORTED_PLATFORMS,
SUPPORTED_ARCHS
} from '../../common/qodana'
import * as fs from 'fs'

Expand Down Expand Up @@ -113,14 +114,51 @@ test('test sarif with no problems to output annotations', () => {
expect(result).toEqual(output)
})

test('check whether action README.md has the latest version mentioned everywhere', () => {
const readmeMd = fs.readFileSync(
path.join(__dirname, '..', '..', 'README.md'),
'utf8'
)
const mentions =
readmeMd.match(/uses: JetBrains\/qodana-action@v\d+\.\d+\.\d+/g) || []
expect(mentions.length > 0).toEqual(true)
for (const mention of mentions) {
expect(mention).toEqual(`uses: JetBrains/qodana-action@v${VERSION}`)
}
})

test('check whether Azure Pipelines task.json definitions is up to date', () => {
const taskJson = JSON.parse(
fs.readFileSync(
path.join(__dirname, '..', '..', 'vsts', 'QodanaScan', 'task.json'),
'utf8'
)
)
expect(
`${taskJson.version.Major}.${taskJson.version.Minor}.${taskJson.version.Patch}`
).toEqual(VERSION)
})

test('check whether Azure Pipelines README.md has the latest major version mentioned', () => {
const readmeMd = fs.readFileSync(
path.join(__dirname, '..', '..', 'vsts', 'README.md'),
'utf8'
)
const mentions = readmeMd.match(/ - task: QodanaScan@\d+/g) || []
expect(mentions.length > 0).toEqual(true)
for (const mention of mentions) {
expect(mention).toEqual(` - task: QodanaScan@${VERSION.split('.')[0]}`)
}
})

test('download all Qodana CLI archives and check their checksums', async () => {
for (const arch of ['x86_64', 'arm64']) {
for (const platform of ['win32', 'linux', 'darwin']) {
for (const arch of SUPPORTED_ARCHS) {
for (const platform of SUPPORTED_PLATFORMS) {
const url = getQodanaUrl(arch, platform)
const archiveName = getQodanaArchiveName(arch, platform)
const archiveName = `${platform}_${arch}`
const temp = path.join(os.tmpdir(), archiveName)
execSync(`curl -L ${url} -o ${temp}`)
const expectedSha256 = getQodanaSha256(archiveName)
const expectedSha256 = getQodanaSha256(arch, platform)
const actualSha256 = sha256sum(temp)
expect(`${archiveName}: ${actualSha256}`).toEqual(
`${archiveName}: ${expectedSha256}`
Expand All @@ -129,19 +167,3 @@ test('download all Qodana CLI archives and check their checksums', async () => {
}
}
})

test('check whether Azure Pipelines task.json definitions is up to date', () => {
const taskJson = JSON.parse(
fs.readFileSync(path.join(__dirname, '..', '..', 'vsts', 'QodanaScan', 'task.json'), 'utf8')
)
expect(`${taskJson.version.Major}.${taskJson.version.Minor}.${taskJson.version.Patch}`).toEqual(VERSION)
})

test('check whether action README.md contains the latest version mentioned everywhere', () => {
const readmeMd = fs.readFileSync(path.join(__dirname, '..', '..', 'README.md'), 'utf8')
const mentions = readmeMd.match(/uses: JetBrains\/qodana-action@v\d+\.\d+\.\d+/g) || []
expect(mentions.length > 0).toEqual(true)
for (const mention of mentions??[]) {
expect(mention).toEqual(`uses: JetBrains/qodana-action@v${VERSION}`)
}
})
70 changes: 33 additions & 37 deletions scan/dist/index.js
Expand Up @@ -2779,9 +2779,12 @@ __export(qodana_exports, {
QODANA_SARIF_NAME: () => QODANA_SARIF_NAME,
QODANA_SHORT_SARIF_NAME: () => QODANA_SHORT_SARIF_NAME,
QodanaExitCode: () => QodanaExitCode,
SUPPORTED_ARCHS: () => SUPPORTED_ARCHS,
SUPPORTED_PLATFORMS: () => SUPPORTED_PLATFORMS,
VERSION: () => VERSION,
extractArg: () => extractArg,
getQodanaArchiveName: () => getQodanaArchiveName,
getProcessArchName: () => getProcessArchName,
getProcessPlatformName: () => getProcessPlatformName,
getQodanaPullArgs: () => getQodanaPullArgs,
getQodanaScanArgs: () => getQodanaScanArgs,
getQodanaSha256: () => getQodanaSha256,
Expand All @@ -2790,8 +2793,8 @@ __export(qodana_exports, {
isExecutionSuccessful: () => isExecutionSuccessful,
sha256sum: () => sha256sum
});
function getQodanaSha256(archiveName) {
switch (archiveName) {
function getQodanaSha256(arch, platform) {
switch (`${platform}_${arch}`) {
case "windows_x86_64":
return "343c7a5e16263ffff12933b96cb6647af338faf3e001b5b66e90b225cd81755b";
case "windows_arm64":
Expand All @@ -2805,43 +2808,28 @@ function getQodanaSha256(archiveName) {
case "darwin_arm64":
return "f69c832feb2c223bfa209fc38262e8559e049dca48ca7b387f7aa19b8fa6d637";
default:
throw new Error(`Qodana CLI does not exist for ${archiveName}`);
throw new Error(`Qodana CLI does not exist for ${platform}_${arch}`);
}
}
function getQodanaSha256MismatchMessage(expected, actual) {
return `Downloaded Qodana CLI binary is corrupted. Expected SHA-256 checksum: ${expected}, actual checksum: ${actual}`;
function getProcessArchName() {
return process.arch === "x64" ? "x86_64" : "arm64";
}
function getQodanaArchiveName(arch = "", platform = "") {
if (arch === "") {
arch = process.arch === "x64" ? "x86_64" : "arm64";
}
if (platform === "") {
platform = process.platform;
function getProcessPlatformName() {
return process.platform === "win32" ? "windows" : process.platform;
}
function getQodanaUrl(arch, platform) {
if (!SUPPORTED_PLATFORMS.includes(platform)) {
throw new Error(`Unsupported platform: ${platform}`);
}
switch (platform) {
case "win32":
return `windows_${arch}`;
case "linux":
return `linux_${arch}`;
case "darwin":
return `darwin_${arch}`;
default:
throw new Error(`Unsupported platform: ${platform}`);
if (!SUPPORTED_ARCHS.includes(arch)) {
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}`;
}
function isExecutionSuccessful(exitCode) {
return Object.values(QodanaExitCode).includes(exitCode);
}
function getQodanaUrl(arch = "", platform = "") {
if (arch === "") {
arch = process.arch === "x64" ? "x86_64" : "arm64";
}
if (platform === "") {
platform = process.platform;
}
const archive = platform === "win32" ? "zip" : "tar.gz";
return `https://github.com/JetBrains/qodana-cli/releases/download/v${VERSION}/qodana_${getQodanaArchiveName(arch, platform)}.${archive}`;
}
function extractArg(argShort, argLong, args) {
let arg = "";
for (let i = 0; i < args.length; i++) {
Expand Down Expand Up @@ -2883,30 +2871,36 @@ function sha256sum(file) {
hash.update((0, import_fs.readFileSync)(file));
return hash.digest("hex");
}
var import_crypto, import_fs, FAIL_THRESHOLD_OUTPUT, QODANA_SARIF_NAME, QODANA_SHORT_SARIF_NAME, VERSION, EXECUTABLE, QodanaExitCode;
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, VERSION, EXECUTABLE, QodanaExitCode;
var init_qodana = __esm({
"../common/qodana.ts"() {
import_crypto = require("crypto");
import_fs = require("fs");
SUPPORTED_PLATFORMS = ["windows", "linux", "darwin"];
SUPPORTED_ARCHS = ["x86_64", "arm64"];
FAIL_THRESHOLD_OUTPUT = "The number of problems exceeds the failThreshold";
QODANA_SARIF_NAME = "qodana.sarif.json";
QODANA_SHORT_SARIF_NAME = "qodana-short.sarif.json";
VERSION = "2022.2.4";
EXECUTABLE = "qodana";
__name(getQodanaSha256, "getQodanaSha256");
__name(getQodanaSha256MismatchMessage, "getQodanaSha256MismatchMessage");
__name(getQodanaArchiveName, "getQodanaArchiveName");
__name(getProcessArchName, "getProcessArchName");
__name(getProcessPlatformName, "getProcessPlatformName");
__name(getQodanaUrl, "getQodanaUrl");
QodanaExitCode = /* @__PURE__ */ ((QodanaExitCode2) => {
QodanaExitCode2[QodanaExitCode2["Success"] = 0] = "Success";
QodanaExitCode2[QodanaExitCode2["FailThreshold"] = 255] = "FailThreshold";
return QodanaExitCode2;
})(QodanaExitCode || {});
__name(isExecutionSuccessful, "isExecutionSuccessful");
__name(getQodanaUrl, "getQodanaUrl");
__name(extractArg, "extractArg");
__name(getQodanaPullArgs, "getQodanaPullArgs");
__name(getQodanaScanArgs, "getQodanaScanArgs");
__name(sha256sum, "sha256sum");
__name(getQodanaSha256MismatchMessage, "getQodanaSha256MismatchMessage");
}
});

Expand Down Expand Up @@ -72440,8 +72434,10 @@ var require_utils7 = __commonJS({
exports2.qodana = qodana;
function prepareAgent(args) {
return __awaiter2(this, void 0, void 0, function* () {
const temp = yield tc.downloadTool((0, qodana_12.getQodanaUrl)());
const expectedChecksum = (0, qodana_12.getQodanaSha256)((0, qodana_12.getQodanaArchiveName)());
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));
Expand Down
2 changes: 1 addition & 1 deletion scan/package.json
Expand Up @@ -11,7 +11,7 @@
"package": "./node_modules/.bin/esbuild lib/main.js --platform=node --keep-names --bundle --outfile=dist/index.js",
"test": "jest",
"readme": "cp ../.github/md/github.md ../README.md && curl -sS https://raw.githubusercontent.com/JetBrains/Qodana/2022.2/topics/github.md >> ../README.md && cat ../.github/md/tracker.md >> ../README.md",
"all": "npm install && npm run build && npm run format && npm run lint && npm test && npm run package && npm run readme"
"all": "npm install && npm run build && npm run format && npm run lint && npm test && npm run package"
},
"contributors": [
{
Expand Down
9 changes: 6 additions & 3 deletions scan/src/utils.ts
Expand Up @@ -9,7 +9,8 @@ import {
EXECUTABLE,
Inputs,
VERSION,
getQodanaArchiveName,
getProcessArchName,
getProcessPlatformName,
getQodanaPullArgs,
getQodanaScanArgs,
getQodanaSha256,
Expand Down Expand Up @@ -70,8 +71,10 @@ export async function qodana(args: string[] = []): Promise<number> {
* @param args qodana arguments
*/
export async function prepareAgent(args: string[]): Promise<void> {
const temp = await tc.downloadTool(getQodanaUrl())
const expectedChecksum = getQodanaSha256(getQodanaArchiveName())
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(
Expand Down

0 comments on commit 76238ce

Please sign in to comment.