CodeCheck.ps1 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #requires -version 5
  2. <#
  3. .SYNOPSIS
  4. This script runs a quick check for common errors, such as checking that Visual Studio solutions are up to date or that generated code has been committed to source.
  5. #>
  6. param(
  7. [switch]$ci
  8. )
  9. $ErrorActionPreference = 'Stop'
  10. Set-StrictMode -Version 1
  11. Import-Module -Scope Local -Force "$PSScriptRoot/common.psm1"
  12. $repoRoot = Resolve-Path "$PSScriptRoot/../.."
  13. [string[]] $errors = @()
  14. function LogError {
  15. param(
  16. [Parameter(Mandatory = $true, Position = 0)]
  17. [string]$message,
  18. [string]$FilePath
  19. )
  20. if ($env:TF_BUILD) {
  21. $prefix = "##vso[task.logissue type=error"
  22. if ($FilePath) {
  23. $prefix = "${prefix};sourcepath=$FilePath"
  24. }
  25. Write-Host "${prefix}]${message}"
  26. }
  27. Write-Host -f Red "error: $message"
  28. $script:errors += $message
  29. }
  30. try {
  31. if ($ci) {
  32. # Install dotnet.exe
  33. & $repoRoot/build.ps1 -ci -norestore /t:InstallDotNet
  34. }
  35. #
  36. # Versions.props and Version.Details.xml
  37. #
  38. Write-Host "Checking that Versions.props and Version.Details.xml match"
  39. [xml] $versionProps = Get-Content "$repoRoot/eng/Versions.props"
  40. [xml] $versionDetails = Get-Content "$repoRoot/eng/Version.Details.xml"
  41. $versionVars = New-Object 'System.Collections.Generic.HashSet[string]'
  42. foreach ($vars in $versionProps.SelectNodes("//PropertyGroup[`@Label=`"Automated`"]/*")) {
  43. $versionVars.Add($vars.Name) | Out-Null
  44. }
  45. foreach ($dep in $versionDetails.SelectNodes('//Dependency')) {
  46. Write-Verbose "Found $dep"
  47. $varName = $dep.Name -replace '\.',''
  48. $varName = $varName -replace '\-',''
  49. $varName = "${varName}PackageVersion"
  50. $versionVar = $versionProps.SelectSingleNode("//PropertyGroup[`@Label=`"Automated`"]/$varName")
  51. if (-not $versionVar) {
  52. LogError "Missing version variable '$varName' in the 'Automated' property group in $repoRoot/eng/Versions.props"
  53. continue
  54. }
  55. $versionVars.Remove($varName) | Out-Null
  56. $expectedVersion = $dep.Version
  57. $actualVersion = $versionVar.InnerText
  58. if ($expectedVersion -ne $actualVersion) {
  59. LogError `
  60. "Version variable '$varName' does not match the value in Version.Details.xml. Expected '$expectedVersion', actual '$actualVersion'" `
  61. -filepath "$repoRoot\eng\Versions.props"
  62. }
  63. }
  64. foreach ($unexpectedVar in $versionVars) {
  65. LogError `
  66. "Version variable '$unexpectedVar' does not have a matching entry in Version.Details.xml. See https://github.com/aspnet/AspNetCore/blob/master/docs/ReferenceResolution.md for instructions on how to add a new dependency." `
  67. -filepath "$repoRoot\eng\Versions.props"
  68. }
  69. #
  70. # Solutions
  71. #
  72. Write-Host "Checking that solutions are up to date"
  73. Get-ChildItem "$repoRoot/*.sln" -Recurse `
  74. | ? {
  75. # This .sln file is used by the templating engine.
  76. $_.Name -ne "RazorComponentsWeb-CSharp.sln"
  77. } `
  78. | % {
  79. Write-Host " Checking $(Split-Path -Leaf $_)"
  80. $slnDir = Split-Path -Parent $_
  81. $sln = $_
  82. & dotnet sln $_ list `
  83. | ? { $_ -like '*proj' } `
  84. | % {
  85. $proj = Join-Path $slnDir $_
  86. if (-not (Test-Path $proj)) {
  87. LogError "Missing project. Solution references a project which does not exist: $proj. [$sln] "
  88. }
  89. }
  90. }
  91. #
  92. # Generated code check
  93. #
  94. Write-Host "Re-running code generation"
  95. Write-Host "Re-generating project lists"
  96. Invoke-Block {
  97. & $PSScriptRoot\GenerateProjectList.ps1 -ci:$ci
  98. }
  99. Write-Host "Re-generating package baselines"
  100. $dotnet = 'dotnet'
  101. if ($ci) {
  102. $dotnet = "$repoRoot/.dotnet/x64/dotnet.exe"
  103. }
  104. Invoke-Block {
  105. & $dotnet run -p "$repoRoot/eng/tools/BaselineGenerator/"
  106. }
  107. Write-Host "Run git diff to check for pending changes"
  108. # Redirect stderr to stdout because PowerShell does not consistently handle output to stderr
  109. $changedFiles = & cmd /c 'git --no-pager diff --ignore-space-at-eol --name-only 2>&1'
  110. if ($changedFiles) {
  111. foreach ($file in $changedFiles) {
  112. if (($file -like 'warning:*') -or ($file -like 'The file will have its original line endings*')) {
  113. # git might emit warnings to stderr about CRLF vs LR, which can vary from machine to machine based on git's configuration
  114. continue
  115. }
  116. $filePath = Resolve-Path "${repoRoot}/${file}"
  117. LogError "Generated code is not up to date in $file." -filepath $filePath
  118. & git --no-pager diff --ignore-space-at-eol $filePath
  119. }
  120. }
  121. }
  122. finally {
  123. Write-Host ""
  124. Write-Host "Summary:"
  125. Write-Host ""
  126. Write-Host " $($errors.Length) error(s)"
  127. Write-Host ""
  128. foreach ($err in $errors) {
  129. Write-Host -f Red "error : $err"
  130. }
  131. if ($errors) {
  132. exit 1
  133. }
  134. }