Skip to content

Commit 2231f27

Browse files
authored
Add Pipeline for /eng/code-quality-reports (Azure#26196)
1 parent 4477d35 commit 2231f27

File tree

6 files changed

+314
-12
lines changed

6 files changed

+314
-12
lines changed

eng/code-quality-reports/ci.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file.
2+
3+
trigger:
4+
branches:
5+
include:
6+
- main
7+
- hotfix/*
8+
- release/*
9+
paths:
10+
include:
11+
- eng/code-quality-reports/
12+
13+
pr:
14+
branches:
15+
include:
16+
- main
17+
- feature/*
18+
- hotfix/*
19+
- release/*
20+
paths:
21+
include:
22+
- eng/code-quality-reports/
23+
24+
extends:
25+
template: /eng/pipelines/code-quality-reports.yml
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
jobs:
2+
- job: 'Linting'
3+
4+
variables:
5+
- template: /eng/pipelines/templates/variables/globals.yml
6+
7+
pool:
8+
name: azsdk-pool-mms-ubuntu-2004-general
9+
10+
steps:
11+
# Skip sparse checkout for the `azure-sdk-for-<lang>-pr` private mirrored repositories
12+
# as we require the github service connection to be loaded.
13+
- ${{ if not(contains(variables['Build.DefinitionName'], 'java-pr')) }}:
14+
- template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
15+
parameters:
16+
Paths:
17+
# Checkout Core as it triggers building all SDKs that use code-quality-reports
18+
- 'sdk/core'
19+
- '**/*.xml'
20+
- '!sdk/**/test-recordings'
21+
- '!sdk/**/session-records'
22+
23+
- template: /eng/pipelines/steps/install-reporting-tools.yml
24+
25+
- task: UsePythonVersion@0
26+
displayName: 'Use Python 3.6'
27+
inputs:
28+
versionSpec: '3.6'
29+
30+
- task: PythonScript@0
31+
displayName: 'Set versions for source build'
32+
inputs:
33+
scriptPath: 'eng/versioning/set_versions.py'
34+
arguments: '--build-type client --pst'
35+
36+
- task: PythonScript@0
37+
displayName: 'Update versions for source build'
38+
inputs:
39+
scriptPath: 'eng/versioning/update_versions.py'
40+
arguments: '--update-type library --build-type client --sr'
41+
42+
- template: /eng/pipelines/steps/generate-project-list.yml
43+
parameters:
44+
Artifacts:
45+
- name: azure-core
46+
groupId: com.azure
47+
safeName: azurecore
48+
AdditionalModules:
49+
- name: perf-test-core
50+
groupId: com.azure
51+
JobType: 'linting'
52+
SDKType: tools
53+
ServiceDirectory: code-quality-reports
54+
55+
- task: PythonScript@0
56+
displayName: 'Generate directories variable for sparse checkout'
57+
inputs:
58+
scriptPath: 'eng/scripts/generate_from_source_pom.py'
59+
arguments: '--set-pipeline-variable CheckoutDirectories --project-list $(ProjectList)'
60+
workingDirectory: '$(System.DefaultWorkingDirectory)'
61+
62+
- template: /eng/common/pipelines/templates/steps/sparse-checkout.yml
63+
parameters:
64+
SkipDefaultCheckout: true
65+
Paths: $(CheckoutDirectories)
66+
67+
- task: Maven@3
68+
displayName: 'Build Projects'
69+
inputs:
70+
mavenPomFile: ClientFromSourcePom.xml
71+
goals: 'install'
72+
options: '$(DefaultOptions) -T 2C -DskipTests -Dgpg.skip -DtrimStackTrace=false -Dmaven.javadoc.skip=true -Dcodesnippet.skip=true -Dcheckstyle.skip -Dspotbugs.skip -Drevapi.skip=true -Djacoco.skip=true'
73+
mavenOptions: '$(MemoryOptions) $(LoggingOptions)'
74+
javaHomeOption: 'JDKVersion'
75+
jdkVersionOption: $(JavaBuildVersion)
76+
jdkArchitectureOption: 'x64'
77+
publishJUnitResults: false
78+
79+
- task: Maven@3
80+
displayName: 'Run Linting'
81+
inputs:
82+
mavenPomFile: ClientFromSourcePom.xml
83+
goals: 'checkstyle:check spotbugs:check revapi:check'
84+
# Skip failing on Checkstyle, RevApi, and Spotbugs errors.
85+
# This is being done as the error reporting will be captured, so if any error reports exist the build can be
86+
# failed later allowing all libraries to be validated.
87+
options: '$(DefaultOptions) -T 2C -Dcheckstyle.failOnViolation=false -Dcheckstyle.failsOnError=false -Dspotbugs.failOnError=false -Drevapi.failBuildOnProblemsFound=false'
88+
mavenOptions: '$(MemoryOptions) $(LoggingOptions)'
89+
javaHomeOption: 'JDKVersion'
90+
jdkVersionOption: $(JavaBuildVersion)
91+
jdkArchitectureOption: 'x64'
92+
publishJUnitResults: false
93+
94+
- task: Powershell@2
95+
inputs:
96+
filePath: /eng/pipelines/scripts/Get-Linting-Reports.ps1
97+
arguments: -OutputDirectory $(Build.ArtifactStagingDirectory)/linting-reports
98+
pwsh: true
99+
workingDirectory: $(Pipeline.Workspace)
100+
displayName: 'Generate Linting Reports'
101+
condition: always()
102+
103+
- publish: $(Build.ArtifactStagingDirectory)/linting-reports.zip
104+
displayName: 'Publish Linting Reports'
105+
artifact: linting-reports-$(System.StageName)-$(System.JobName)-$(System.JobAttempt)
106+
condition: always()
107+
108+
- pwsh: |
109+
if ((Get-ChildItem -Directory | Measure-Object).Count -gt 0) {
110+
exit 1
111+
}
112+
displayName: 'Fail Pipeline if Linting Reports Exist'
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<#
2+
.SYNOPSIS
3+
Captures and processes Checkstyle, RevApi, and Spotbugs linting reports.
4+
5+
.DESCRIPTION
6+
Given an SDK directory this will capture the Checkstyle, RevApi, and Spotbugs linting reports.
7+
Found Checkstyle and Spotbugs reports will be converted from their XML object representation to a more easily parsed
8+
CSV.
9+
10+
For each SDK containing non-empty linting reports, found in /target after running build verification, a folder with the
11+
SDK name will be created. The sub-folder may contain a processed Checkstyle report, processed Spotbugs report, and the
12+
default RevApi report. To prevent potential collisions of SDKs the sub-folder will use <SDK group>-<SDK>, so for azure-core
13+
it will be core_azure-core.
14+
15+
The searched for reports are /target/checkstyle-result.xml, /target/revapi.json, and /target/spotbugs.xml. There is no
16+
guarantee that each, or any, of these reports will exist, so if processing is safe if the file doesn't exist.
17+
18+
For Checkstyle the XML report will have the file name, line number, column number, linting error message, and linting error
19+
reported. For Spotbugs the XML will have the file name, line number, linting error message, and linting error reported, Spotbugs
20+
doesn't report the column number.
21+
22+
.PARAMETER OutputDirectory
23+
Where the linting report retrieval and processing will be output.
24+
25+
.PARAMETER SdkDirectory
26+
An optional SDK directory, such as core, that scopes the linting report searching and processing to the specific SDK
27+
directory. If this isn't passed all SDK directories will be searched and processed.
28+
#>
29+
30+
param(
31+
[Parameter(Mandatory = $true)]
32+
[string]$OutputDirectory,
33+
34+
[Parameter(Mandatory = $false)]
35+
[string]$SdkDirectory
36+
)
37+
38+
function NewFolderIfNotExists($FolderPath) {
39+
if (!(Test-Path -Path $FolderPath)) {
40+
New-Item -Path $FolderPath -ItemType Directory | Out-Null
41+
}
42+
}
43+
44+
function WriteCheckstyleProcessedReport($CheckstyleXmlReport, $ReportOutputFolder) {
45+
# Load the Checkstyle XML report.
46+
$xml = New-Object -TypeName System.Xml.XmlDocument
47+
$xml.Load($CheckstyleXmlReport)
48+
49+
$reportBuilder = New-Object -TypeName System.Text.StringBuilder
50+
51+
# List all "file" nodes contained in the report.
52+
foreach ($fileNode in $xml.GetElementsByTagName("file")) {
53+
if ($fileNode.HasChildNodes) {
54+
# Name of the file is an XML attribute "name".
55+
$fileName = $fileNode.Attributes["name"].Value
56+
foreach ($errorNode in $fileNode.ChildNodes) {
57+
# Information about the Checkstyle error is maintained as XML attributes.
58+
$lineNumber = $errorNode.Attributes["line"].Value
59+
$columnNumber = $errorNode.Attributes["column"].Value
60+
$lintingMessage = $errorNode.Attributes["message"].Value
61+
$lintingType = $errorNode.Attributes["source"].Value
62+
$reportBuilder.AppendLine("""$fileName"",$lineNumber,$columnNumber,""$lintingMessage"",""$lintingType""")
63+
}
64+
}
65+
}
66+
67+
if ($reportBuilder.Length -gt 0) {
68+
$reportBuilder.Insert(0, "File Name,Line Number,Column Number,Message,Type`n")
69+
NewFolderIfNotExists($ReportOutputFolder)
70+
New-Item -Path (Join-Path $ReportOutputFolder "checkstyle-report.csv") -ItemType File -Value $reportBuilder | Out-Null
71+
}
72+
}
73+
74+
function WriteSpotbugsProcessedReport($SpotbugsXmlReport, $ReportOutputFolder) {
75+
# Load the Spotbugs XML report.
76+
$xml = New-Object -TypeName System.Xml.XmlDocument
77+
$xml.Load($SpotbugsXmlReport)
78+
79+
$reportBuilder = New-Object -TypeName System.Text.StringBuilder
80+
81+
# List all "file" nodes contained in the report.
82+
foreach ($fileNode in $xml.GetElementsByTagName("file")) {
83+
if ($fileNode.HasChildNodes) {
84+
# Name of the class is an XML attribute "classname".
85+
$className = $fileNode.Attributes["classname"].Value
86+
foreach ($errorNode in $fileNode.ChildNodes) {
87+
# Information about the Checkstyle error is maintained as XML attributes.
88+
$lineNumber = $errorNode.Attributes["lineNumber"].Value
89+
$lintingMessage = $errorNode.Attributes["message"].Value
90+
$lintingType = $errorNode.Attributes["type"].Value
91+
$reportBuilder.AppendLine("""$className"",$lineNumber,""$lintingMessage"",""$lintingType""")
92+
}
93+
}
94+
}
95+
96+
if ($reportBuilder.Length -gt 0) {
97+
$reportBuilder.Insert(0, "Class Name,Line Number,Message,Type`n")
98+
NewFolderIfNotExists($ReportOutputFolder)
99+
New-Item -Path (Join-Path $ReportOutputFolder "spotbugs-report.csv") -ItemType File -Value $reportBuilder | Out-Null
100+
}
101+
}
102+
103+
# Change the working directory to the root of the repository
104+
Set-Location -ErrorAction Stop -LiteralPath (Join-Path $PSScriptRoot "../../../")
105+
106+
# Always create the output directory
107+
New-Item -Path $OutputDirectory -ItemType Directory | Out-Null
108+
109+
$path = "sdk/*/"
110+
if ($SdkDirectory) {
111+
$path = "sdk/$SdkDirectory/*/"
112+
}
113+
114+
foreach ($targetFolder in (Get-ChildItem -Path $path -Filter "target" -Directory -Recurse)) {
115+
# An assumption is being made here that the file path is /sdk/<SDK group>/<SDK name>
116+
$sdkGroup = $targetFolder.Parent.Parent.Name
117+
$sdk = $targetFolder.Parent.Name
118+
119+
$reportOutputFolder = Join-Path $OutputDirectory "$sdkGroup-$sdk"
120+
121+
$checkstyleXmlReport = Join-Path $targetFolder.FullName "checkstyle-result.xml"
122+
if (Test-Path -Path $checkstyleXmlReport) {
123+
WriteCheckstyleProcessedReport $checkstyleXmlReport $reportOutputFolder
124+
}
125+
126+
$spotbugsXmlReport = Join-Path $targetFolder.FullName "spotbugs.xml"
127+
if (Test-Path -Path $spotbugsXmlReport) {
128+
WriteSpotbugsProcessedReport $spotbugsXmlReport $OutputDirectory
129+
}
130+
131+
$revapiReport = Join-Path $targetFolder.FullName "revapi.json"
132+
if (Test-Path -Path $revapiReport) {
133+
$json = [System.Text.Json.JsonDocument]::Parse((Get-Content -Raw -Path $revapiReport))
134+
135+
# Only include the RevApi report if it contains an errors.
136+
if ($json.RootElement.GetArrayLength() -gt 0) {
137+
NewFolderIfNotExists($reportOutputFolder)
138+
Copy-Item -Path $revapiReport -Destination (Join-Path $reportOutputFolder "revapi-report.json")
139+
}
140+
}
141+
}
142+
143+
[System.IO.Compression.ZipFile]::CreateFromDirectory($OutputDirectory, $OutputDirectory + ".zip")

eng/versioning/external_dependencies.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ org.mockito:mockito-core;4.0.0
278278
org.mockito:mockito-inline;4.0.0
279279
org.revapi:revapi-java;0.20.0
280280
org.revapi:revapi-maven-plugin;0.11.2
281+
org.revapi:revapi-reporter-json;0.1.1
281282
org.moditect:moditect-maven-plugin;1.0.0.RC1
282283
org.ow2.asm:asm;9.1
283284
com.azure.tools:codesnippet-maven-plugin;1.0.0-beta.2

sdk/core/ci.yml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@ trigger:
1111
- sdk/core/
1212
- sdk/parents/azure-sdk-parent/
1313
- sdk/parents/azure-client-sdk-parent/
14-
- eng/
15-
exclude:
16-
- eng/versioning
17-
- eng/jacoco-test-coverage
14+
- eng/pipelines/
1815

1916
pr:
2017
branches:
@@ -28,10 +25,7 @@ pr:
2825
- sdk/core/
2926
- sdk/parents/azure-sdk-parent/
3027
- sdk/parents/azure-client-sdk-parent/
31-
- eng/
32-
exclude:
33-
- eng/versioning
34-
- eng/jacoco-test-coverage
28+
- eng/pipelines/
3529

3630

3731
extends:

0 commit comments

Comments
 (0)