Skip to content

Commit

Permalink
⚡ Add initial coverage support
Browse files Browse the repository at this point in the history
  • Loading branch information
tiulpin committed Jun 20, 2023
1 parent e6ca5c0 commit b1da29f
Show file tree
Hide file tree
Showing 10 changed files with 386 additions and 142 deletions.
44 changes: 42 additions & 2 deletions common/qodana.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
// noinspection JSUnusedGlobalSymbols
import {checksum, version} from './cli.json'
import {createHash} from 'crypto'
import {readFileSync} from 'fs'
import fs 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 QODANA_REPORT_URL_NAME = 'qodana.cloud'

export const QODANA_LICENSES_MD = 'thirdPartySoftwareList.md'
export const QODANA_LICENSES_JSON = 'thirdPartySoftwareList.json'
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':
Expand Down Expand Up @@ -163,13 +166,50 @@ export interface Inputs {
githubToken: string
}

/**
* The test code coverage information.
*/
export interface Coverage {
totalCoverage: number
totalLines: number
totalCoveredLines: number
}

/**
* Read the coverage information from the SARIF file.
* @param sarifPath the path to the SARIF file.
*/
export function getCoverageFromSarif(sarifPath: string): Coverage {
if (fs.existsSync(sarifPath)) {
const sarifContents = JSON.parse(
fs.readFileSync(sarifPath, {encoding: 'utf8'})
)
if (sarifContents.runs[0].properties['coverage']) {
return {
totalCoverage:
sarifContents.runs[0].properties['coverage']['totalCoverage'],
totalLines: sarifContents.runs[0].properties['coverage']['totalLines'],
totalCoveredLines:
sarifContents.runs[0].properties['coverage']['totalCoveredLines']
}
} else {
return {
totalCoverage: 0,
totalLines: 0,
totalCoveredLines: 0
}
}
}
throw new Error(`SARIF file not found: ${sarifPath}`)
}

/**
* Get the SHA256 checksum of the given file.
* @param file absolute path to the file.
*/
export function sha256sum(file: string): string {
const hash = createHash('sha256')
hash.update(readFileSync(file))
hash.update(fs.readFileSync(file))
return hash.digest('hex')
}

Expand Down
9 changes: 7 additions & 2 deletions qodana.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
version: "1.0"
linter: registry.jetbrains.team/p/sa/containers/qodana-js:latest
bootstrap: npm ci && npm run build && npm run test && mv scan/coverage /data/coverage
bootstrap: npm ci && npm run build && npm run test && mkdir -p /data/coverage && mv scan/coverage/lcov.info /data/coverage && rm -rf scan/coverage
plugins:
- id: com.intellij.grazie.pro
profile:
name: qodana.recommended
name: empty
exclude:
- name: All
paths:
- node_modules/
- common/node_modules/
- scan/node_modules/
- vsts/node_modules/
- scan/jest.config.js
- common/lib
- scan/lib
- scan/dist
- scan/__tests__
Expand Down
8 changes: 7 additions & 1 deletion scan/__tests__/data/empty.sarif.json
Original file line number Diff line number Diff line change
Expand Up @@ -8038,7 +8038,13 @@
"\r\n",
"\n"
],
"properties": {}
"properties": {
"coverage": {
"totalCoverage": 0,
"totalLines": 100,
"totalCoveredLines": 0
}
}
}
]
}
8 changes: 7 additions & 1 deletion scan/__tests__/data/some.sarif.json
Original file line number Diff line number Diff line change
Expand Up @@ -8198,7 +8198,13 @@
"\r\n",
"\n"
],
"properties": {}
"properties": {
"coverage": {
"totalCoverage": 70.0,
"totalLines": 124.0,
"totalCoveredLines": 87.0
}
}
}
]
}
50 changes: 47 additions & 3 deletions scan/__tests__/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import {expect, test} from '@jest/globals'
import {AnnotationProperties} from '@actions/core'
import {getQodanaScanArgs, Inputs} from '../../common/qodana'
import {
getCoverageFromSarif,
getQodanaScanArgs,
Inputs
} from '../../common/qodana'
import {
Annotation,
getGitHubCheckConclusion,
parseSarif,
toAnnotationProperties
} from '../src/annotations'
import {getSummary} from '../src/output'
import {getSummary, getCoverageStats} from '../src/output'

test('qodana scan command args', () => {
const inputs = inputsDefaultFixture()
Expand Down Expand Up @@ -35,6 +39,7 @@ test('test typical summary output', () => {
const result = getSummary(
'Qodana for JS',
annotationsDefaultFixture().reverse(), // reversed for testing the correct sorting in output
'',
'There is no licenses information available',
'https://example.com/report',
true
Expand All @@ -48,11 +53,28 @@ test('test empty summary output', () => {
outputEmptyFixture(),
'',
'',
'',
false
)
expect(result).toEqual(markdownEmptySummaryFixture())
})

test('test passed coverage output', () => {
const result = getCoverageStats(
getCoverageFromSarif('__tests__/data/some.sarif.json'),
50
)
expect(result).toEqual(passedCoverageFixture())
})

test('test failed coverage output', () => {
const result = getCoverageStats(
getCoverageFromSarif('__tests__/data/empty.sarif.json'),
50
)
expect(result).toEqual(failedCoverageFixture())
})

test('check conversion from Checks API Annotations to actions/core AnnotationProperty', () => {
const result = toAnnotationProperties(annotationsDefaultFixture()[0])
expect(result).toEqual(annotationPropertyDefaultFixture())
Expand Down Expand Up @@ -156,7 +178,7 @@ export function defaultDockerRunCommandFixture(): string[] {
}

export function markdownSummaryFixture(): string {
return `# Qodana for JS
return `# [Qodana](https://example.com/report) for JS
**3 new problems** were found
Expand All @@ -166,6 +188,7 @@ export function markdownSummaryFixture(): string {
| \`Condition of 'if' expression is constant\` | 🔶 Warning | 1 |
| \`Might be 'const'\` | ◽️ Notice | 1 |
💡 Qodana analysis was run in the pull request mode: only the changed files were checked
☁️ [View the detailed Qodana report](https://example.com/report)
<details>
Expand All @@ -189,6 +212,7 @@ export function markdownEmptySummaryFixture(): string {
No new problems were found according to the checks applied
<details>
<summary>View the detailed Qodana report</summary>
Expand Down Expand Up @@ -217,3 +241,23 @@ Contact us at [qodana-support@jetbrains.com](mailto:qodana-support@jetbrains.com
- Or share your feedback: https://jb.gg/qodana-discussions
</details>`
}

function passedCoverageFixture(): string {
return `\`\`\`diff
@@ Code coverage @@
✅ PASSED, required line coverage needs to be more than 50%
+ 70% lines covered
124 lines analyzed, 87 lines covered
# Calculated according to the filters of your coverage tool
\`\`\``
}

function failedCoverageFixture(): string {
return `\`\`\`diff
@@ Code coverage @@
❌ FAILED, required line coverage needs to be more than 50%
- 0% lines covered
100 lines analyzed, 0 lines covered
# Calculated according to the filters of your coverage tool
\`\`\``
}

0 comments on commit b1da29f

Please sign in to comment.