Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a GitHub action to perform a Binary Diff job on each PR/push event #14007

Merged
merged 24 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
258 changes: 258 additions & 0 deletions .github/scripts/bin_diff.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
################################################################################
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this script based on some sample code? Did it have a license, can we link to it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added source.

### USAGE: bin_diff.ps1 path/to/left,path/to/right [-s path/to/summary/dir] ###
### ADD LOCATION OF THIS SCRIPT TO PATH ###
################################################################################
[CmdletBinding()]
param (
[parameter(HelpMessage="Stores the execution working directory.")]
[string]$ExecutionDirectory=$PWD,

[parameter(Position=0,HelpMessage="Compare two directories recursively for differences.")]
[alias("c")]
[string[]]$Compare,

[parameter(HelpMessage="Export a summary to path.")]
[alias("s")]
[string]$ExportSummary
)

### FUNCTION DEFINITIONS ###

# SETS WORKING DIRECTORY FOR .NET #
function SetWorkDir($PathName, $TestPath) {
$AbsPath = NormalizePath $PathName $TestPath
Set-Location $AbsPath
[System.IO.Directory]::SetCurrentDirectory($AbsPath)
}

# RESTORES THE EXECUTION WORKING DIRECTORY AND EXITS #
function SafeExit() {
SetWorkDir /path/to/execution/directory $ExecutionDirectory
Exit
}

function Print {
[CmdletBinding()]
param (
[parameter(Mandatory=$TRUE,Position=0,HelpMessage="Message to print.")]
[string]$Message,

[parameter(HelpMessage="Specifies a success.")]
[alias("s")]
[switch]$SuccessFlag,

[parameter(HelpMessage="Specifies a warning.")]
[alias("w")]
[switch]$WarningFlag,

[parameter(HelpMessage="Specifies an error.")]
[alias("e")]
[switch]$ErrorFlag,

[parameter(HelpMessage="Specifies a fatal error.")]
[alias("f")]
[switch]$FatalFlag,

[parameter(HelpMessage="Specifies a info message.")]
[alias("i")]
[switch]$InfoFlag = !$SuccessFlag -and !$WarningFlag -and !$ErrorFlag -and !$FatalFlag,

[parameter(HelpMessage="Specifies blank lines to print before.")]
[alias("b")]
[int]$LinesBefore=0,

[parameter(HelpMessage="Specifies blank lines to print after.")]
[alias("a")]
[int]$LinesAfter=0,

[parameter(HelpMessage="Specifies if program should exit.")]
[alias("x")]
[switch]$ExitAfter
)
PROCESS {
if($LinesBefore -ne 0) {
foreach($i in 0..$LinesBefore) { Write-Host "" }
}
if($InfoFlag) { Write-Host "$Message" }
if($SuccessFlag) { Write-Host "$Message" -ForegroundColor "Green" }
if($WarningFlag) { Write-Host "$Message" -ForegroundColor "Orange" }
if($ErrorFlag) { Write-Host "$Message" -ForegroundColor "Red" }
if($FatalFlag) { Write-Host "$Message" -ForegroundColor "Red" -BackgroundColor "Black" }
if($LinesAfter -ne 0) {
foreach($i in 0..$LinesAfter) { Write-Host "" }
}
if($ExitAfter) { SafeExit }
}
}

# VALIDATES STRING MIGHT BE A PATH #
function ValidatePath($PathName, $TestPath) {
If([string]::IsNullOrWhiteSpace($TestPath)) {
Print -x -f "$PathName is not a path"
}
}

# NORMALIZES RELATIVE OR ABSOLUTE PATH TO ABSOLUTE PATH #
function NormalizePath($PathName, $TestPath) {
ValidatePath "$PathName" "$TestPath"
$TestPath = [System.IO.Path]::Combine((pwd).Path, $TestPath)
$NormalizedPath = [System.IO.Path]::GetFullPath($TestPath)
return $NormalizedPath
}


# VALIDATES STRING MIGHT BE A PATH AND RETURNS ABSOLUTE PATH #
function ResolvePath($PathName, $TestPath) {
ValidatePath "$PathName" "$TestPath"
$ResolvedPath = NormalizePath $PathName $TestPath
return $ResolvedPath
}

# VALIDATES STRING RESOLVES TO A PATH AND RETURNS ABSOLUTE PATH #
function RequirePath($PathName, $TestPath, $PathType) {
ValidatePath $PathName $TestPath
If(!(Test-Path $TestPath -PathType $PathType)) {
Print -x -f "$PathName ($TestPath) does not exist as a $PathType"
}
$ResolvedPath = Resolve-Path $TestPath
return $ResolvedPath
}

# Like mkdir -p -> creates a directory recursively if it doesn't exist #
function MakeDirP {
[CmdletBinding()]
param (
[parameter(Mandatory=$TRUE,Position=0,HelpMessage="Path create.")]
[string]$Path
)
PROCESS {
New-Item -path $Path -itemtype Directory -force | Out-Null
}
}

# GETS ALL FILES IN A PATH RECURSIVELY #
function GetFiles {
[CmdletBinding()]
param (
[parameter(Mandatory=$TRUE,Position=0,HelpMessage="Path to get files for.")]
[string]$Path
)
PROCESS {
ls $Path -r | where { !$_.PSIsContainer }
}
}

# GETS ALL FILES WITH CALCULATED HASH PROPERTY RELATIVE TO A ROOT DIRECTORY RECURSIVELY #
# RETURNS LIST OF @{RelativePath, Hash, FullName}
function GetFilesWithHash {
[CmdletBinding()]
param (
[parameter(Mandatory=$TRUE,Position=0,HelpMessage="Path to get directories for.")]
[string]$Path,

[parameter(HelpMessage="The hash algorithm to use.")]
[string]$Algorithm="MD5"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

)
PROCESS {
$OriginalPath = $PWD
SetWorkDir path/to/diff $Path
GetFiles $Path | select @{N="RelativePath";E={$_.FullName | Resolve-Path -Relative}},
@{N="Hash";E={(Get-FileHash $_.FullName -Algorithm $Algorithm | select Hash).Hash}},
FullName
SetWorkDir path/to/original $OriginalPath
}
}

filter UpdatedOnlyFilter{
param(
[Parameter(Position=0, Mandatory=$true,ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[PSCustomObject]
$obj
)

$obj|?{$_.Status -ne '--'}
}

# COMPARE TWO DIRECTORIES RECURSIVELY #
# RETURNS LIST OF @{RelativePath, Hash, FullName}
function DiffDirectories {
[CmdletBinding()]
param (
[parameter(Mandatory=$TRUE,Position=0,HelpMessage="Directory to compare left.")]
[alias("l")]
[string]$LeftPath,

[parameter(Mandatory=$TRUE,Position=1,HelpMessage="Directory to compare right.")]
[alias("r")]
[string]$RightPath
)
PROCESS {
$LeftHash = GetFilesWithHash $LeftPath
$RightHash = GetFilesWithHash $RightPath
diff -ReferenceObject $LeftHash -DifferenceObject $RightHash -Property RelativePath,Hash |
Select-Object *, @{
Name = 'Status'
Expression = {
if ($_.SideIndicator -eq "=>") {
if (-not (Test-Path (Join-Path -Path $LeftPath -ChildPath $_.RelativePath))) {
'Added'
}
else {
'Modified'
}
}
if ($_.SideIndicator -eq "<=") {
if (-not (Test-Path (Join-Path -Path $RightPath -ChildPath $_.RelativePath))) {
'Deleted'
}
else {
'--'
}
}
}
} | UpdatedOnlyFilter | Sort-Object Status
}
}


### END FUNCTION DEFINITIONS ###

### PROGRAM LOGIC ###

if($Compare.length -ne 2) {
Print -x "Compare requires passing exactly 2 path parameters separated by comma, you passed $($Compare.length)." -f
}
Print "Comparing $($Compare[0]) to $($Compare[1])..." -a 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so I have a bit of a hard time understanding how this code works - but from your screenshot I have a few questions/comments.

  1. I think noting that a file is modified if it still exists is probably just noise - IMO we don't really care, I expect files to be different when I do a build - they will contain different version numbers etc.
  2. What I really care about are new files and deleted files - if we need to keep modified files - can we make deleted and added files pop out some how? (color text?)
  3. Is a deleted file also considered modified or does it have a separate state? Can you show a screenshot of this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Agreed, do you suggest removing modified entries? I think we can let them be.
  2. I have added colors to make them pop, green for Added, and red for Deleted entries.
  3. Yes, deleted files has a separate "Deleted" label. attaching ss below.
    Screenshot 2023-05-22 at 7 22 26 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed hash and side indicator columns as they were not useful.

Screenshot 2023-05-22 at 8 32 56 PM

$LeftPath = RequirePath path/to/left $Compare[0] container
$RightPath = RequirePath path/to/right $Compare[1] container
$Diff = DiffDirectories $LeftPath $RightPath
$LeftDiff = $Diff | where {$_.SideIndicator -eq "<="} | select RelativePath,Hash
$RightDiff = $Diff | where {$_.SideIndicator -eq "=>"} | select RelativePath,Hash
if($ExportSummary) {
$ExportSummary = ResolvePath path/to/summary/dir $ExportSummary
MakeDirP $ExportSummary
$SummaryPath = Join-Path $ExportSummary summary.txt
$LeftCsvPath = Join-Path $ExportSummary left.csv
$RightCsvPath = Join-Path $ExportSummary right.csv

$LeftMeasure = $LeftDiff | measure
$RightMeasure = $RightDiff | measure

"== DIFF SUMMARY ==" > $SummaryPath
"" >> $SummaryPath
"-- DIRECTORIES --" >> $SummaryPath
"`tLEFT -> $LeftPath" >> $SummaryPath
"`tRIGHT -> $RightPath" >> $SummaryPath
"" >> $SummaryPath
"-- DIFF COUNT --" >> $SummaryPath
"`tLEFT -> $($LeftMeasure.Count)" >> $SummaryPath
"`tRIGHT -> $($RightMeasure.Count)" >> $SummaryPath
"" >> $SummaryPath
$Diff | Format-Table >> $SummaryPath

$LeftDiff | Export-Csv $LeftCsvPath -f
$RightDiff | Export-Csv $RightCsvPath -f
}
$Diff
SafeExit
86 changes: 86 additions & 0 deletions .github/workflows/dynamoBinDiff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Build Dynamo using latest VS and DotNET and perform a Bin Diff
name: Dynamo-BinDiff
on: [push,pull_request]
jobs:
build-current:
runs-on: windows-2022
steps:
- name: Checkout Dynamo Repo current branch
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a complication for you - we also need to do this same comparison for the DynamoAll.Net6.Sln targeting windows.

Would you prefer to just duplicate this action for net6 or have this job do 4 builds?

Copy link
Contributor Author

@zeusongit zeusongit May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 2 more builds for Net6-Windows (parallel builds for quick results)

Screenshot 2023-05-22 at 8 34 31 PM

uses: actions/checkout@v3
with:
path: Dynamo
repository: DynamoDS/Dynamo
- name: Setup Nuget.exe to use on VM (current)
uses: nuget/setup-nuget@v1
- name: Nuget Restore in Dynamo solution (current)
run: nuget restore $Env:GITHUB_WORKSPACE\Dynamo\src\Dynamo.All.sln
- name: Test var
run: echo "${{ github.workspace }}"
- name: Build Dynamo current branch with MSBuild
run: |
echo "***Continue with the build, Good luck developer!***"
cd "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64"
.\MSBuild.exe $Env:GITHUB_WORKSPACE\Dynamo\src\Dynamo.All.sln
- name: Confirm Dynamo Build (current)
run: |
cd "$Env:GITHUB_WORKSPACE\Dynamo\bin\AnyCPU\Debug"
echo "***Locating DynamoSandbox after current build!***"
test ".\DynamoSandbox.exe" && echo "DynamoSandbox exists!"
- name: Cache Current Build
uses: actions/cache/save@v3
with:
path: |
${{ github.workspace }}\Dynamo\bin\AnyCPU\Debug
${{ github.workspace }}\Dynamo\.github\scripts
key: cache-current-${{ github.run_id }}-${{ github.run_attempt }}
build-master:
runs-on: windows-2022
steps:
- name: Checkout Dynamo Repo master branch
uses: actions/checkout@v3
with:
ref: master
path: master_Dynamo
repository: DynamoDS/Dynamo
- name: Setup Nuget.exe to use on VM (master)
uses: nuget/setup-nuget@v1
- name: Nuget Restore in Dynamo solution (master)
run: nuget restore $Env:GITHUB_WORKSPACE\master_Dynamo\src\Dynamo.All.sln
- name: Build Dynamo master branch with MSBuild
run: |
echo "***Continue with the build, Good luck developer!***"
cd "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64"
.\MSBuild.exe $Env:GITHUB_WORKSPACE\master_Dynamo\src\Dynamo.All.sln
- name: Confirm Dynamo Build (master)
run: |
cd "$Env:GITHUB_WORKSPACE\master_Dynamo\bin\AnyCPU\Debug"
echo "***Locating DynamoSandbox after master build!***"
test ".\DynamoSandbox.exe" && echo "DynamoSandbox exists!"
- name: Cache Master Build
uses: actions/cache/save@v3
with:
path: ${{ github.workspace }}\master_Dynamo\bin\AnyCPU\Debug
key: cache-master-${{ github.run_id }}-${{ github.run_attempt }}
run-bin-diff:
needs: [build-current, build-master]
runs-on: windows-2022
steps:
- name: Restore Current Build
uses: actions/cache/restore@v3
with:
fail-on-cache-miss: true
path: |
${{ github.workspace }}\Dynamo\bin\AnyCPU\Debug
${{ github.workspace }}\Dynamo\.github\scripts
key: cache-current-${{ github.run_id }}-${{ github.run_attempt }}
- name: Restore Master Build
uses: actions/cache/restore@v3
with:
fail-on-cache-miss: true
path: ${{ github.workspace }}\master_Dynamo\bin\AnyCPU\Debug
key: cache-master-${{ github.run_id }}-${{ github.run_attempt }}
- name: Run Binary Diff Job
run: |
echo "***Running the binary diff job between the current branch and the master branch!***"
cd "$Env:GITHUB_WORKSPACE\Dynamo\.github\scripts"
.\bin_diff.ps1 $Env:GITHUB_WORKSPACE\master_Dynamo\bin\AnyCPU\Debug,$Env:GITHUB_WORKSPACE\Dynamo\bin\AnyCPU\Debug