common.psm1 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. $ErrorActionPreference = 'Stop'
  2. # Update the default TLS support to 1.2
  3. [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
  4. function Assert-Git {
  5. if (!(Get-Command git -ErrorAction Ignore)) {
  6. Write-Error 'git is required to execute this script'
  7. exit 1
  8. }
  9. }
  10. function Invoke-Block([scriptblock]$cmd, [string]$WorkingDir = $null) {
  11. if ($WorkingDir) {
  12. Push-Location $WorkingDir
  13. }
  14. try {
  15. $cmd | Out-String | Write-Verbose
  16. & $cmd
  17. # Need to check both of these cases for errors as they represent different items
  18. # - $?: did the powershell script block throw an error
  19. # - $lastexitcode: did a windows command executed by the script block end in error
  20. if ((-not $?) -or ($lastexitcode -ne 0)) {
  21. if ($error -ne $null)
  22. {
  23. Write-Warning $error[0]
  24. }
  25. throw "Command failed to execute: $cmd"
  26. }
  27. }
  28. finally {
  29. if ($WorkingDir) {
  30. Pop-Location
  31. }
  32. }
  33. }
  34. function Get-Submodules {
  35. param(
  36. [Parameter(Mandatory = $true)]
  37. [string]$RepoRoot,
  38. [switch]$Shipping
  39. )
  40. $moduleConfigFile = Join-Path $RepoRoot ".gitmodules"
  41. $submodules = @()
  42. [xml] $submoduleConfig = Get-Content "$RepoRoot/build/submodules.props"
  43. $repos = $submoduleConfig.Project.ItemGroup.Repository | % { $_.Include }
  44. Get-ChildItem "$RepoRoot/modules/*" -Directory `
  45. | ? { (-not $Shipping) -or $($repos -contains $($_.Name)) -or $_.Name -eq 'Templating' } `
  46. | % {
  47. Push-Location $_ | Out-Null
  48. Write-Verbose "Attempting to get submodule info for $_"
  49. if (Test-Path 'version.props') {
  50. [xml] $versionXml = Get-Content 'version.props'
  51. $versionPrefix = $versionXml.Project.PropertyGroup.VersionPrefix | select-object -first 1
  52. $versionSuffix = $versionXml.Project.PropertyGroup.VersionSuffix | select-object -first 1
  53. }
  54. else {
  55. $versionPrefix = ''
  56. $versionSuffix = ''
  57. }
  58. try {
  59. $data = [PSCustomObject] @{
  60. path = $_
  61. module = $_.Name
  62. commit = $(git rev-parse HEAD)
  63. newCommit = $null
  64. changed = $false
  65. remote = $(git config remote.origin.url)
  66. branch = $(git config -f $moduleConfigFile --get submodule.modules/$($_.Name).branch )
  67. versionPrefix = $versionPrefix
  68. versionSuffix = $versionSuffix
  69. }
  70. $submodules += $data
  71. }
  72. finally {
  73. Pop-Location | Out-Null
  74. }
  75. }
  76. return $submodules
  77. }
  78. function SaveXml([xml]$xml, [string]$path) {
  79. Write-Verbose "Saving to $path"
  80. $ErrorActionPreference = 'stop'
  81. $settings = New-Object System.XML.XmlWriterSettings
  82. $settings.OmitXmlDeclaration = $true
  83. $settings.Encoding = New-Object System.Text.UTF8Encoding( $true )
  84. $writer = [System.XML.XMLTextWriter]::Create($path, $settings)
  85. $xml.Save($writer)
  86. $writer.Close()
  87. }
  88. function LoadXml([string]$path) {
  89. Write-Verbose "Reading from $path"
  90. $ErrorActionPreference = 'stop'
  91. $obj = new-object xml
  92. $obj.PreserveWhitespace = $true
  93. $obj.Load($path)
  94. return $obj
  95. }
  96. function PackageIdVarName([string]$packageId) {
  97. $canonicalVarName = ''
  98. $upperCaseNext = $true
  99. for ($i = 0; $i -lt $packageId.Length; $i++) {
  100. $ch = $packageId[$i]
  101. if (-not [System.Char]::IsLetterOrDigit(($ch))) {
  102. $upperCaseNext = $true
  103. continue
  104. }
  105. if ($upperCaseNext) {
  106. $ch = [System.Char]::ToUpperInvariant($ch)
  107. $upperCaseNext = $false
  108. }
  109. $canonicalVarName += $ch
  110. }
  111. $canonicalVarName += "PackageVersion"
  112. return $canonicalVarName
  113. }
  114. function Ensure-Hub() {
  115. $tmpDir = "$PSScriptRoot\tmp"
  116. $zipDir = "$tmpDir\Hub"
  117. $hubLocation = "$zipDir\bin\hub.exe"
  118. if (-Not (Test-Path $hubLocation) ) {
  119. $source = "https://github.com/github/hub/releases/download/v2.3.0-pre9/hub-windows-amd64-2.3.0-pre9.zip"
  120. $zipLocation = "$tmpDir\hub.zip"
  121. mkdir -Path $tmpDir -ErrorAction Ignore | Out-Null
  122. Invoke-WebRequest -OutFile $zipLocation -Uri $source
  123. Expand-Archive -Path $zipLocation -DestinationPath $zipDir -Force
  124. if (-Not (Test-Path $hubLocation)) {
  125. throw "Hub couldn't be downloaded"
  126. }
  127. }
  128. return $hubLocation
  129. }
  130. function CreatePR(
  131. [string]$baseFork,
  132. [string]$headFork,
  133. [string]$baseBranch,
  134. [string]$destinationBranch,
  135. [string]$body,
  136. [string]$gitHubToken) {
  137. $hubLocation = Ensure-Hub
  138. Invoke-Block { git push -f https://[email protected]/$headFork/AspNetCore.git $destinationBranch }
  139. & $hubLocation pull-request -f -b "${baseFork}:$baseBranch" -h "${headFork}:$destinationBranch" -m $body
  140. }
  141. function Set-GithubInfo(
  142. [string]$GitHubPassword,
  143. [string]$GitHubUser,
  144. [string]$GitHubEmail)
  145. {
  146. $Env:GITHUB_TOKEN = $GitHubPassword
  147. $Env:GITHUB_USER = $GitHubUser
  148. $Env:GITHUB_EMAIL = $GitHubEmail
  149. }
  150. function CommitUpdatedVersions(
  151. [hashtable]$updatedVars,
  152. [xml]$dependencies,
  153. [string]$depsPath,
  154. [string]$subject = 'Updating external dependencies')
  155. {
  156. $count = $updatedVars.Count
  157. if ($count -gt 0) {
  158. & git add build\dependencies.props
  159. $gitConfigArgs = @()
  160. if ($env:GITHUB_USER) {
  161. $gitConfigArgs += '-c',"user.name=$env:GITHUB_USER"
  162. }
  163. if ($env:GITHUB_EMAIL) {
  164. $gitConfigArgs += '-c',"user.email=$env:GITHUB_EMAIL"
  165. }
  166. Invoke-Block { & git @gitConfigArgs commit -m $subject } | Out-Null
  167. $body = "$subject`n`n"
  168. $body += "New versions:`n"
  169. foreach ($var in $updatedVars.GetEnumerator()) {
  170. $body += " $($var.Name)`n"
  171. }
  172. return $body
  173. }
  174. }
  175. function UpdateVersions([hashtable]$variables, [xml]$dependencies, [string]$depsPath) {
  176. $updatedVars = @{}
  177. foreach ($varName in ($variables.Keys | sort)) {
  178. $packageVersions = $variables[$varName]
  179. if ($packageVersions.Length -gt 1) {
  180. Write-Warning "Skipped $varName. Multiple version found. { $($packageVersions -join ', ') }."
  181. continue
  182. }
  183. $packageVersion = $packageVersions | Select-Object -First 1
  184. $depVarNode = $dependencies.SelectSingleNode("//PropertyGroup[`@Label=`"Package Versions: Auto`"]/$varName")
  185. if ($depVarNode -and $depVarNode.InnerText -ne $packageVersion) {
  186. $depVarNode.InnerText = $packageVersion
  187. Write-Host -f DarkGray " Updating $varName to $packageVersion"
  188. $updatedVars[$varName] = $packageVersion
  189. }
  190. elseif ($depVarNode) {
  191. Write-Host -f DarkBlue " Didn't update $varName to $packageVersion because it was $($depVarNode.InnerText)"
  192. }
  193. else {
  194. # This isn't a dependency we use
  195. }
  196. }
  197. if ($updatedVars.Count -gt 0) {
  198. Write-Host -f Cyan "Updating version variables in $depsPath"
  199. SaveXml $dependencies $depsPath
  200. }
  201. else {
  202. Write-Host -f Green "No changes found"
  203. }
  204. return $updatedVars
  205. }
  206. function Get-MSBuildPath {
  207. param(
  208. [switch]$Prerelease,
  209. [string[]]$Requires
  210. )
  211. $vsInstallDir = $null
  212. if ($env:VSINSTALLDIR -and (Test-Path $env:VSINSTALLDIR)) {
  213. $vsInstallDir = $env:VSINSTALLDIR
  214. Write-Verbose "Using VSINSTALLDIR=$vsInstallDir"
  215. }
  216. else {
  217. $vswhere = "${env:ProgramFiles(x86)}/Microsoft Visual Studio/Installer/vswhere.exe"
  218. Write-Verbose "Using vswhere.exe from $vswhere"
  219. if (-not (Test-Path $vswhere)) {
  220. Write-Error "Missing prerequisite: could not find vswhere"
  221. }
  222. [string[]] $vswhereArgs = @()
  223. if ($Prerelease) {
  224. $vswhereArgs += '-prerelease'
  225. }
  226. if ($Requires) {
  227. foreach ($r in $Requires) {
  228. $vswhereArgs += '-requires', $r
  229. }
  230. }
  231. $installs = & $vswhere -format json -version '[15.0, 16.0)' -latest -products * @vswhereArgs | ConvertFrom-Json
  232. if (!$installs) {
  233. Write-Error "Missing prerequisite: could not find any installations of Visual Studio"
  234. }
  235. $vs = $installs | Select-Object -First 1
  236. $vsInstallDir = $vs.installationPath
  237. Write-Host "Using $($vs.displayName)"
  238. }
  239. $msbuild = Join-Path $vsInstallDir 'MSBuild/15.0/bin/msbuild.exe'
  240. if (!(Test-Path $msbuild)) {
  241. Write-Error "Missing prerequisite: could not find msbuild.exe"
  242. }
  243. return $msbuild
  244. }
  245. function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) {
  246. if ($RemotePath -notlike 'http*') {
  247. Copy-Item $RemotePath $LocalPath
  248. return
  249. }
  250. $retries = 10
  251. while ($retries -gt 0) {
  252. $retries -= 1
  253. try {
  254. Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath
  255. return
  256. }
  257. catch {
  258. Write-Verbose "Request failed. $retries retries remaining"
  259. }
  260. }
  261. Write-Error "Download failed: '$RemotePath'."
  262. }