diff --git a/common/__tests__/main.test.ts b/common/__tests__/main.test.ts
index 76c41e99..c03d04b9 100644
--- a/common/__tests__/main.test.ts
+++ b/common/__tests__/main.test.ts
@@ -24,18 +24,36 @@ import * as fs from 'fs'
import * as path from 'path'
import * as os from 'os'
-test('test passed coverage output', () => {
+test('test passed coverage output using diff', () => {
const result = getCoverageStats(
- getCoverageFromSarif('__tests__/data/some.sarif.json')
+ getCoverageFromSarif('__tests__/data/some.sarif.json'),
+ true
)
- expect(result).toEqual(passedCoverageFixture())
+ expect(result).toEqual(passedCoverageFixtureDiff())
})
-test('test failed coverage output', () => {
+test('test failed coverage output using diff', () => {
const result = getCoverageStats(
- getCoverageFromSarif('__tests__/data/empty.sarif.json')
+ getCoverageFromSarif('__tests__/data/empty.sarif.json'),
+ true
)
- expect(result).toEqual(failedCoverageFixture())
+ expect(result).toEqual(failedCoverageFixtureDiff())
+})
+
+test('test passed coverage output using spam', () => {
+ const result = getCoverageStats(
+ getCoverageFromSarif('__tests__/data/some.sarif.json'),
+ false
+ )
+ expect(result).toEqual(passedCoverageFixtureSpam())
+})
+
+test('test failed coverage output using spam', () => {
+ const result = getCoverageStats(
+ getCoverageFromSarif('__tests__/data/empty.sarif.json'),
+ false
+ )
+ expect(result).toEqual(failedCoverageFixtureSpam())
})
describe('getReportURL', () => {
@@ -90,7 +108,25 @@ describe('getReportURL', () => {
})
})
-function passedCoverageFixture(): string {
+function passedCoverageFixtureSpam(): string {
+ return `@@ Code coverage @@
+45% total lines covered
+124 lines analyzed, 56 lines covered
+33% fresh lines covered
+9 lines analyzed, 3 lines covered
+# Calculated according to the filters of your coverage tool`
+}
+
+function failedCoverageFixtureSpam(): string {
+ return `@@ Code coverage @@
+0% total lines covered
+100 lines analyzed, 0 lines covered
+0% fresh lines covered
+100 lines analyzed, 0 lines covered
+# Calculated according to the filters of your coverage tool`
+}
+
+function passedCoverageFixtureDiff(): string {
return `\`\`\`diff
@@ Code coverage @@
+ 45% total lines covered
@@ -101,7 +137,7 @@ function passedCoverageFixture(): string {
\`\`\``
}
-function failedCoverageFixture(): string {
+function failedCoverageFixtureDiff(): string {
return `\`\`\`diff
@@ Code coverage @@
- 0% total lines covered
diff --git a/common/output.ts b/common/output.ts
index a348a69d..2f828170 100644
--- a/common/output.ts
+++ b/common/output.ts
@@ -99,16 +99,19 @@ ${message}
function makeConclusion(
conclusion: string,
- failedByThreshold: boolean
+ failedByThreshold: boolean,
+ useDiffBlock: boolean,
): string {
- if (failedByThreshold) {
- return `- ${conclusion}`
+ if (useDiffBlock) {
+ return failedByThreshold ? `- ${conclusion}` : `+ ${conclusion}`
} else {
- return `+ ${conclusion}`
+ return failedByThreshold
+ ? `${conclusion}`
+ : `${conclusion}`
}
}
-export function getCoverageStats(c: Coverage): string {
+export function getCoverageStats(c: Coverage, useDiffBlock: boolean): string {
if (c.totalLines === 0 && c.totalCoveredLines === 0) {
return ''
}
@@ -116,24 +119,23 @@ export function getCoverageStats(c: Coverage): string {
let stats = ''
if (c.totalLines !== 0) {
const conclusion = `${c.totalCoverage}% total lines covered`
- stats += `${makeConclusion(conclusion, c.totalCoverage < c.totalCoverageThreshold)}
+ stats += `${makeConclusion(conclusion, c.totalCoverage < c.totalCoverageThreshold, useDiffBlock)}
${c.totalLines} lines analyzed, ${c.totalCoveredLines} lines covered`
}
if (c.freshLines !== 0) {
const conclusion = `${c.freshCoverage}% fresh lines covered`
stats += `
-${makeConclusion(conclusion, c.freshCoverage < c.freshCoverageThreshold)}
+${makeConclusion(conclusion, c.freshCoverage < c.freshCoverageThreshold, useDiffBlock)}
${c.freshLines} lines analyzed, ${c.freshCoveredLines} lines covered`
}
- return wrapToDiffBlock(
- [
- `@@ Code coverage @@`,
- `${stats}`,
- `# Calculated according to the filters of your coverage tool`
- ].join('\n')
- )
+ const coverageBlock = [
+ `@@ Code coverage @@`,
+ `${stats}`,
+ `# Calculated according to the filters of your coverage tool`
+ ].join('\n')
+ return useDiffBlock ? wrapToDiffBlock(coverageBlock) : coverageBlock
}
export function getLicenseInfo(
diff --git a/scan/dist/index.js b/scan/dist/index.js
index 2d327a51..1a0a2104 100644
--- a/scan/dist/index.js
+++ b/scan/dist/index.js
@@ -137016,36 +137016,35 @@ function wrapToDiffBlock(message) {
${message}
\`\`\``;
}
-function makeConclusion(conclusion, failedByThreshold) {
- if (failedByThreshold) {
- return `- ${conclusion}`;
+function makeConclusion(conclusion, failedByThreshold, useDiffBlock) {
+ if (useDiffBlock) {
+ return failedByThreshold ? `- ${conclusion}` : `+ ${conclusion}`;
} else {
- return `+ ${conclusion}`;
+ return failedByThreshold ? `${conclusion}` : `${conclusion}`;
}
}
-function getCoverageStats(c) {
+function getCoverageStats(c, useDiffBlock) {
if (c.totalLines === 0 && c.totalCoveredLines === 0) {
return "";
}
let stats = "";
if (c.totalLines !== 0) {
const conclusion = `${c.totalCoverage}% total lines covered`;
- stats += `${makeConclusion(conclusion, c.totalCoverage < c.totalCoverageThreshold)}
+ stats += `${makeConclusion(conclusion, c.totalCoverage < c.totalCoverageThreshold, useDiffBlock)}
${c.totalLines} lines analyzed, ${c.totalCoveredLines} lines covered`;
}
if (c.freshLines !== 0) {
const conclusion = `${c.freshCoverage}% fresh lines covered`;
stats += `
-${makeConclusion(conclusion, c.freshCoverage < c.freshCoverageThreshold)}
+${makeConclusion(conclusion, c.freshCoverage < c.freshCoverageThreshold, useDiffBlock)}
${c.freshLines} lines analyzed, ${c.freshCoveredLines} lines covered`;
}
- return wrapToDiffBlock(
- [
- `@@ Code coverage @@`,
- `${stats}`,
- `# Calculated according to the filters of your coverage tool`
- ].join("\n")
- );
+ const coverageBlock = [
+ `@@ Code coverage @@`,
+ `${stats}`,
+ `# Calculated according to the filters of your coverage tool`
+ ].join("\n");
+ return useDiffBlock ? wrapToDiffBlock(coverageBlock) : coverageBlock;
}
function getLicenseInfo(resultsDir) {
let licensesInfo = "";
@@ -137558,7 +137557,7 @@ so that the action will upload the files as the job artifacts:
try {
const problems = (0, annotations_1.parseSarif)(`${resultsDir}/${qodana_12.QODANA_SARIF_NAME}`);
const reportUrl = (0, output_12.getReportURL)(resultsDir);
- const coverageInfo = (0, output_12.getCoverageStats)((0, qodana_12.getCoverageFromSarif)(`${resultsDir}/${qodana_12.QODANA_SHORT_SARIF_NAME}`));
+ const coverageInfo = (0, output_12.getCoverageStats)((0, qodana_12.getCoverageFromSarif)(`${resultsDir}/${qodana_12.QODANA_SHORT_SARIF_NAME}`), true);
const licensesInfo = (0, output_12.getLicenseInfo)(resultsDir);
const problemsDescriptions = annotationsToProblemDescriptors(problems.annotations);
const toolName = (_a = problems.title.split("found by ")[1]) !== null && _a !== void 0 ? _a : output_12.QODANA_CHECK_NAME;
diff --git a/scan/src/output.ts b/scan/src/output.ts
index 9f324bd9..fc53820f 100644
--- a/scan/src/output.ts
+++ b/scan/src/output.ts
@@ -93,7 +93,8 @@ export async function publishOutput(
const problems = parseSarif(`${resultsDir}/${QODANA_SARIF_NAME}`)
const reportUrl = getReportURL(resultsDir)
const coverageInfo = getCoverageStats(
- getCoverageFromSarif(`${resultsDir}/${QODANA_SHORT_SARIF_NAME}`)
+ getCoverageFromSarif(`${resultsDir}/${QODANA_SHORT_SARIF_NAME}`),
+ true
)
const licensesInfo: LicenseInfo = getLicenseInfo(resultsDir)
diff --git a/vsts/QodanaScan/index.js b/vsts/QodanaScan/index.js
index 0a5d5a22..ded668ca 100644
--- a/vsts/QodanaScan/index.js
+++ b/vsts/QodanaScan/index.js
@@ -16877,36 +16877,35 @@ function wrapToDiffBlock(message) {
${message}
\`\`\``;
}
-function makeConclusion(conclusion, failedByThreshold) {
- if (failedByThreshold) {
- return `- ${conclusion}`;
+function makeConclusion(conclusion, failedByThreshold, useDiffBlock) {
+ if (useDiffBlock) {
+ return failedByThreshold ? `- ${conclusion}` : `+ ${conclusion}`;
} else {
- return `+ ${conclusion}`;
+ return failedByThreshold ? `${conclusion}` : `${conclusion}`;
}
}
-function getCoverageStats(c) {
+function getCoverageStats(c, useDiffBlock) {
if (c.totalLines === 0 && c.totalCoveredLines === 0) {
return "";
}
let stats = "";
if (c.totalLines !== 0) {
const conclusion = `${c.totalCoverage}% total lines covered`;
- stats += `${makeConclusion(conclusion, c.totalCoverage < c.totalCoverageThreshold)}
+ stats += `${makeConclusion(conclusion, c.totalCoverage < c.totalCoverageThreshold, useDiffBlock)}
${c.totalLines} lines analyzed, ${c.totalCoveredLines} lines covered`;
}
if (c.freshLines !== 0) {
const conclusion = `${c.freshCoverage}% fresh lines covered`;
stats += `
-${makeConclusion(conclusion, c.freshCoverage < c.freshCoverageThreshold)}
+${makeConclusion(conclusion, c.freshCoverage < c.freshCoverageThreshold, useDiffBlock)}
${c.freshLines} lines analyzed, ${c.freshCoveredLines} lines covered`;
}
- return wrapToDiffBlock(
- [
- `@@ Code coverage @@`,
- `${stats}`,
- `# Calculated according to the filters of your coverage tool`
- ].join("\n")
- );
+ const coverageBlock = [
+ `@@ Code coverage @@`,
+ `${stats}`,
+ `# Calculated according to the filters of your coverage tool`
+ ].join("\n");
+ return useDiffBlock ? wrapToDiffBlock(coverageBlock) : coverageBlock;
}
function getLicenseInfo(resultsDir) {
let licensesInfo = "";
@@ -79048,7 +79047,7 @@ so that the action will upload the files as the job artifacts:
try {
const problems = (0, utils_12.parseSarif)(`${resultsDir}/${qodana_12.QODANA_SARIF_NAME}`);
const reportUrl = (0, output_12.getReportURL)(resultsDir);
- const coverageInfo = (0, output_12.getCoverageStats)((0, qodana_12.getCoverageFromSarif)(`${resultsDir}/${qodana_12.QODANA_SHORT_SARIF_NAME}`));
+ const coverageInfo = (0, output_12.getCoverageStats)((0, qodana_12.getCoverageFromSarif)(`${resultsDir}/${qodana_12.QODANA_SHORT_SARIF_NAME}`), false);
const licensesInfo = (0, output_12.getLicenseInfo)(resultsDir);
const problemsDescriptions = (_a = problems.problemDescriptions) !== null && _a !== void 0 ? _a : [];
const toolName = (_b = problems.title.split("found by ")[1]) !== null && _b !== void 0 ? _b : output_12.QODANA_CHECK_NAME;
@@ -79185,10 +79184,10 @@ var require_utils4 = __commonJS({
uploadSarif: tl2.getBoolInput("uploadSarif", false),
artifactName: tl2.getInput("artifactName", false) || "qodana-report",
useNightly: tl2.getBoolInput("useNightly", false),
- prMode: tl2.getBoolInput("prMode", true),
+ prMode: tl2.getBoolInput("prMode", false),
postComment: tl2.getBoolInput("postPrComment", false),
pushFixes: tl2.getInput("pushFixes", false) || "none",
- commitMessage: tl2.getInput("commitMessage", false) || "\u{1F916} Apply quick-fixes by Qodana",
+ commitMessage: tl2.getInput("commitMessage", false) || "\u{1F916} Apply quick-fixes by Qodana \n\n[skip ci]",
// Not used by the Azure task
additionalCacheKey: "",
primaryCacheKey: "",
@@ -79466,11 +79465,9 @@ ${comment_tag_pattern}`;
return;
}
if (mode === qodana_12.BRANCH) {
- if (pullRequest) {
- const commitToCherryPick = (yield gitOutput(["rev-parse", "HEAD"])).stdout.trim();
- yield git(["checkout", currentBranch]);
- yield git(["cherry-pick", commitToCherryPick]);
- }
+ const commitToCherryPick = (yield gitOutput(["rev-parse", "HEAD"])).stdout.trim();
+ yield git(["checkout", currentBranch]);
+ yield git(["cherry-pick", commitToCherryPick]);
yield gitPush(currentBranch);
} else if (mode === qodana_12.PULL_REQUEST) {
const newBranch = `qodana/quick-fixes-${currentCommit.slice(0, 7)}`;
@@ -79488,9 +79485,7 @@ ${comment_tag_pattern}`;
const output = yield gitOutput(["push", "origin", branch], {
ignoreReturnCode: true
});
- if (output.exitCode == 1) {
- tl2.warning(`Branch ${branch} already exists. Push of quick-fixes was skipped.`);
- } else if (output.exitCode !== 0) {
+ if (output.exitCode !== 0) {
tl2.warning(`Failed to push branch ${branch}: ${output.stderr}`);
}
});
diff --git a/vsts/QodanaScan/task.json b/vsts/QodanaScan/task.json
index 0536863c..f88c9265 100644
--- a/vsts/QodanaScan/task.json
+++ b/vsts/QodanaScan/task.json
@@ -74,9 +74,33 @@
"name": "prMode",
"type": "boolean",
"label": "PR Mode",
- "defaultValue": false,
+ "defaultValue": true,
"required": false,
"helpMarkDown": "Whether the PR analysis gets executed in the pull request mode."
+ },
+ {
+ "name": "postPrComment",
+ "type": "boolean",
+ "label": "Post PR comment",
+ "defaultValue": true,
+ "required": false,
+ "helpMarkDown": "Post a comment with the Qodana results summary to the pull request."
+ },
+ {
+ "name": "pushFixes",
+ "type": "string",
+ "label": "Push quick-fixes",
+ "defaultValue": "none",
+ "required": false,
+ "helpMarkDown": "Push Qodana fixes to the repository, can be `none`, `branch` to the current branch, or `pull-request`."
+ },
+ {
+ "name": "commitMessage",
+ "type": "string",
+ "label": "Commit Message",
+ "defaultValue": "\uD83E\uDD16 Apply quick-fixes by Qodana\n\n[skip ci]",
+ "required": false,
+ "helpMarkDown": "Message used when quick-fixes are pushed"
}
],
"execution": {
diff --git a/vsts/README.md b/vsts/README.md
index 219a3101..2c5ceefa 100644
--- a/vsts/README.md
+++ b/vsts/README.md
@@ -68,7 +68,7 @@ to
- or `branch`: push fixes to the original branch
3. Set the correct permissions for the job. Go to `Repositories` → `Manage repositories` → `Security`. Choose `Qodana for Azure Pipelines Build Service` user. Allow:
- `Contribute`
- - `Bypass policies when pushing`. Without this, the analysis will be performed twice
+ - `Bypass policies when pushing` if they may fail the push of quick-fixes
- `Create branch` if you use `pull-request` value
Also, set `persistCredentials` property to `true`. This is needed for pushing changes to the repository
diff --git a/vsts/src/output.ts b/vsts/src/output.ts
index 4e9df655..5fd51755 100644
--- a/vsts/src/output.ts
+++ b/vsts/src/output.ts
@@ -69,7 +69,8 @@ export async function publishOutput(
const problems = parseSarif(`${resultsDir}/${QODANA_SARIF_NAME}`)
const reportUrl = getReportURL(resultsDir)
const coverageInfo = getCoverageStats(
- getCoverageFromSarif(`${resultsDir}/${QODANA_SHORT_SARIF_NAME}`)
+ getCoverageFromSarif(`${resultsDir}/${QODANA_SHORT_SARIF_NAME}`),
+ false
)
const licensesInfo = getLicenseInfo(resultsDir)
diff --git a/vsts/src/utils.ts b/vsts/src/utils.ts
index 6198db4a..72b3edbd 100644
--- a/vsts/src/utils.ts
+++ b/vsts/src/utils.ts
@@ -73,11 +73,12 @@ export function getInputs(): Inputs {
uploadSarif: tl.getBoolInput('uploadSarif', false),
artifactName: tl.getInput('artifactName', false) || 'qodana-report',
useNightly: tl.getBoolInput('useNightly', false),
- prMode: tl.getBoolInput('prMode', true),
+ prMode: tl.getBoolInput('prMode', false),
postComment: tl.getBoolInput('postPrComment', false),
pushFixes: tl.getInput('pushFixes', false) || 'none',
commitMessage:
- tl.getInput('commitMessage', false) || '🤖 Apply quick-fixes by Qodana',
+ tl.getInput('commitMessage', false) ||
+ '🤖 Apply quick-fixes by Qodana \n\n[skip ci]',
// Not used by the Azure task
additionalCacheKey: '',
primaryCacheKey: '',
@@ -487,13 +488,11 @@ export async function pushQuickFixes(
return
}
if (mode === BRANCH) {
- if (pullRequest) {
- const commitToCherryPick = (
- await gitOutput(['rev-parse', 'HEAD'])
- ).stdout.trim()
- await git(['checkout', currentBranch])
- await git(['cherry-pick', commitToCherryPick])
- }
+ const commitToCherryPick = (
+ await gitOutput(['rev-parse', 'HEAD'])
+ ).stdout.trim()
+ await git(['checkout', currentBranch])
+ await git(['cherry-pick', commitToCherryPick])
await gitPush(currentBranch)
} else if (mode === PULL_REQUEST) {
const newBranch = `qodana/quick-fixes-${currentCommit.slice(0, 7)}`
@@ -510,11 +509,7 @@ async function gitPush(branch: string): Promise {
const output = await gitOutput(['push', 'origin', branch], {
ignoreReturnCode: true
})
- if (output.exitCode == 1) {
- tl.warning(
- `Branch ${branch} already exists. Push of quick-fixes was skipped.`
- )
- } else if (output.exitCode !== 0) {
+ if (output.exitCode !== 0) {
tl.warning(`Failed to push branch ${branch}: ${output.stderr}`)
}
}
diff --git a/vsts/vss-extension.dev.json b/vsts/vss-extension.dev.json
index c2fda4e0..4fdd55b7 100644
--- a/vsts/vss-extension.dev.json
+++ b/vsts/vss-extension.dev.json
@@ -2,7 +2,7 @@
"manifestVersion": 1,
"id": "qodana-dev",
"name": "Qodana (Dev)",
- "version": "2024.3.195",
+ "version": "2024.3.198",
"publisher": "JetBrains",
"targets": [
{