зеркало из https://github.com/dotnet/aspnetcore.git
262 строки
9.7 KiB
PowerShell
262 строки
9.7 KiB
PowerShell
#requires -version 5
|
|
<#
|
|
.SYNOPSIS
|
|
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.
|
|
#>
|
|
param(
|
|
[switch]$ci,
|
|
# Optional arguments that enable downloading an internal
|
|
# runtime or runtime from a non-default location
|
|
[Alias('DotNetRuntimeSourceFeed')]
|
|
[string]$RuntimeSourceFeed,
|
|
[Alias('DotNetRuntimeSourceFeedKey')]
|
|
[string]$RuntimeSourceFeedKey
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-StrictMode -Version 1
|
|
Import-Module -Scope Local -Force "$PSScriptRoot/common.psm1"
|
|
|
|
$repoRoot = Resolve-Path "$PSScriptRoot/../.."
|
|
|
|
[string[]] $errors = @()
|
|
|
|
function LogError {
|
|
param(
|
|
[Parameter(Mandatory = $true, Position = 0)]
|
|
[string]$message,
|
|
[string]$FilePath,
|
|
[string]$Code
|
|
)
|
|
if ($env:TF_BUILD) {
|
|
$prefix = "##vso[task.logissue type=error"
|
|
if ($FilePath) {
|
|
$prefix = "${prefix};sourcepath=$FilePath"
|
|
}
|
|
if ($Code) {
|
|
$prefix = "${prefix};code=$Code"
|
|
}
|
|
Write-Host "${prefix}]${message}"
|
|
}
|
|
$fullMessage = "error ${Code}: $message"
|
|
if ($FilePath) {
|
|
$fullMessage += " [$FilePath]"
|
|
}
|
|
Write-Host -f Red $fullMessage
|
|
$script:errors += $fullMessage
|
|
}
|
|
|
|
try {
|
|
if ($ci) {
|
|
# Install dotnet.exe
|
|
if ($RuntimeSourceFeed -or $RuntimeSourceFeedKey) {
|
|
& $repoRoot/restore.cmd -ci -nobl -noBuildNodeJS -RuntimeSourceFeed $RuntimeSourceFeed `
|
|
-RuntimeSourceFeedKey $RuntimeSourceFeedKey
|
|
} else {
|
|
& $repoRoot/restore.cmd -ci -nobl -noBuildNodeJS
|
|
}
|
|
}
|
|
|
|
. "$repoRoot/activate.ps1"
|
|
|
|
#
|
|
# Duplicate .csproj files can cause issues with a shared build output folder
|
|
#
|
|
|
|
$projectFileNames = New-Object 'System.Collections.Generic.HashSet[string]'
|
|
|
|
# Ignore duplicates in submodules. These should be isolated from the rest of the build.
|
|
# Ignore duplicates in the .ref folder. This is expected.
|
|
Get-ChildItem -Recurse "$repoRoot/src/*.*proj" |
|
|
Where-Object { $_.FullName -notmatch 'submodules' -and $_.FullName -notmatch 'node_modules' } |
|
|
Where-Object { (Split-Path -Leaf (Split-Path -Parent $_)) -ne 'ref' } |
|
|
ForEach-Object {
|
|
$fileName = [io.path]::GetFileNameWithoutExtension($_)
|
|
if (-not ($projectFileNames.Add($fileName))) {
|
|
LogError -code 'BUILD003' -filepath $_ `
|
|
("Multiple project files named '$fileName' exist. Project files should have a unique name " +
|
|
"to avoid conflicts in build output.")
|
|
}
|
|
}
|
|
|
|
#
|
|
# Versions.props and Version.Details.xml
|
|
#
|
|
|
|
Write-Host "Checking that Versions.props and Version.Details.xml match"
|
|
[xml] $versionProps = Get-Content "$repoRoot/eng/Versions.props"
|
|
[xml] $versionDetails = Get-Content "$repoRoot/eng/Version.Details.xml"
|
|
$globalJson = Get-Content $repoRoot/global.json | ConvertFrom-Json
|
|
|
|
$versionVars = New-Object 'System.Collections.Generic.HashSet[string]'
|
|
foreach ($vars in $versionProps.SelectNodes("//PropertyGroup[`@Label=`"Automated`"]/*")) {
|
|
$versionVars.Add($vars.Name) | Out-Null
|
|
}
|
|
|
|
foreach ($dep in $versionDetails.SelectNodes('//Dependency')) {
|
|
Write-Verbose "Found $dep"
|
|
|
|
$expectedVersion = $dep.Version
|
|
|
|
if ($dep.Name -in $globalJson.'msbuild-sdks'.PSObject.Properties.Name) {
|
|
|
|
$actualVersion = $globalJson.'msbuild-sdks'.($dep.Name)
|
|
|
|
if ($expectedVersion -ne $actualVersion) {
|
|
LogError -filepath "$repoRoot\global.json" `
|
|
("MSBuild SDK version '$($dep.Name)' in global.json does not match the value in " +
|
|
"Version.Details.xml. Expected '$expectedVersion', actual '$actualVersion'")
|
|
}
|
|
}
|
|
else {
|
|
$varName = $dep.Name -replace '\.',''
|
|
$varName = $varName -replace '\-',''
|
|
$varName = "${varName}Version"
|
|
|
|
$versionVar = $versionProps.SelectSingleNode("//PropertyGroup[`@Label=`"Automated`"]/$varName")
|
|
$actualVersion = $versionVar.InnerText
|
|
$versionVars.Remove($varName) | Out-Null
|
|
|
|
if (-not $versionVar) {
|
|
LogError "Missing version variable '$varName' in the 'Automated' property group in $repoRoot/eng/Versions.props"
|
|
continue
|
|
}
|
|
|
|
if ($expectedVersion -ne $actualVersion) {
|
|
LogError -filepath "$repoRoot\eng\Versions.props" `
|
|
("Version variable '$varName' does not match the value in Version.Details.xml. " +
|
|
"Expected '$expectedVersion', actual '$actualVersion'")
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach ($unexpectedVar in $versionVars) {
|
|
LogError -Filepath "$repoRoot\eng\Versions.props" `
|
|
("Version variable '$unexpectedVar' does not have a matching entry in Version.Details.xml. " +
|
|
"See https://github.com/dotnet/aspnetcore/blob/main/docs/ReferenceResolution.md for instructions " +
|
|
"on how to add a new dependency.")
|
|
}
|
|
|
|
# ComponentsWebAssembly-CSharp.sln is used by the templating engine; MessagePack.sln is irrelevant (in submodule).
|
|
$solution = Get-ChildItem "$repoRoot/AspNetCore.sln"
|
|
$solutionFile = Split-Path -Leaf $solution
|
|
|
|
Write-Host "Checking that $solutionFile is up to date"
|
|
|
|
# $solutionProjects will store relative paths i.e. the exact solution and solution filter content.
|
|
$solutionProjects = New-Object 'System.Collections.Generic.HashSet[string]'
|
|
|
|
# Where-Object needed to ignore heading `dotnet sln` outputs
|
|
& dotnet sln $solution list | Where-Object { $_ -like '*proj' } | ForEach-Object {
|
|
$proj = Join-Path $repoRoot $_
|
|
if (-not ($solutionProjects.Add($_))) {
|
|
LogError "Duplicate project. $solutionFile references a project more than once: $proj."
|
|
}
|
|
if (-not (Test-Path $proj)) {
|
|
LogError "Missing project. $solutionFile references a project which does not exist: $proj."
|
|
}
|
|
}
|
|
|
|
Write-Host "Checking solution filters"
|
|
Get-ChildItem -Recurse "$repoRoot\*.slnf" | ForEach-Object {
|
|
$solutionFilter = $_
|
|
$json = Get-Content -Raw -Path $solutionFilter |ConvertFrom-Json
|
|
$json.solution.projects | ForEach-Object {
|
|
if (!$solutionProjects.Contains($_)) {
|
|
LogError "$solutionFilter references a project not in $solutionFile`: $_"
|
|
}
|
|
}
|
|
}
|
|
|
|
#
|
|
# Generated code check
|
|
#
|
|
|
|
Write-Host "Re-running code generation"
|
|
|
|
Write-Host " Re-generating project lists"
|
|
Invoke-Block {
|
|
& $PSScriptRoot\GenerateProjectList.ps1 -ci:$ci
|
|
}
|
|
|
|
Write-Host " Re-generating package baselines"
|
|
Invoke-Block {
|
|
& dotnet run --project "$repoRoot/eng/tools/BaselineGenerator/"
|
|
}
|
|
|
|
Write-Host "Running git diff to check for pending changes"
|
|
|
|
# Redirect stderr to stdout because PowerShell does not consistently handle output to stderr
|
|
$changedFiles = & cmd /c 'git --no-pager diff --ignore-space-change --name-only 2>nul'
|
|
|
|
# Temporary: Disable check for blazor js file and nuget.config (updated automatically for
|
|
# internal builds)
|
|
$changedFilesExclusions = @("src/Components/Web.JS/dist/Release/blazor.server.js", "NuGet.config")
|
|
|
|
if ($changedFiles) {
|
|
foreach ($file in $changedFiles) {
|
|
if ($changedFilesExclusions -contains $file) {continue}
|
|
$filePath = Resolve-Path "${repoRoot}/${file}"
|
|
LogError -filepath $filePath `
|
|
("Generated code is not up to date in $file. You might need to regenerate the reference " +
|
|
"assemblies or project list (see docs/ReferenceResolution.md)")
|
|
& git --no-pager diff --ignore-space-change $filePath
|
|
}
|
|
}
|
|
|
|
$targetBranch = $env:SYSTEM_PULLREQUEST_TARGETBRANCH
|
|
|
|
if (![string]::IsNullOrEmpty($targetBranch)) {
|
|
if ($targetBranch.StartsWith('refs/heads/')) {
|
|
$targetBranch = $targetBranch.Replace('refs/heads/','')
|
|
}
|
|
|
|
# Retrieve the set of changed files compared to main
|
|
Write-Host "Checking for changes to API baseline files $targetBranch"
|
|
|
|
$changedFilesFromTarget = git --no-pager diff origin/$targetBranch --ignore-space-change --name-only --diff-filter=ar
|
|
$changedAPIBaselines = [System.Collections.Generic.List[string]]::new()
|
|
|
|
if ($changedFilesFromTarget) {
|
|
foreach ($file in $changedFilesFromTarget) {
|
|
# Check for changes in Shipped in all branches
|
|
if ($file -like '*PublicAPI.Shipped.txt') {
|
|
if (!$file.Contains('DevServer/src/PublicAPI.Shipped.txt')) {
|
|
$changedAPIBaselines.Add($file)
|
|
}
|
|
}
|
|
# Check for changes in Unshipped in servicing branches
|
|
if ($targetBranch -like 'release*' -and $targetBranch -notlike '*preview*' -and $file -like '*PublicAPI.Unshipped.txt') {
|
|
$changedAPIBaselines.Add($file)
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-Host "Found changes in $($changedAPIBaselines.count) API baseline files"
|
|
|
|
if ($changedAPIBaselines.count -gt 0) {
|
|
LogError ("Detected modification to baseline API files. PublicAPI.Shipped.txt files should only " +
|
|
"be updated after a major release. See /docs/APIBaselines.md for more information.")
|
|
LogError "Modified API baseline files:"
|
|
foreach ($file in $changedAPIBaselines) {
|
|
LogError $file
|
|
}
|
|
}
|
|
}
|
|
}
|
|
finally {
|
|
Write-Host ""
|
|
Write-Host "Summary:"
|
|
Write-Host ""
|
|
Write-Host " $($errors.Length) error(s)"
|
|
Write-Host ""
|
|
|
|
foreach ($err in $errors) {
|
|
Write-Host -f Red $err
|
|
}
|
|
|
|
if ($errors) {
|
|
exit 1
|
|
}
|
|
}
|