From 8df85b2317a9a17a50fb808f71145fde17f4f613 Mon Sep 17 00:00:00 2001 From: "Scott Beddall (from Dev Box)" Date: Thu, 11 Jan 2024 18:39:52 -0800 Subject: [PATCH 01/10] updating to create the structure of the new script --- .../onboarding/common-asset-functions.ps1 | 18 ++++ .../resolve-asset-conflict.ps1 | 92 +++++++++++++++++++ .../scripts/tag-merge/merge-proxy-tags.ps1 | 18 ---- 3 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 diff --git a/eng/common/testproxy/onboarding/common-asset-functions.ps1 b/eng/common/testproxy/onboarding/common-asset-functions.ps1 index 3caa6654c133..3d7bcf605584 100644 --- a/eng/common/testproxy/onboarding/common-asset-functions.ps1 +++ b/eng/common/testproxy/onboarding/common-asset-functions.ps1 @@ -57,6 +57,24 @@ class Version { } } +Function Resolve-Proxy { + $testProxyExe = "test-proxy" + # this script requires the presence of the test-proxy on the PATH + $proxyToolPresent = Test-Exe-In-Path -ExeToLookFor "test-proxy" -ExitOnError $false + $proxyStandalonePresent = Test-Exe-In-Path -ExeToLookFor "Azure.Sdk.Tools.TestProxy" -ExitOnError $false + + if (-not $proxyToolPresent -and -not $proxyStandalonePresent) { + Write-Error "This script requires the presence of a test-proxy executable to complete its operations. Exiting." + exit 1 + } + + if (-not $proxyToolPresent) { + $testProxyExe = "Azure.Sdk.Tools.TestProxy" + } + + return $testProxyExe +} + Function Test-Exe-In-Path { Param([string] $ExeToLookFor, [bool]$ExitOnError = $true) if ($null -eq (Get-Command $ExeToLookFor -ErrorAction SilentlyContinue)) { diff --git a/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 b/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 new file mode 100644 index 000000000000..ba51798c5a93 --- /dev/null +++ b/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 @@ -0,0 +1,92 @@ +#Requires -Version 6.0 +#Requires -PSEdition Core + +<# +.SYNOPSIS +Within an assets.json file that has in a conflicted state (specifically on asset tag), merge the two tags that are conflicting and leave the assets.json in a commitable state. + +.DESCRIPTION +USAGE: resolve-asset-conflict.ps1 path/to/target_assets_json + +Parses the assets.json file and determines which tags are in conflict. If there are no conflicts, the script exits. + +1. Parse the tags (base and target) from conflicting assets.json. +2. Update the assets.json with the base tag, but remember the target tag. +3. merge-proxy-tags.ps1 $AssetsJson base_tag target_tag + +This script requires that test-proxy or azure.sdk.tools.testproxy should be on the PATH. + +.PARAMETER AssetsJson +The script uses a target assets.json to understand what tags are in conflict. This is the only required parameter. +#> + +param( + [Parameter(Position=0)] + [string] $AssetsJson +) + + +. (Join-Path $PSScriptRoot ".." ".." "onboarding" "common-asset-functions.ps1") + +function Get-AssetsBase { + param( + [Parameter(Position=0)] + [string] $AssetsJson + ) + + $AssetsContent = Get-Content -Raw $AssetsJson + + + # $Assets = ConvertFrom-Json $AssetsContent + + # $AssetsVersions = @{} + + # foreach ($Asset in $Assets) { + # $AssetsVersions[$Asset.name] = $Asset.version + # } + + return $AssetsVersions +} + +function Get-AssetsTarget { + param( + [Parameter(Position=0)] + [string] $AssetsJson + ) + + $AssetsContent = Get-Content -Raw $AssetsJson + + + # $Assets = ConvertFrom-Json $AssetsContent + + # $AssetsVersions = @{} + + # foreach ($Asset in $Assets) { + # $AssetsVersions[$Asset.name] = $Asset.version + # } + + return $AssetsVersions +} + +$TestProxy = Resolve-Proxy + +if (!(Test-Path $AssetsJson)) { + Write-Error "AssetsJson file does not exist: $AssetsJson" + exit 1 +} + +$AssetsJson = Resolve-Path $AssetsJson + +if ($AssetsJson.Name -ne "assets.json") { + Write-Error "This script can only resolve conflicts within an assets.json. The file provided is not an assets.json: $AssetsJson" + exit 1 +} + + + +$BaseAssets = Get-AssetsBase $AssetsJson +$TargetAssets = Get-AssetsTarget $AssetsJson + +$TargetAssets | ConvertTo-Json -Depth 100 | Out-File $AssetsJson + +$PSScriptRoot/../tag-merge/merge-proxy-tags.ps1 $AssetsJson $BaseAssets.Tag $TargetAssets.Tag diff --git a/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 b/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 index 18e57acc589f..1a81a83a463e 100644 --- a/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 +++ b/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 @@ -68,24 +68,6 @@ function Git-Command($CommandString, $WorkingDirectory, $HardExit=$true) { return $result.Output } -function Resolve-Proxy { - $testProxyExe = "test-proxy" - # this script requires the presence of the test-proxy on the PATH - $proxyToolPresent = Test-Exe-In-Path -ExeToLookFor "test-proxy" -ExitOnError $false - $proxyStandalonePresent = Test-Exe-In-Path -ExeToLookFor "Azure.Sdk.Tools.TestProxy" -ExitOnError $false - - if (-not $proxyToolPresent -and -not $proxyStandalonePresent) { - Write-Error "This script requires the presence of a test-proxy executable to complete its operations. Exiting." - exit 1 - } - - if (-not $proxyToolPresent) { - $testProxyExe = "Azure.Sdk.Tools.TestProxy" - } - - return $testProxyExe -} - function Call-Proxy { param( [string] $TestProxyExe, From 74cda5f8fbcec75094135e1d7786ab4268fa756e Mon Sep 17 00:00:00 2001 From: "Scott Beddall (from Dev Box)" Date: Tue, 16 Jan 2024 12:44:36 -0800 Subject: [PATCH 02/10] basic shape of the differ is done. need to understand why this function isn't actually calling the constructor --- eng/common/scripts/Helpers/git-helpers.ps1 | 71 +++++++++++++++++++ .../scripts/Helpers/git-helpers.tests.ps1 | 57 +++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 eng/common/scripts/Helpers/git-helpers.tests.ps1 diff --git a/eng/common/scripts/Helpers/git-helpers.ps1 b/eng/common/scripts/Helpers/git-helpers.ps1 index e9feafe4636f..faa6b1af3db4 100644 --- a/eng/common/scripts/Helpers/git-helpers.ps1 +++ b/eng/common/scripts/Helpers/git-helpers.ps1 @@ -36,3 +36,74 @@ function Get-ChangedFiles { } return $changedFiles } + +class ConflictedFile { + [string]$LeftSource = "" + [string]$RightSource = "" + [string]$Content = "" + [string]$Path = "" + [boolean]$IsConflicted = $false + + ConflictedFile([string]$File = "") { + if (!(Test-Path $File)) { + throw "File $File does not exist, pass a valid file path to the constructor." + } + + $this.Path = Resolve-Path $File + $this.Content = Get-Content -Raw $File + + Write-Host $this.Content + $this.ParseContent($this.Content) + } + + [string] Left(){ + if ($this.IsConflicted) { + $tempContent = git show $this.LeftSource:$this.Path + return $tempContent + } + else { + return $this.Content + } + } + + [string] Right(){ + if ($this.IsConflicted) { + $tempContent = git show $this.RightSource:$this.Path + return $tempContent + } + else { + return $this.Content + } + } + + [void] ParseContent([string]$IncomingContent) { + $lines = $IncomingContent -split "`r?`n" + $l = @() + $r = @() + $direction = "both" + + foreach($line in $lines) { + Write-Host $line + + $leftMatch = $line -match "^<<<<<<<\s*(.+)" + $rightMatch = $line -match "^>>>>>>>\s*(.+)" + # state machine for choosing what we're looking at + if ($leftMatch) { + $this.IsConflicted = $true + + Write-Host $leftMatch + + $this.LeftSource = $leftMatch[1] + continue + } + elseif ($rightMatch) { + $this.IsConflicted = $true + + Write-Host $rightMatch + + $this.RightSource = $rightMatch[1] + continue + } + } + } +} diff --git a/eng/common/scripts/Helpers/git-helpers.tests.ps1 b/eng/common/scripts/Helpers/git-helpers.tests.ps1 new file mode 100644 index 000000000000..f048fe8946a4 --- /dev/null +++ b/eng/common/scripts/Helpers/git-helpers.tests.ps1 @@ -0,0 +1,57 @@ +# Install-Module -Name Pester -Force -SkipPublisherCheck +# Invoke-Pester -Passthru path/to/git-helpers.tests.ps1 +BeforeAll { + . $PSScriptRoot/git-helpers.ps1 + + $RunFolder = "$PSScriptRoot/.testruns" + + if (Test-Path $RunFolder){ + Remove-Item -Recurse -Force $RunFolder + } + + New-Item -ItemType Directory -Path $RunFolder +} + +Describe "git-helpers.ps1 tests"{ + Context "Test Parse-ConflictedFile" { + It "Parses a basic conflicted file" { + $content = @' +{ + "AssetsRepo": "Azure/azure-sdk-assets-integration", + "AssetsRepoPrefixPath": "python", + "TagPrefix": "python/storage/azure-storage-blob", +<<<<<<< HEAD + "Tag": "integration/example/storage_feature_addition2" +======= + "Tag": "integration/example/storage_feature_addition1" +>>>>>>> test-storage-tag-combination +} +'@ + $contentPath = Join-Path $RunFolder "basic_conflict_test.json" + Set-Content -Path $contentPath -Value $content + + $resolution = [ConflictedFile]::new($contentPath) + $resolution.IsConflicted | Should -Be $true + $resolution.LeftSource | Should -Be "HEAD" + $resolution.RightSource | Should -Be "test-storage-tag-combination" + } + + It "Recognizes when no conflicts are present" { + $content = @' +{ + "AssetsRepo": "Azure/azure-sdk-assets-integration", + "AssetsRepoPrefixPath": "python", + "TagPrefix": "python/storage/azure-storage-blob", + "Tag": "integration/example/storage_feature_addition1" +} +'@ + $contentPath = Join-Path $RunFolder "no_conflict_test.json" + Set-Content -Path $contentPath -Value $content + + $resolution = [ConflictedFile]::new($contentPath) + $resolution.IsConflicted | Should -Be $false + $resolution.LeftSource | Should -Be "" + $resolution.RightSource | Should -Be "" + } + } +} \ No newline at end of file From 30400d6bfa6557eb803a0001d460c5b470f977fa Mon Sep 17 00:00:00 2001 From: "Scott Beddall (from Dev Box)" Date: Tue, 16 Jan 2024 13:12:57 -0800 Subject: [PATCH 03/10] now we are properly getting a result out of git show. the problem is we're destroying the newlines. gotta be a better way to get the results --- eng/common/scripts/Helpers/git-helpers.ps1 | 30 ++++++++-------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/eng/common/scripts/Helpers/git-helpers.ps1 b/eng/common/scripts/Helpers/git-helpers.ps1 index faa6b1af3db4..a6f97211042e 100644 --- a/eng/common/scripts/Helpers/git-helpers.ps1 +++ b/eng/common/scripts/Helpers/git-helpers.ps1 @@ -49,16 +49,18 @@ class ConflictedFile { throw "File $File does not exist, pass a valid file path to the constructor." } - $this.Path = Resolve-Path $File + # Normally we would use Resolve-Path $file, but git only can handle relative paths using git show : + # Therefore, just maintain whatever the path is here. + $this.Path = $File $this.Content = Get-Content -Raw $File - Write-Host $this.Content $this.ParseContent($this.Content) } [string] Left(){ if ($this.IsConflicted) { - $tempContent = git show $this.LeftSource:$this.Path + Write-Host "& git show --textconv $($this.LeftSource):$($this.Path)" + $tempContent = & git show --textconv "$($this.LeftSource):$($this.Path)" return $tempContent } else { @@ -68,7 +70,8 @@ class ConflictedFile { [string] Right(){ if ($this.IsConflicted) { - $tempContent = git show $this.RightSource:$this.Path + Write-Host "& git show --textconv $($this.RightSource):$($this.Path)" + $tempContent = & git show --textconv "$($this.RightSource):$($this.Path)" return $tempContent } else { @@ -83,25 +86,14 @@ class ConflictedFile { $direction = "both" foreach($line in $lines) { - Write-Host $line - - $leftMatch = $line -match "^<<<<<<<\s*(.+)" - $rightMatch = $line -match "^>>>>>>>\s*(.+)" - # state machine for choosing what we're looking at - if ($leftMatch) { + if ($line -match "^<<<<<<<\s*(.+)") { $this.IsConflicted = $true - - Write-Host $leftMatch - - $this.LeftSource = $leftMatch[1] + $this.LeftSource = $matches[1] continue } - elseif ($rightMatch) { + elseif ($line -match "^>>>>>>>\s*(.+)") { $this.IsConflicted = $true - - Write-Host $rightMatch - - $this.RightSource = $rightMatch[1] + $this.RightSource = $matches[1] continue } } From bd1a9e4144fc9433a7ea91df9d8c51d1f04d2bf1 Mon Sep 17 00:00:00 2001 From: "Scott Beddall (from Dev Box)" Date: Tue, 16 Jan 2024 13:58:45 -0800 Subject: [PATCH 04/10] add some clarity via comment as to why certain choices were made --- eng/common/scripts/Helpers/git-helpers.ps1 | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/eng/common/scripts/Helpers/git-helpers.ps1 b/eng/common/scripts/Helpers/git-helpers.ps1 index a6f97211042e..5d852d85b090 100644 --- a/eng/common/scripts/Helpers/git-helpers.ps1 +++ b/eng/common/scripts/Helpers/git-helpers.ps1 @@ -50,7 +50,8 @@ class ConflictedFile { } # Normally we would use Resolve-Path $file, but git only can handle relative paths using git show : - # Therefore, just maintain whatever the path is here. + # Therefore, just maintain whatever the path is given to us. Left() and Right() should therefore be called from the same + # directory as where we defined the relative path to the target file. $this.Path = $File $this.Content = Get-Content -Raw $File @@ -59,9 +60,14 @@ class ConflictedFile { [string] Left(){ if ($this.IsConflicted) { - Write-Host "& git show --textconv $($this.LeftSource):$($this.Path)" - $tempContent = & git show --textconv "$($this.LeftSource):$($this.Path)" - return $tempContent + # we are forced to get this line by line and reassemble via join because of how powershell is interacting with + # git show --textconv commitsh:path + # powershell ignores the newlines with and without --textconv, which results in a json file without original spacing. + # by forcefully reading into the array line by line, the whitespace is preserved. we're relying on gits autoconverstion of clrf to lf + # to ensure that the line endings are consistent. + Write-Host "& git show $($this.LeftSource):$($this.Path)" + [array]$tempContent = & git show "$($this.LeftSource):$($this.Path)" + return $tempContent -join "`n" } else { return $this.Content @@ -70,9 +76,9 @@ class ConflictedFile { [string] Right(){ if ($this.IsConflicted) { - Write-Host "& git show --textconv $($this.RightSource):$($this.Path)" - $tempContent = & git show --textconv "$($this.RightSource):$($this.Path)" - return $tempContent + Write-Host "& git show $($this.RightSource):$($this.Path)" + [array]$tempContent = & git show "$($this.RightSource):$($this.Path)" + return $tempContent -join `n } else { return $this.Content @@ -83,7 +89,6 @@ class ConflictedFile { $lines = $IncomingContent -split "`r?`n" $l = @() $r = @() - $direction = "both" foreach($line in $lines) { if ($line -match "^<<<<<<<\s*(.+)") { @@ -96,6 +101,10 @@ class ConflictedFile { $this.RightSource = $matches[1] continue } + + if ($this.LeftSource -and $this.RightSource) { + break + } } } } From 44c9afa3dda14103312ee19f03558dcc42541d3a Mon Sep 17 00:00:00 2001 From: "Scott Beddall (from Dev Box)" Date: Tue, 16 Jan 2024 15:44:08 -0800 Subject: [PATCH 05/10] having issues with formatting, so removing the problem --- eng/common/scripts/Helpers/git-helpers.ps1 | 10 +-- .../scripts/resolve-asset-conflict/README.md | 54 +++++++++++++ .../resolve-asset-conflict.ps1 | 80 ++++++++----------- .../testproxy/scripts/tag-merge/README.md | 2 +- 4 files changed, 92 insertions(+), 54 deletions(-) create mode 100644 eng/common/testproxy/scripts/resolve-asset-conflict/README.md diff --git a/eng/common/scripts/Helpers/git-helpers.ps1 b/eng/common/scripts/Helpers/git-helpers.ps1 index 5d852d85b090..114ee0fcce12 100644 --- a/eng/common/scripts/Helpers/git-helpers.ps1 +++ b/eng/common/scripts/Helpers/git-helpers.ps1 @@ -65,9 +65,8 @@ class ConflictedFile { # powershell ignores the newlines with and without --textconv, which results in a json file without original spacing. # by forcefully reading into the array line by line, the whitespace is preserved. we're relying on gits autoconverstion of clrf to lf # to ensure that the line endings are consistent. - Write-Host "& git show $($this.LeftSource):$($this.Path)" - [array]$tempContent = & git show "$($this.LeftSource):$($this.Path)" - return $tempContent -join "`n" + Write-Host "git show $($this.LeftSource):$($this.Path)" + return git show ("$($this.LeftSource):$($this.Path)") } else { return $this.Content @@ -76,9 +75,8 @@ class ConflictedFile { [string] Right(){ if ($this.IsConflicted) { - Write-Host "& git show $($this.RightSource):$($this.Path)" - [array]$tempContent = & git show "$($this.RightSource):$($this.Path)" - return $tempContent -join `n + Write-Host "git show $($this.RightSource):$($this.Path)" + return git show ("$($this.RightSource):$($this.Path)") } else { return $this.Content diff --git a/eng/common/testproxy/scripts/resolve-asset-conflict/README.md b/eng/common/testproxy/scripts/resolve-asset-conflict/README.md new file mode 100644 index 000000000000..ca497317c4fb --- /dev/null +++ b/eng/common/testproxy/scripts/resolve-asset-conflict/README.md @@ -0,0 +1,54 @@ +# Merge Proxy Tags Script + +This script is intended to allow easy resolution of a conflicting `assets.json` file. + +In most cases where two branches `X` and `Y` have progressed alongside each other, a simple + +`git checkout X && git merge Y` can successfully merge _other_ than the `assets.json` file. + +That often will end up looking like this: + +```text +{ + "AssetsRepo": "Azure/azure-sdk-assets-integration", + "AssetsRepoPrefixPath": "python", + "TagPrefix": "python/storage/azure-storage-blob", +<<<<<<< HEAD + "Tag": "integration/example/storage_feature_addition2" +======= + "Tag": "integration/example/storage_feature_addition1" +>>>>>>> test-storage-tag-combination +} +``` + +This script uses `git` to tease out the source and target tags, then merge the incoming tag into the recordings of the base tag. + +This script should _only_ be used on an already conflicted `assets.json` file. Otherwise, no action will be executed. + +## Usage + +### PreReqs + +- Must have []`pshell 6+`](https://learn.microsoft.com/powershell/scripting/install/installing-powershell-on-windows) +- Must have `git` available on your PATH +- Must have the `test-proxy` available on your PATH + - `test-proxy` is honored when the proxy is installed as a `dotnet tool` + - `Azure.Sdk.Tools.TestProxy` is honored when the standalone executable is on your PATH + - Defaults to `dotnet tool` if both are present on the PATH. + +### Call the script + +```powershell +# including context to get into a merge conflict +cd "path/to/language/repo/root" +git checkout base-branch +git merge target-branch +# auto resolve / merge conflicting tag values +./eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 sdk/storage/azure-storage-blob/assets.json +# user pushes +test-proxy push -a sdk/storage/azure-storage-blob/assets.json +``` + +### Resolving conflicts + + implement this and see what falls out. diff --git a/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 b/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 index ba51798c5a93..d7c2d11865b3 100644 --- a/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 +++ b/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 @@ -25,48 +25,8 @@ param( [string] $AssetsJson ) - . (Join-Path $PSScriptRoot ".." ".." "onboarding" "common-asset-functions.ps1") - -function Get-AssetsBase { - param( - [Parameter(Position=0)] - [string] $AssetsJson - ) - - $AssetsContent = Get-Content -Raw $AssetsJson - - - # $Assets = ConvertFrom-Json $AssetsContent - - # $AssetsVersions = @{} - - # foreach ($Asset in $Assets) { - # $AssetsVersions[$Asset.name] = $Asset.version - # } - - return $AssetsVersions -} - -function Get-AssetsTarget { - param( - [Parameter(Position=0)] - [string] $AssetsJson - ) - - $AssetsContent = Get-Content -Raw $AssetsJson - - - # $Assets = ConvertFrom-Json $AssetsContent - - # $AssetsVersions = @{} - - # foreach ($Asset in $Assets) { - # $AssetsVersions[$Asset.name] = $Asset.version - # } - - return $AssetsVersions -} +. (Join-Path $PSScriptRoot ".." ".." ".." "scripts" "Helpers" "git-helpers.ps1") $TestProxy = Resolve-Proxy @@ -75,18 +35,44 @@ if (!(Test-Path $AssetsJson)) { exit 1 } -$AssetsJson = Resolve-Path $AssetsJson +# normally we we would Resolve-Path the $AssetsJson, but the git show command only works with relative paths, so we'll just keep that here. -if ($AssetsJson.Name -ne "assets.json") { +if (-not $AssetsJson.EndsWith("assets.json")) { Write-Error "This script can only resolve conflicts within an assets.json. The file provided is not an assets.json: $AssetsJson" exit 1 } +$conflictingAssets = [ConflictedFile]::new($AssetsJson) + +if (-not $conflictingAssets.IsConflicted) { + Write-Host "No conflicts found in $AssetsJson, nothing to resolve, so there is no second tag to merge. Exiting" + exit 0 +} + +# this is very dumb, but will properly work! +try { + $BaseAssets = $conflictingAssets.Left() | ConvertFrom-Json +} +catch { + Write-Error "Failed to convert previous version to valid JSON format." + exit 1 +} + +try { + $TargetAssets = $conflictingAssets.Right() | ConvertFrom-Json +} +catch { + Write-Error "Failed to convert target assets.json version to valid JSON format." + exit 1 +} +Write-Host "Replacing conflicted assets.json with base branch version." -ForegroundColor Green +Set-Content -Path $AssetsJson -Value $conflictingAssets.Left() -$BaseAssets = Get-AssetsBase $AssetsJson -$TargetAssets = Get-AssetsTarget $AssetsJson +# $PSScriptRoot/../tag-merge/merge-proxy-tags.ps1 $AssetsJson $BaseAssets.Tag $TargetAssets.Tag -$TargetAssets | ConvertTo-Json -Depth 100 | Out-File $AssetsJson +# Write-Host $lastexitcode -$PSScriptRoot/../tag-merge/merge-proxy-tags.ps1 $AssetsJson $BaseAssets.Tag $TargetAssets.Tag +# if ($lastexitcode -eq 0) { +# Write-Host "Successfully merged '$($TargetASsets.Tag)' into '$($BaseAssets.Tag)'. Invoke 'test-proxy push $AssetsJson' and commit the result before continuing the merge!" -ForegroundColor Green +# } \ No newline at end of file diff --git a/eng/common/testproxy/scripts/tag-merge/README.md b/eng/common/testproxy/scripts/tag-merge/README.md index d72dd4dbefac..d16dc3be054e 100644 --- a/eng/common/testproxy/scripts/tag-merge/README.md +++ b/eng/common/testproxy/scripts/tag-merge/README.md @@ -16,7 +16,7 @@ This script merely allows the abstraction of some of this "combination" work. - Must have the `test-proxy` available on your PATH - `test-proxy` is honored when the proxy is installed as a `dotnet tool` - `Azure.Sdk.Tools.TestProxy` is honored when the standalone executable is on your PATH - - Preference for `dotnet tool` if present + - Defaults to `dotnet tool` if both are present on the PATH. ### Call the script From efe17e8f9020d3bf757df7e7f2b2d5fa4cb1352c Mon Sep 17 00:00:00 2001 From: "Scott Beddall (from Dev Box)" Date: Tue, 16 Jan 2024 16:04:39 -0800 Subject: [PATCH 06/10] properly get the content of the left and ride side versions of the file --- eng/common/scripts/Helpers/git-helpers.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/eng/common/scripts/Helpers/git-helpers.ps1 b/eng/common/scripts/Helpers/git-helpers.ps1 index 114ee0fcce12..d80df4ca3b14 100644 --- a/eng/common/scripts/Helpers/git-helpers.ps1 +++ b/eng/common/scripts/Helpers/git-helpers.ps1 @@ -58,7 +58,7 @@ class ConflictedFile { $this.ParseContent($this.Content) } - [string] Left(){ + [array] Left(){ if ($this.IsConflicted) { # we are forced to get this line by line and reassemble via join because of how powershell is interacting with # git show --textconv commitsh:path @@ -66,17 +66,19 @@ class ConflictedFile { # by forcefully reading into the array line by line, the whitespace is preserved. we're relying on gits autoconverstion of clrf to lf # to ensure that the line endings are consistent. Write-Host "git show $($this.LeftSource):$($this.Path)" - return git show ("$($this.LeftSource):$($this.Path)") + $tempContent = (git show ("$($this.LeftSource):$($this.Path)")) + return $tempContent -split "`r?`n" } else { return $this.Content } } - [string] Right(){ + [array] Right(){ if ($this.IsConflicted) { Write-Host "git show $($this.RightSource):$($this.Path)" - return git show ("$($this.RightSource):$($this.Path)") + $tempContent = git show ("$($this.RightSource):$($this.Path)") + return $tempContent -split "`r?`n" } else { return $this.Content From 41da3ccc3e61e182e6ee9b19e08bb46ea1421e63 Mon Sep 17 00:00:00 2001 From: "Scott Beddall (from Dev Box)" Date: Tue, 16 Jan 2024 16:57:33 -0800 Subject: [PATCH 07/10] basic resolution should be working now --- .../scripts/resolve-asset-conflict/README.md | 2 ++ .../resolve-asset-conflict.ps1 | 14 +++++++------- .../scripts/tag-merge/merge-proxy-tags.ps1 | 9 ++++++--- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/eng/common/testproxy/scripts/resolve-asset-conflict/README.md b/eng/common/testproxy/scripts/resolve-asset-conflict/README.md index ca497317c4fb..f7b8325925d3 100644 --- a/eng/common/testproxy/scripts/resolve-asset-conflict/README.md +++ b/eng/common/testproxy/scripts/resolve-asset-conflict/README.md @@ -38,6 +38,8 @@ This script should _only_ be used on an already conflicted `assets.json` file. O ### Call the script +For simplicity when resolving merge-conflicts, invoke the script from the root of the repo. The help instructions from `merge-asset-tags` use paths relative from repo root. + ```powershell # including context to get into a merge conflict cd "path/to/language/repo/root" diff --git a/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 b/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 index d7c2d11865b3..e5bb418d2ef8 100644 --- a/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 +++ b/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 @@ -36,7 +36,6 @@ if (!(Test-Path $AssetsJson)) { } # normally we we would Resolve-Path the $AssetsJson, but the git show command only works with relative paths, so we'll just keep that here. - if (-not $AssetsJson.EndsWith("assets.json")) { Write-Error "This script can only resolve conflicts within an assets.json. The file provided is not an assets.json: $AssetsJson" exit 1 @@ -69,10 +68,11 @@ catch { Write-Host "Replacing conflicted assets.json with base branch version." -ForegroundColor Green Set-Content -Path $AssetsJson -Value $conflictingAssets.Left() -# $PSScriptRoot/../tag-merge/merge-proxy-tags.ps1 $AssetsJson $BaseAssets.Tag $TargetAssets.Tag - -# Write-Host $lastexitcode +$PSScriptRoot/../tag-merge/merge-proxy-tags.ps1 $AssetsJson $BaseAssets.Tag $TargetAssets.Tag -# if ($lastexitcode -eq 0) { -# Write-Host "Successfully merged '$($TargetASsets.Tag)' into '$($BaseAssets.Tag)'. Invoke 'test-proxy push $AssetsJson' and commit the result before continuing the merge!" -ForegroundColor Green -# } \ No newline at end of file +if ($lastexitcode -eq 0) { + Write-Host "Successfully merged '$($TargetASsets.Tag)' into '$($BaseAssets.Tag)'. Invoke 'test-proxy push -a $AssetsJson' and commit the resulting assets.json!" -ForegroundColor Green +} +else { + Write-Host "Conflicts were discovered, resolve the conflicts and invoke the `"merge-proxy-tags.ps1`" as recommended in the line directly above." +} \ No newline at end of file diff --git a/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 b/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 index 1a81a83a463e..7f76d6466aa3 100644 --- a/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 +++ b/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 @@ -238,14 +238,16 @@ function Prepare-Assets($ProxyExe, $MountDirectory, $AssetsJson) { } } -function Combine-Tags($RemainingTags, $AssetsRepoLocation, $MountDirectory){ +function Combine-Tags($RemainingTags, $AssetsRepoLocation, $MountDirectory, $RelativeAssetsJson){ + $remainingTagString = $RemainingTags -join " " foreach($Tag in $RemainingTags) { $tagSha = Get-Tag-SHA $Tag $AssetsRepoLocation $existingTags = Save-Incomplete-Progress $Tag $MountDirectory $cherryPickResult = Git-Command-With-Result "cherry-pick $tagSha" - $AssetsRepoLocation -HardExit $false if ($cherryPickResult.ExitCode -ne 0) { - Write-Host "Conflicts while cherry-picking $Tag. Resolve the the conflict over in `"$AssetsRepoLocation`", and re-run this script with the same arguments as before." -ForegroundColor Red + Write-Host "Conflicts while cherry-picking $Tag. Resolve the the conflict over in `"$AssetsRepoLocation`", and re-invoke " + + "by `"./eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 $RelativeAssetsJson $remainingTagString`"" -ForegroundColor Red exit 1 } } @@ -276,6 +278,7 @@ if ($PSVersionTable["PSVersion"].Major -lt 6) { # resolve the proxy location so that we can invoke it easily, if not present we exit here. $proxyExe = Resolve-Proxy +$relativeAssetsJson = $AssetsJson $AssetsJson = Resolve-Path $AssetsJson # figure out where the root of the repo for the passed assets.json is. We need it to properly set the mounting @@ -295,6 +298,6 @@ $tags = Resolve-Target-Tags $AssetsJson $TargetTags $mountDirectory Start-Message $AssetsJson $Tags $AssetsRepoLocation $mountDirectory -$CombinedTags = Combine-Tags $Tags $AssetsRepoLocation $mountDirectory +$CombinedTags = Combine-Tags $Tags $AssetsRepoLocation $mountDirectory $relativeAssetsJson Finish-Message $AssetsJson $CombinedTags $AssetsRepoLocation $mountDirectory From a2c7c2918cd77c9def91ab4e00cbbc6e76d183c6 Mon Sep 17 00:00:00 2001 From: "Scott Beddall (from Dev Box)" Date: Tue, 16 Jan 2024 17:03:31 -0800 Subject: [PATCH 08/10] basic auto-merge resolution is definitely working --- .../resolve-asset-conflict/resolve-asset-conflict.ps1 | 5 +++-- eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 b/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 index e5bb418d2ef8..c11e9c879e6c 100644 --- a/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 +++ b/eng/common/testproxy/scripts/resolve-asset-conflict/resolve-asset-conflict.ps1 @@ -68,10 +68,11 @@ catch { Write-Host "Replacing conflicted assets.json with base branch version." -ForegroundColor Green Set-Content -Path $AssetsJson -Value $conflictingAssets.Left() -$PSScriptRoot/../tag-merge/merge-proxy-tags.ps1 $AssetsJson $BaseAssets.Tag $TargetAssets.Tag +$ScriptPath = Join-Path $PSScriptRoot ".." "tag-merge" "merge-proxy-tags.ps1" +& $ScriptPath $AssetsJson $BaseAssets.Tag $TargetAssets.Tag if ($lastexitcode -eq 0) { - Write-Host "Successfully merged '$($TargetASsets.Tag)' into '$($BaseAssets.Tag)'. Invoke 'test-proxy push -a $AssetsJson' and commit the resulting assets.json!" -ForegroundColor Green + Write-Host "Successfully auto-merged assets tag '$($TargetASsets.Tag)' into tag '$($BaseAssets.Tag)'. Invoke 'test-proxy push -a $AssetsJson' and commit the resulting assets.json!" -ForegroundColor Green } else { Write-Host "Conflicts were discovered, resolve the conflicts and invoke the `"merge-proxy-tags.ps1`" as recommended in the line directly above." diff --git a/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 b/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 index 7f76d6466aa3..715e4b177538 100644 --- a/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 +++ b/eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 @@ -246,8 +246,9 @@ function Combine-Tags($RemainingTags, $AssetsRepoLocation, $MountDirectory, $Rel $cherryPickResult = Git-Command-With-Result "cherry-pick $tagSha" - $AssetsRepoLocation -HardExit $false if ($cherryPickResult.ExitCode -ne 0) { - Write-Host "Conflicts while cherry-picking $Tag. Resolve the the conflict over in `"$AssetsRepoLocation`", and re-invoke " + - "by `"./eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 $RelativeAssetsJson $remainingTagString`"" -ForegroundColor Red + $error = "Conflicts while cherry-picking $Tag. Resolve the the conflict over in `"$AssetsRepoLocation`", and re-invoke " + + "by `"./eng/common/testproxy/scripts/tag-merge/merge-proxy-tags.ps1 $RelativeAssetsJson $remainingTagString`"" + Write-Host $error -ForegroundColor Red exit 1 } } From 6eeb9dbb32ab917dd188a75b9337cd4b090b3f44 Mon Sep 17 00:00:00 2001 From: "Scott Beddall (from Dev Box)" Date: Tue, 16 Jan 2024 17:12:48 -0800 Subject: [PATCH 09/10] updating the error resolution side --- .../testproxy/scripts/resolve-asset-conflict/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/eng/common/testproxy/scripts/resolve-asset-conflict/README.md b/eng/common/testproxy/scripts/resolve-asset-conflict/README.md index f7b8325925d3..13326596e32e 100644 --- a/eng/common/testproxy/scripts/resolve-asset-conflict/README.md +++ b/eng/common/testproxy/scripts/resolve-asset-conflict/README.md @@ -53,4 +53,10 @@ test-proxy push -a sdk/storage/azure-storage-blob/assets.json ### Resolving conflicts - implement this and see what falls out. +When an assets.json merge has conflicts on the **test recordings** side, the `merge-proxy-tags` script will exit with an error describing how to re-invoke the `merge-proxy-tags` script AFTER you resolve the conflicts. + +- `cd` into the assets location output by the script +- resolve the conflict or conflicts +- add the resolution, and invoke `git cherry-pick --continue` + +Afterwards, re-invoke the `merge-proxy-tags` script with arguments given to you in original error. This will leave the assets in a `touched` state that can be `test-proxy push`-ed. From 5005627106aca63c92b6ebc4d4b18ca9bd37d688 Mon Sep 17 00:00:00 2001 From: Scott Beddall <45376673+scbedd@users.noreply.github.com> Date: Wed, 17 Jan 2024 11:09:50 -0800 Subject: [PATCH 10/10] Update eng/common/scripts/Helpers/git-helpers.ps1 Co-authored-by: Ben Broderick Phillips --- eng/common/scripts/Helpers/git-helpers.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/common/scripts/Helpers/git-helpers.ps1 b/eng/common/scripts/Helpers/git-helpers.ps1 index d80df4ca3b14..2365304bedcb 100644 --- a/eng/common/scripts/Helpers/git-helpers.ps1 +++ b/eng/common/scripts/Helpers/git-helpers.ps1 @@ -66,7 +66,7 @@ class ConflictedFile { # by forcefully reading into the array line by line, the whitespace is preserved. we're relying on gits autoconverstion of clrf to lf # to ensure that the line endings are consistent. Write-Host "git show $($this.LeftSource):$($this.Path)" - $tempContent = (git show ("$($this.LeftSource):$($this.Path)")) + $tempContent = git show ("$($this.LeftSource):$($this.Path)") return $tempContent -split "`r?`n" } else {