195 lines
7.1 KiB
PowerShell
195 lines
7.1 KiB
PowerShell
|
|
param(
|
||
|
|
[string]$Revision,
|
||
|
|
[switch]$Force,
|
||
|
|
[switch]$SkipBuild
|
||
|
|
)
|
||
|
|
|
||
|
|
$ErrorActionPreference = 'Stop'
|
||
|
|
Set-StrictMode -Version Latest
|
||
|
|
|
||
|
|
function Invoke-CommandChecked {
|
||
|
|
param(
|
||
|
|
[Parameter(Mandatory = $true)]
|
||
|
|
[string]$Executable,
|
||
|
|
[Parameter(Mandatory = $true)]
|
||
|
|
[string[]]$Arguments
|
||
|
|
)
|
||
|
|
|
||
|
|
& $Executable @Arguments
|
||
|
|
if ($LASTEXITCODE -ne 0) {
|
||
|
|
throw "$Executable failed with exit code $LASTEXITCODE."
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function Get-PomProperty {
|
||
|
|
param(
|
||
|
|
[Parameter(Mandatory = $true)]
|
||
|
|
[string]$PomText,
|
||
|
|
[Parameter(Mandatory = $true)]
|
||
|
|
[string]$Name
|
||
|
|
)
|
||
|
|
|
||
|
|
$escapedName = [Regex]::Escape($Name)
|
||
|
|
$match = [Regex]::Match($PomText, "<$escapedName>([^<]+)</$escapedName>")
|
||
|
|
if (-not $match.Success) {
|
||
|
|
throw "Cannot find Maven property '$Name'."
|
||
|
|
}
|
||
|
|
|
||
|
|
return $match.Groups[1].Value.Trim()
|
||
|
|
}
|
||
|
|
|
||
|
|
function Sync-ProtoDirectory {
|
||
|
|
param(
|
||
|
|
[Parameter(Mandatory = $true)]
|
||
|
|
[string]$Source,
|
||
|
|
[Parameter(Mandatory = $true)]
|
||
|
|
[string]$Destination
|
||
|
|
)
|
||
|
|
|
||
|
|
if (-not (Test-Path -LiteralPath $Source -PathType Container)) {
|
||
|
|
throw "Upstream proto directory does not exist: $Source"
|
||
|
|
}
|
||
|
|
|
||
|
|
New-Item -ItemType Directory -Path $Destination -Force | Out-Null
|
||
|
|
|
||
|
|
$sourceFiles = @{}
|
||
|
|
foreach ($sourceFile in Get-ChildItem -LiteralPath $Source -Filter '*.proto' -File -Recurse) {
|
||
|
|
$relativePath = $sourceFile.FullName.Substring($Source.Length).TrimStart('\', '/')
|
||
|
|
$sourceFiles[$relativePath] = $true
|
||
|
|
|
||
|
|
$destinationFile = Join-Path $Destination $relativePath
|
||
|
|
$destinationDirectory = Split-Path -Parent $destinationFile
|
||
|
|
New-Item -ItemType Directory -Path $destinationDirectory -Force | Out-Null
|
||
|
|
Copy-Item -LiteralPath $sourceFile.FullName -Destination $destinationFile -Force
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ($destinationFile in Get-ChildItem -LiteralPath $Destination -Filter '*.proto' -File -Recurse) {
|
||
|
|
$relativePath = $destinationFile.FullName.Substring($Destination.Length).TrimStart('\', '/')
|
||
|
|
if (-not $sourceFiles.ContainsKey($relativePath)) {
|
||
|
|
Remove-Item -LiteralPath $destinationFile.FullName -Force
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
|
||
|
|
throw 'Git was not found on PATH.'
|
||
|
|
}
|
||
|
|
|
||
|
|
$rootDirectory = Split-Path -Parent $PSScriptRoot
|
||
|
|
$moduleRelativePath = 'cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-lib'
|
||
|
|
$moduleDirectory = Join-Path $rootDirectory $moduleRelativePath
|
||
|
|
$pomPath = Join-Path $moduleDirectory 'pom.xml'
|
||
|
|
$protoRelativePath = "$moduleRelativePath/src/main/proto/cmvr"
|
||
|
|
$protoDirectory = Join-Path $rootDirectory $protoRelativePath
|
||
|
|
$checkoutDirectory = Join-Path $moduleDirectory 'target/cmvr-es'
|
||
|
|
|
||
|
|
$pomText = [IO.File]::ReadAllText($pomPath)
|
||
|
|
$repository = Get-PomProperty -PomText $pomText -Name 'cmvr.es.repository'
|
||
|
|
$branch = Get-PomProperty -PomText $pomText -Name 'cmvr.es.proto.branch'
|
||
|
|
|
||
|
|
$localProtoChanges = @(& git -C $rootDirectory status --porcelain -- $protoRelativePath)
|
||
|
|
if ($LASTEXITCODE -ne 0) {
|
||
|
|
throw 'Unable to inspect local proto changes.'
|
||
|
|
}
|
||
|
|
if ($localProtoChanges.Count -gt 0 -and -not $Force) {
|
||
|
|
throw "Local proto files have uncommitted changes. Commit/stash them first, or rerun with -Force.`n$($localProtoChanges -join "`n")"
|
||
|
|
}
|
||
|
|
|
||
|
|
if ([string]::IsNullOrWhiteSpace($Revision)) {
|
||
|
|
Write-Host "Looking up the latest '$branch' revision..."
|
||
|
|
$remoteLine = @(& git ls-remote $repository "refs/heads/$branch")
|
||
|
|
if ($LASTEXITCODE -ne 0) {
|
||
|
|
throw 'Unable to read the upstream branch. Check the network and Git credentials.'
|
||
|
|
}
|
||
|
|
if ($remoteLine.Count -ne 1) {
|
||
|
|
throw "Upstream branch '$branch' was not found or was ambiguous."
|
||
|
|
}
|
||
|
|
$Revision = ($remoteLine[0] -split '\s+')[0]
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($Revision -notmatch '^[0-9a-fA-F]{40}$') {
|
||
|
|
throw "Revision must be a full 40-character Git commit SHA: $Revision"
|
||
|
|
}
|
||
|
|
$Revision = $Revision.ToLowerInvariant()
|
||
|
|
|
||
|
|
$checkoutParent = Split-Path -Parent $checkoutDirectory
|
||
|
|
New-Item -ItemType Directory -Path $checkoutParent -Force | Out-Null
|
||
|
|
|
||
|
|
if (Test-Path -LiteralPath (Join-Path $checkoutDirectory '.git') -PathType Container) {
|
||
|
|
Write-Host 'Refreshing the existing upstream checkout...'
|
||
|
|
Invoke-CommandChecked git @('-C', $checkoutDirectory, 'remote', 'set-url', 'origin', $repository)
|
||
|
|
Invoke-CommandChecked git @('-C', $checkoutDirectory, 'fetch', '--filter=blob:none', 'origin', $branch)
|
||
|
|
} else {
|
||
|
|
if (Test-Path -LiteralPath $checkoutDirectory) {
|
||
|
|
$expectedPath = [IO.Path]::GetFullPath($checkoutDirectory).TrimEnd('\')
|
||
|
|
$actualPath = (Resolve-Path -LiteralPath $checkoutDirectory).Path.TrimEnd('\')
|
||
|
|
if ($actualPath -ne $expectedPath -or (Split-Path -Parent $actualPath) -ne [IO.Path]::GetFullPath($checkoutParent).TrimEnd('\')) {
|
||
|
|
throw "Refusing to replace unexpected checkout path: $actualPath"
|
||
|
|
}
|
||
|
|
Remove-Item -LiteralPath $checkoutDirectory -Recurse -Force
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host 'Cloning the upstream proto repository...'
|
||
|
|
Invoke-CommandChecked git @(
|
||
|
|
'clone', '--filter=blob:none', '--sparse', '--single-branch',
|
||
|
|
'--branch', $branch, $repository, $checkoutDirectory
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
Invoke-CommandChecked git @(
|
||
|
|
'-C', $checkoutDirectory, 'sparse-checkout', 'set',
|
||
|
|
'protos/cmvr/api', 'protos/cmvr/msgs', 'protos/cmvr/common'
|
||
|
|
)
|
||
|
|
Invoke-CommandChecked git @('-C', $checkoutDirectory, 'checkout', '--detach', $Revision)
|
||
|
|
|
||
|
|
$actualRevision = (& git -C $checkoutDirectory rev-parse HEAD).Trim()
|
||
|
|
if ($LASTEXITCODE -ne 0 -or $actualRevision -ne $Revision) {
|
||
|
|
throw "Expected revision $Revision, but checked out $actualRevision."
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host "Syncing proto files from revision $Revision..."
|
||
|
|
foreach ($group in @('api', 'msgs', 'common')) {
|
||
|
|
Sync-ProtoDirectory `
|
||
|
|
-Source (Join-Path $checkoutDirectory "protos/cmvr/$group") `
|
||
|
|
-Destination (Join-Path $protoDirectory $group)
|
||
|
|
}
|
||
|
|
|
||
|
|
$revisionPattern = '(<cmvr\.es\.proto\.revision>)[^<]+(</cmvr\.es\.proto\.revision>)'
|
||
|
|
$revisionRegex = [Regex]::new($revisionPattern)
|
||
|
|
$updatedPomText = $revisionRegex.Replace($pomText, "`${1}$Revision`${2}", 1)
|
||
|
|
if ($updatedPomText -eq $pomText -and (Get-PomProperty -PomText $pomText -Name 'cmvr.es.proto.revision') -ne $Revision) {
|
||
|
|
throw 'Unable to update cmvr.es.proto.revision in pom.xml.'
|
||
|
|
}
|
||
|
|
if ($updatedPomText -ne $pomText) {
|
||
|
|
[IO.File]::WriteAllText($pomPath, $updatedPomText, [Text.UTF8Encoding]::new($false))
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host 'Updated files:'
|
||
|
|
& git -C $rootDirectory status --short -- $protoRelativePath "$moduleRelativePath/pom.xml"
|
||
|
|
if ($LASTEXITCODE -ne 0) {
|
||
|
|
throw 'Unable to show the update summary.'
|
||
|
|
}
|
||
|
|
|
||
|
|
if (-not $SkipBuild) {
|
||
|
|
if (-not (Get-Command mvn -ErrorAction SilentlyContinue)) {
|
||
|
|
throw 'Maven was not found on PATH. Proto files were updated, but the verification build was not run.'
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host 'Running the gRPC verification build...'
|
||
|
|
Push-Location $rootDirectory
|
||
|
|
try {
|
||
|
|
Invoke-CommandChecked mvn @(
|
||
|
|
'-pl', 'cmvr-iot-api/cmvr-iot-edge/cmvr-iot-grpc-client',
|
||
|
|
'-am', 'clean', 'package', '-DskipTests'
|
||
|
|
)
|
||
|
|
} finally {
|
||
|
|
Pop-Location
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host "CMVR-ES proto update completed: $Revision"
|
||
|
|
Write-Host 'Review and commit the proto files and pom.xml together.'
|