Skip to content

Commit

Permalink
⬆️ Azure DevOps should support pr-mode flag
Browse files Browse the repository at this point in the history
  • Loading branch information
hybloid authored and tiulpin committed Dec 20, 2024
1 parent 6bdac20 commit f060199
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 8 deletions.
73 changes: 71 additions & 2 deletions vsts/QodanaScan/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14690,6 +14690,7 @@ var require_utils3 = __commonJS({
var tool = __importStar2(require_tool());
var qodana_12 = (init_qodana(), __toCommonJS(qodana_exports));
var path2 = require("path");
var node_stream_1 = require("node:stream");
function setFailed(message) {
tl2.setResult(tl2.TaskResult.Failed, message);
}
Expand All @@ -14703,28 +14704,39 @@ var require_utils3 = __commonJS({
uploadSarif: tl2.getBoolInput("uploadSarif", false) || true,
artifactName: tl2.getInput("artifactName", false) || "qodana-report",
useNightly: tl2.getBoolInput("useNightly", false) || false,
prMode: tl2.getBoolInput("prMode", false) || false,
// Not used by the Azure task
postComment: false,
additionalCacheKey: "",
primaryCacheKey: "",
useAnnotations: false,
useCaches: false,
cacheDefaultBranchOnly: false,
prMode: false,
githubToken: "",
pushFixes: "none",
commitMessage: ""
};
}
function qodana() {
return __awaiter2(this, arguments, void 0, function* (args = []) {
const env = Object.assign(Object.assign({}, process.env), { NONINTERACTIVE: "1" });
if (args.length === 0) {
const inputs = getInputs();
args = (0, qodana_12.getQodanaScanArgs)(inputs.args, inputs.resultsDir, inputs.cacheDir);
if (inputs.prMode && tl2.getVariable("Build.Reason") === "PullRequest") {
const sha = yield getPrSha();
if (sha !== "") {
args.push("--commit", sha);
const sourceBranch = process.env.QODANA_BRANCH || getSourceAndTargetBranches().sourceBranch;
if (sourceBranch) {
env.QODANA_BRANCH = sourceBranch;
}
}
}
}
return yield tl2.execAsync(qodana_12.EXECUTABLE, args, {
ignoreReturnCode: true,
env: Object.assign(Object.assign({}, process.env), { NONINTERACTIVE: "1" })
env
});
});
}
Expand Down Expand Up @@ -14783,6 +14795,63 @@ var require_utils3 = __commonJS({
tl2.warning(`Failed to upload SARIF \u2013 ${error.message}`);
}
}
function getSourceAndTargetBranches() {
var _a, _b;
const sourceBranch = (_a = tl2.getVariable("System.PullRequest.SourceBranch")) === null || _a === void 0 ? void 0 : _a.replace("refs/heads/", "");
const targetBranch = (_b = tl2.getVariable("System.PullRequest.TargetBranch")) === null || _b === void 0 ? void 0 : _b.replace("refs/heads/", "");
return { sourceBranch, targetBranch };
}
function getPrSha() {
return __awaiter2(this, void 0, void 0, function* () {
if (process.env.QODANA_PR_SHA) {
return process.env.QODANA_PR_SHA;
}
const { sourceBranch, targetBranch } = getSourceAndTargetBranches();
if (sourceBranch && targetBranch) {
yield git(["fetch", "origin"]);
const output = yield gitOutput(["merge-base", "origin/" + sourceBranch, "origin/" + targetBranch], {
ignoreReturnCode: true
});
if (output.exitCode === 0) {
const lines = output.stdout.trim().split("\n");
if (lines.length > 1) {
return lines[1].trim();
}
}
}
return "";
});
}
function git(args_1) {
return __awaiter2(this, arguments, void 0, function* (args, options = {}) {
return (yield gitOutput(args, options)).exitCode;
});
}
function gitOutput(args_1) {
return __awaiter2(this, arguments, void 0, function* (args, options = {}) {
const result = {
exitCode: 0,
stdout: "",
stderr: ""
};
const outStream = new node_stream_1.Writable({
write(chunk, _, callback) {
result.stdout += chunk.toString("utf8");
callback();
}
});
const errStream = new node_stream_1.Writable({
write(chunk, _, callback) {
result.stderr += chunk.toString("utf8");
callback();
}
});
options.outStream = outStream;
options.errStream = errStream;
result.exitCode = yield tl2.execAsync("git", args, options);
return result;
});
}
}
});

Expand Down
8 changes: 8 additions & 0 deletions vsts/QodanaScan/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@
"defaultValue": false,
"required": false,
"helpMarkDown": "This option is for development purposes only. Do not use it in production."
},
{
"name": "prMode",
"type": "boolean",
"label": "PR Mode",
"defaultValue": false,
"required": false,
"helpMarkDown": "Whether the PR analysis gets executed in the pull request mode."
}
],
"execution": {
Expand Down
1 change: 1 addition & 0 deletions vsts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ You probably won't need other options than `args`: all other options can be help
| `uploadSarif` | Upload qodana.sarif.json as an qodana.sarif artifact to the job. Optional. | `true` |
| `artifactName` | Specify Qodana results artifact name, used for results uploading. Optional. | `qodana-report` |
| `cacheDir` | Directory to store Qodana caches. Optional. | `$(Agent.TempDirectory)/qodana/cache` |
| `prMode` | Analyze ONLY changed files in a pull request. Optional. | `false` |

[gh:qodana]: https://github.com/JetBrains/qodana-action/actions/workflows/code_scanning.yml
[youtrack]: https://youtrack.jetbrains.com/issues/QD
Expand Down
100 changes: 95 additions & 5 deletions vsts/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import {

// eslint-disable-next-line @typescript-eslint/no-require-imports
import path = require('path')
import {IExecOptions} from 'azure-pipelines-task-lib/toolrunner'
import {Writable} from 'node:stream'

export function setFailed(message: string): void {
tl.setResult(tl.TaskResult.Failed, message)
Expand All @@ -54,14 +56,14 @@ export function getInputs(): Inputs {
uploadSarif: tl.getBoolInput('uploadSarif', false) || true,
artifactName: tl.getInput('artifactName', false) || 'qodana-report',
useNightly: tl.getBoolInput('useNightly', false) || false,
prMode: tl.getBoolInput('prMode', false) || false,
// Not used by the Azure task
postComment: false,
additionalCacheKey: '',
primaryCacheKey: '',
useAnnotations: false,
useCaches: false,
cacheDefaultBranchOnly: false,
prMode: false,
githubToken: '',
pushFixes: 'none',
commitMessage: ''
Expand All @@ -74,16 +76,28 @@ export function getInputs(): Inputs {
* @returns The qodana command execution output.
*/
export async function qodana(args: string[] = []): Promise<number> {
const env: Record<string, string> = {
...process.env,
NONINTERACTIVE: '1'
}
if (args.length === 0) {
const inputs = getInputs()
args = getQodanaScanArgs(inputs.args, inputs.resultsDir, inputs.cacheDir)
if (inputs.prMode && tl.getVariable('Build.Reason') === 'PullRequest') {
const sha = await getPrSha()
if (sha !== '') {
args.push('--commit', sha)
const sourceBranch =
process.env.QODANA_BRANCH || getSourceAndTargetBranches().sourceBranch
if (sourceBranch) {
env.QODANA_BRANCH = sourceBranch
}
}
}
}
return await tl.execAsync(EXECUTABLE, args, {
ignoreReturnCode: true,
env: {
...process.env,
NONINTERACTIVE: '1'
}
env
})
}

Expand Down Expand Up @@ -171,3 +185,79 @@ export function uploadSarif(resultsDir: string, execute: boolean): void {
tl.warning(`Failed to upload SARIF – ${(error as Error).message}`)
}
}

function getSourceAndTargetBranches(): {
sourceBranch?: string
targetBranch?: string
} {
const sourceBranch = tl
.getVariable('System.PullRequest.SourceBranch')
?.replace('refs/heads/', '')
const targetBranch = tl
.getVariable('System.PullRequest.TargetBranch')
?.replace('refs/heads/', '')
return {sourceBranch, targetBranch}
}

async function getPrSha(): Promise<string> {
if (process.env.QODANA_PR_SHA) {
return process.env.QODANA_PR_SHA
}
const {sourceBranch, targetBranch} = getSourceAndTargetBranches()

if (sourceBranch && targetBranch) {
await git(['fetch', 'origin'])
const output = await gitOutput(
['merge-base', 'origin/' + sourceBranch, 'origin/' + targetBranch],
{
ignoreReturnCode: true
}
)
if (output.exitCode === 0) {
const lines = output.stdout.trim().split('\n')
if (lines.length > 1) {
return lines[1].trim()
}
}
}
return ''
}

async function git(
args: string[],
options: IExecOptions = {}
): Promise<number> {
return (await gitOutput(args, options)).exitCode
}

async function gitOutput(
args: string[],
options: IExecOptions = {}
): Promise<{exitCode: number; stderr: string; stdout: string}> {
const result = {
exitCode: 0,
stdout: '',
stderr: ''
}

const outStream = new Writable({
write(chunk, _, callback) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
result.stdout += chunk.toString('utf8')
callback()
}
})

const errStream = new Writable({
write(chunk, _, callback) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
result.stderr += chunk.toString('utf8')
callback()
}
})
options.outStream = outStream
options.errStream = errStream

result.exitCode = await tl.execAsync('git', args, options)
return result
}
2 changes: 1 addition & 1 deletion vsts/vss-extension.dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifestVersion": 1,
"id": "qodana-dev",
"name": "Qodana (Dev)",
"version": "2024.3.135",
"version": "2024.3.146",
"publisher": "JetBrains",
"targets": [
{
Expand Down

0 comments on commit f060199

Please # to comment.