|
| 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") |
0 commit comments