diff --git a/clients/windows/README.md b/clients/windows/README.md index 24b898d..cf77987 100644 --- a/clients/windows/README.md +++ b/clients/windows/README.md @@ -10,8 +10,10 @@ dotnet build clients/windows/VoiceCat.slnx -c Release --no-restore ./clients/windows/publish-client.ps1 ``` -Publishing produces `artifacts/client/win-x64`. The noninteractive form and WASAPI device gate -is: +Publishing produces `artifacts/client/win-x64`. Runtime-specific restore graphs are generated +under each project's ignored `obj` directory; they are intentionally not committed because they +include SDK-injected packages that change with servicing updates. The noninteractive form and +WASAPI device gate is: ```powershell ./artifacts/client/win-x64/VoiceCat.App.exe --smoke-test --audio diff --git a/clients/windows/VoiceCat.App/packages.publish.win-x64.lock.json b/clients/windows/VoiceCat.App/packages.publish.win-x64.lock.json deleted file mode 100644 index c167e07..0000000 --- a/clients/windows/VoiceCat.App/packages.publish.win-x64.lock.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net10.0-windows7.0": { - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[10.0.7, )", - "resolved": "10.0.7", - "contentHash": "AA/yhzFHNtQZXLdqjzujPy25G8EWwGWsAnxOE2zYSBoT/8QHP6ketN3CToD3DFreO653ipUwnKHo22B8AlBMCw==" - }, - "Prismatoid": { - "type": "Direct", - "requested": "[0.3.0, )", - "resolved": "0.3.0", - "contentHash": "mUOgtmFtjbLxydrdAImkfP3u0U8qrYkvfx2NlQqdQQ8TB9qe59BobxBCcNDo21g8xSefkBJB1VdGPbVTfiE7zw==" - }, - "BouncyCastle.Cryptography": { - "type": "Transitive", - "resolved": "2.6.2", - "contentHash": "7oWOcvnntmMKNzDLsdxAYqApt+AjpRpP2CShjMfIa3umZ42UQMvH0tl1qAliYPNYO6vTdcGMqnRrCPmsfzTI1w==" - }, - "Google.Protobuf": { - "type": "Transitive", - "resolved": "3.36.1", - "contentHash": "77AqPEoaY1ODE+syYBHti0jXiwQq0J/fUr/fRyYhNlc9oKtH5dZZEr/OLKtdKNVG83PRnCYB2r8B80ZrObzOGQ==" - }, - "voicecat.audio": { - "type": "Project", - "dependencies": { - "VoiceCat.Codec": "[1.0.0, )", - "VoiceCat.Dsp": "[1.0.0, )", - "VoiceCat.Protocol": "[1.0.0, )" - } - }, - "voicecat.codec": { - "type": "Project" - }, - "voicecat.core": { - "type": "Project", - "dependencies": { - "VoiceCat.Audio": "[1.0.0, )", - "VoiceCat.Crypto": "[1.0.0, )" - } - }, - "voicecat.crypto": { - "type": "Project", - "dependencies": { - "BouncyCastle.Cryptography": "[2.6.2, )", - "VoiceCat.Protocol": "[1.0.0, )" - } - }, - "voicecat.dsp": { - "type": "Project" - }, - "voicecat.windows": { - "type": "Project", - "dependencies": { - "VoiceCat.Core": "[1.0.0, )" - } - }, - "voicecat.protocol": { - "type": "Project", - "dependencies": { - "Google.Protobuf": "[3.36.1, )" - } - } - }, - "net10.0-windows7.0/win-x64": { - "Prismatoid": { - "type": "Direct", - "requested": "[0.3.0, )", - "resolved": "0.3.0", - "contentHash": "mUOgtmFtjbLxydrdAImkfP3u0U8qrYkvfx2NlQqdQQ8TB9qe59BobxBCcNDo21g8xSefkBJB1VdGPbVTfiE7zw==" - } - } - } -} diff --git a/clients/windows/VoiceCat.Windows/packages.publish.win-x64.lock.json b/clients/windows/VoiceCat.Windows/packages.publish.win-x64.lock.json deleted file mode 100644 index 4e143e2..0000000 --- a/clients/windows/VoiceCat.Windows/packages.publish.win-x64.lock.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net10.0": { - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[10.0.7, )", - "resolved": "10.0.7", - "contentHash": "AA/yhzFHNtQZXLdqjzujPy25G8EWwGWsAnxOE2zYSBoT/8QHP6ketN3CToD3DFreO653ipUwnKHo22B8AlBMCw==" - }, - "BouncyCastle.Cryptography": { - "type": "Transitive", - "resolved": "2.6.2", - "contentHash": "7oWOcvnntmMKNzDLsdxAYqApt+AjpRpP2CShjMfIa3umZ42UQMvH0tl1qAliYPNYO6vTdcGMqnRrCPmsfzTI1w==" - }, - "Google.Protobuf": { - "type": "Transitive", - "resolved": "3.36.1", - "contentHash": "77AqPEoaY1ODE+syYBHti0jXiwQq0J/fUr/fRyYhNlc9oKtH5dZZEr/OLKtdKNVG83PRnCYB2r8B80ZrObzOGQ==" - }, - "voicecat.audio": { - "type": "Project", - "dependencies": { - "VoiceCat.Codec": "[1.0.0, )", - "VoiceCat.Dsp": "[1.0.0, )", - "VoiceCat.Protocol": "[1.0.0, )" - } - }, - "voicecat.codec": { - "type": "Project" - }, - "voicecat.core": { - "type": "Project", - "dependencies": { - "VoiceCat.Audio": "[1.0.0, )", - "VoiceCat.Crypto": "[1.0.0, )" - } - }, - "voicecat.crypto": { - "type": "Project", - "dependencies": { - "BouncyCastle.Cryptography": "[2.6.2, )", - "VoiceCat.Protocol": "[1.0.0, )" - } - }, - "voicecat.dsp": { - "type": "Project" - }, - "voicecat.protocol": { - "type": "Project", - "dependencies": { - "Google.Protobuf": "[3.36.1, )" - } - } - }, - "net10.0/win-x64": {} - } -} \ No newline at end of file diff --git a/clients/windows/publish-client.ps1 b/clients/windows/publish-client.ps1 index 387cf0a..709a45c 100644 --- a/clients/windows/publish-client.ps1 +++ b/clients/windows/publish-client.ps1 @@ -7,8 +7,8 @@ $repoRoot = (Resolve-Path "$PSScriptRoot/../..").Path if ([string]::IsNullOrWhiteSpace($Output)) { $Output = "$repoRoot/artifacts/client/$RuntimeIdentifier" } dotnet publish "$PSScriptRoot/VoiceCat.App/VoiceCat.App.csproj" -c Release -r $RuntimeIdentifier --self-contained true ` -p:PublishSingleFile=true -p:PublishTrimmed=false -p:IncludeNativeLibrariesForSelfExtract=false ` - -p:RestorePackagesWithLockFile=true -p:RestoreLockedMode=true ` - "-p:NuGetLockFilePath=packages.publish.$RuntimeIdentifier.lock.json" -o $Output + -p:RestorePackagesWithLockFile=true -p:RestoreLockedMode=false ` + "-p:NuGetLockFilePath=obj/packages.publish.$RuntimeIdentifier.lock.json" -o $Output if ($LASTEXITCODE -ne 0) { throw "Managed Windows client publish failed." } if (-not (Test-Path "$Output/voicecat_media.dll")) { throw "Managed media shim was not published." } Write-Host "Published managed Windows client to $Output" diff --git a/scripts/check-licenses.ps1 b/scripts/check-licenses.ps1 index a08d27e..f42b421 100644 --- a/scripts/check-licenses.ps1 +++ b/scripts/check-licenses.ps1 @@ -1,7 +1,9 @@ $ErrorActionPreference = 'Stop' $allowed = @('MIT', 'BSD-2-Clause', 'BSD-3-Clause', 'Apache-2.0', 'ISC', '0BSD', 'MPL-2.0') $seen = @{} -foreach ($lockPath in (Get-ChildItem -LiteralPath "$PSScriptRoot/.." -Filter 'packages*.lock.json' -Recurse)) { +$sourceLocks = Get-ChildItem -LiteralPath "$PSScriptRoot/.." -Filter 'packages*.lock.json' -Recurse | + Where-Object { $_.FullName -notmatch '[\\/](?:bin|obj)[\\/]' } +foreach ($lockPath in $sourceLocks) { $lock = Get-Content -Raw -LiteralPath $lockPath.FullName | ConvertFrom-Json $assets = Get-Content -Raw -LiteralPath (Join-Path $lockPath.DirectoryName 'obj/project.assets.json') | ConvertFrom-Json foreach ($framework in $lock.dependencies.PSObject.Properties) { diff --git a/scripts/publish-server.ps1 b/scripts/publish-server.ps1 index 911f65e..d790224 100644 --- a/scripts/publish-server.ps1 +++ b/scripts/publish-server.ps1 @@ -12,6 +12,6 @@ foreach ($targetRuntime in $Runtime) { $targetOutput = if ($Output) { $Output } else { "$PSScriptRoot/../artifacts/server/$targetRuntime" } if (-not $PSCmdlet.ShouldProcess($targetOutput, "Publish VoiceCat.Server for $targetRuntime")) { continue } - dotnet publish "$PSScriptRoot/../src/VoiceCat.Server/VoiceCat.Server.csproj" -c Release -r $targetRuntime --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:PublishTrimmed=false -p:RestoreLockedMode=true "-p:NuGetLockFilePath=packages.publish.$targetRuntime.lock.json" -o $targetOutput + dotnet publish "$PSScriptRoot/../src/VoiceCat.Server/VoiceCat.Server.csproj" -c Release -r $targetRuntime --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:PublishTrimmed=false -p:RestorePackagesWithLockFile=true -p:RestoreLockedMode=false "-p:NuGetLockFilePath=obj/packages.publish.$targetRuntime.lock.json" -o $targetOutput if ($LASTEXITCODE -ne 0) { throw "Managed server publish failed for $targetRuntime." } } diff --git a/src/VoiceCat.Audio/packages.publish.win-x64.lock.json b/src/VoiceCat.Audio/packages.publish.win-x64.lock.json deleted file mode 100644 index f5c4ed7..0000000 --- a/src/VoiceCat.Audio/packages.publish.win-x64.lock.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net10.0": { - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[10.0.7, )", - "resolved": "10.0.7", - "contentHash": "AA/yhzFHNtQZXLdqjzujPy25G8EWwGWsAnxOE2zYSBoT/8QHP6ketN3CToD3DFreO653ipUwnKHo22B8AlBMCw==" - }, - "Google.Protobuf": { - "type": "Transitive", - "resolved": "3.36.1", - "contentHash": "77AqPEoaY1ODE+syYBHti0jXiwQq0J/fUr/fRyYhNlc9oKtH5dZZEr/OLKtdKNVG83PRnCYB2r8B80ZrObzOGQ==" - }, - "voicecat.codec": { - "type": "Project" - }, - "voicecat.dsp": { - "type": "Project" - }, - "voicecat.protocol": { - "type": "Project", - "dependencies": { - "Google.Protobuf": "[3.36.1, )" - } - } - }, - "net10.0/win-x64": {} - } -} \ No newline at end of file diff --git a/src/VoiceCat.Codec/packages.publish.win-x64.lock.json b/src/VoiceCat.Codec/packages.publish.win-x64.lock.json deleted file mode 100644 index c6129b8..0000000 --- a/src/VoiceCat.Codec/packages.publish.win-x64.lock.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net10.0": { - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[10.0.7, )", - "resolved": "10.0.7", - "contentHash": "AA/yhzFHNtQZXLdqjzujPy25G8EWwGWsAnxOE2zYSBoT/8QHP6ketN3CToD3DFreO653ipUwnKHo22B8AlBMCw==" - } - }, - "net10.0/win-x64": {} - } -} \ No newline at end of file diff --git a/src/VoiceCat.Core/packages.publish.win-x64.lock.json b/src/VoiceCat.Core/packages.publish.win-x64.lock.json deleted file mode 100644 index 515a3ca..0000000 --- a/src/VoiceCat.Core/packages.publish.win-x64.lock.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net10.0": { - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[10.0.7, )", - "resolved": "10.0.7", - "contentHash": "AA/yhzFHNtQZXLdqjzujPy25G8EWwGWsAnxOE2zYSBoT/8QHP6ketN3CToD3DFreO653ipUwnKHo22B8AlBMCw==" - }, - "BouncyCastle.Cryptography": { - "type": "Transitive", - "resolved": "2.6.2", - "contentHash": "7oWOcvnntmMKNzDLsdxAYqApt+AjpRpP2CShjMfIa3umZ42UQMvH0tl1qAliYPNYO6vTdcGMqnRrCPmsfzTI1w==" - }, - "Google.Protobuf": { - "type": "Transitive", - "resolved": "3.36.1", - "contentHash": "77AqPEoaY1ODE+syYBHti0jXiwQq0J/fUr/fRyYhNlc9oKtH5dZZEr/OLKtdKNVG83PRnCYB2r8B80ZrObzOGQ==" - }, - "voicecat.audio": { - "type": "Project", - "dependencies": { - "VoiceCat.Codec": "[1.0.0, )", - "VoiceCat.Dsp": "[1.0.0, )", - "VoiceCat.Protocol": "[1.0.0, )" - } - }, - "voicecat.codec": { - "type": "Project" - }, - "voicecat.crypto": { - "type": "Project", - "dependencies": { - "BouncyCastle.Cryptography": "[2.6.2, )", - "VoiceCat.Protocol": "[1.0.0, )" - } - }, - "voicecat.dsp": { - "type": "Project" - }, - "voicecat.protocol": { - "type": "Project", - "dependencies": { - "Google.Protobuf": "[3.36.1, )" - } - } - }, - "net10.0/win-x64": {} - } -} \ No newline at end of file diff --git a/src/VoiceCat.Crypto/packages.publish.win-x64.lock.json b/src/VoiceCat.Crypto/packages.publish.win-x64.lock.json deleted file mode 100644 index 1935814..0000000 --- a/src/VoiceCat.Crypto/packages.publish.win-x64.lock.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net10.0": { - "BouncyCastle.Cryptography": { - "type": "Direct", - "requested": "[2.6.2, )", - "resolved": "2.6.2", - "contentHash": "7oWOcvnntmMKNzDLsdxAYqApt+AjpRpP2CShjMfIa3umZ42UQMvH0tl1qAliYPNYO6vTdcGMqnRrCPmsfzTI1w==" - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[10.0.12, )", - "resolved": "10.0.12", - "contentHash": "xi+BDjFpW+Sb+MHFHaH6Y/gV9I8BluFwRXc1QyCdoZbIK26eNiBeFuMTe/FMwc33G1wdHCyDg7CVTmb8OdQrMQ==" - }, - "Google.Protobuf": { - "type": "Transitive", - "resolved": "3.36.1", - "contentHash": "77AqPEoaY1ODE+syYBHti0jXiwQq0J/fUr/fRyYhNlc9oKtH5dZZEr/OLKtdKNVG83PRnCYB2r8B80ZrObzOGQ==" - }, - "voicecat.protocol": { - "type": "Project", - "dependencies": { - "Google.Protobuf": "[3.36.1, )" - } - } - }, - "net10.0/win-x64": {} - } -} \ No newline at end of file diff --git a/src/VoiceCat.Dsp/packages.publish.win-x64.lock.json b/src/VoiceCat.Dsp/packages.publish.win-x64.lock.json deleted file mode 100644 index c6129b8..0000000 --- a/src/VoiceCat.Dsp/packages.publish.win-x64.lock.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net10.0": { - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[10.0.7, )", - "resolved": "10.0.7", - "contentHash": "AA/yhzFHNtQZXLdqjzujPy25G8EWwGWsAnxOE2zYSBoT/8QHP6ketN3CToD3DFreO653ipUwnKHo22B8AlBMCw==" - } - }, - "net10.0/win-x64": {} - } -} \ No newline at end of file diff --git a/src/VoiceCat.Protocol/packages.publish.win-x64.lock.json b/src/VoiceCat.Protocol/packages.publish.win-x64.lock.json deleted file mode 100644 index d81b227..0000000 --- a/src/VoiceCat.Protocol/packages.publish.win-x64.lock.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net10.0": { - "Google.Protobuf": { - "type": "Direct", - "requested": "[3.36.1, )", - "resolved": "3.36.1", - "contentHash": "77AqPEoaY1ODE+syYBHti0jXiwQq0J/fUr/fRyYhNlc9oKtH5dZZEr/OLKtdKNVG83PRnCYB2r8B80ZrObzOGQ==" - }, - "Grpc.Tools": { - "type": "Direct", - "requested": "[2.83.0, )", - "resolved": "2.83.0", - "contentHash": "vK2Go/83W0v2Nn7tTP9fGrX4IjmOa93s3M0SZeFimU1vIIr2wL9yNJlIyK21y85SGm3++JncB8IF751cjoLHuQ==" - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[10.0.12, )", - "resolved": "10.0.12", - "contentHash": "xi+BDjFpW+Sb+MHFHaH6Y/gV9I8BluFwRXc1QyCdoZbIK26eNiBeFuMTe/FMwc33G1wdHCyDg7CVTmb8OdQrMQ==" - } - }, - "net10.0/win-x64": {} - } -} \ No newline at end of file diff --git a/src/VoiceCat.Server/packages.publish.win-x64.lock.json b/src/VoiceCat.Server/packages.publish.win-x64.lock.json deleted file mode 100644 index a422df9..0000000 --- a/src/VoiceCat.Server/packages.publish.win-x64.lock.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "version": 1, - "dependencies": { - "net10.0": { - "Microsoft.Data.Sqlite.Core": { - "type": "Direct", - "requested": "[10.0.5, )", - "resolved": "10.0.5", - "contentHash": "jFYXnh7s0RShCw6Vkf+ReGCw+mVi7ISg1YaEzYCJcXnUifmbW+aqvCsRJuSRj2ZuQ+oqetpjxlZtbpMmk5FKqQ==", - "dependencies": { - "SQLitePCLRaw.core": "2.1.11" - } - }, - "Microsoft.NET.ILLink.Tasks": { - "type": "Direct", - "requested": "[10.0.12, )", - "resolved": "10.0.12", - "contentHash": "xi+BDjFpW+Sb+MHFHaH6Y/gV9I8BluFwRXc1QyCdoZbIK26eNiBeFuMTe/FMwc33G1wdHCyDg7CVTmb8OdQrMQ==" - }, - "SourceGear.sqlite3": { - "type": "Direct", - "requested": "[3.50.4.2, )", - "resolved": "3.50.4.2", - "contentHash": "eV9HwQ88WyoU+reGVxJz1SwME9NbYnl9h2LOY15j0LGdXN4JkTJDk8JRRg/yNgt00O3Cn5/qnska10FEZNoU5g==" - }, - "SQLitePCLRaw.bundle_e_sqlite3": { - "type": "Direct", - "requested": "[3.0.2, )", - "resolved": "3.0.2", - "contentHash": "nzPPFpELY9U1scLvQpA1k1GIgR9ror83DCPmirT2/i5NCPdTBfhTDA6MZqFZonGDayye5mUQRQLOVyEiJNYr0g==", - "dependencies": { - "SQLitePCLRaw.config.e_sqlite3": "3.0.2", - "SourceGear.sqlite3": "3.50.4.2" - } - }, - "BouncyCastle.Cryptography": { - "type": "Transitive", - "resolved": "2.6.2", - "contentHash": "7oWOcvnntmMKNzDLsdxAYqApt+AjpRpP2CShjMfIa3umZ42UQMvH0tl1qAliYPNYO6vTdcGMqnRrCPmsfzTI1w==" - }, - "Google.Protobuf": { - "type": "Transitive", - "resolved": "3.36.1", - "contentHash": "77AqPEoaY1ODE+syYBHti0jXiwQq0J/fUr/fRyYhNlc9oKtH5dZZEr/OLKtdKNVG83PRnCYB2r8B80ZrObzOGQ==" - }, - "SQLitePCLRaw.config.e_sqlite3": { - "type": "Transitive", - "resolved": "3.0.2", - "contentHash": "QPHR1Axs8YCCapb0TnmT7PxY9DX3sg4I4T9HOSKeFBiT5l482mjrOIxuyt+xOCwEQ2Enq5h0tgDOXMnJi+i0sw==", - "dependencies": { - "SQLitePCLRaw.provider.e_sqlite3": "3.0.2" - } - }, - "SQLitePCLRaw.core": { - "type": "Transitive", - "resolved": "3.0.2", - "contentHash": "tnbRf0muOOSJK1RLCfyYK13jynFScgL4xMj7yC3oy8lrrGKXTKmOoWjfdV+cFfBRdppm4qST31hvp8ihgIgvMQ==" - }, - "SQLitePCLRaw.provider.e_sqlite3": { - "type": "Transitive", - "resolved": "3.0.2", - "contentHash": "RQIliDp47mQxGYNcBB6W+ezHbegkImrSZVTuWjQCSTTl3pQ37Q3rALkkkdTAMEmcIz71PEOCqNZMp7lXCnVqEQ==", - "dependencies": { - "SQLitePCLRaw.core": "3.0.2" - } - }, - "voicecat.crypto": { - "type": "Project", - "dependencies": { - "BouncyCastle.Cryptography": "[2.6.2, )", - "VoiceCat.Protocol": "[1.0.0, )" - } - }, - "voicecat.protocol": { - "type": "Project", - "dependencies": { - "Google.Protobuf": "[3.36.1, )" - } - } - }, - "net10.0/win-x64": { - "SourceGear.sqlite3": { - "type": "Direct", - "requested": "[3.50.4.2, )", - "resolved": "3.50.4.2", - "contentHash": "eV9HwQ88WyoU+reGVxJz1SwME9NbYnl9h2LOY15j0LGdXN4JkTJDk8JRRg/yNgt00O3Cn5/qnska10FEZNoU5g==" - } - } - } -} \ No newline at end of file diff --git a/tests/VoiceCat.Tests/PublishServerScriptTests.cs b/tests/VoiceCat.Tests/PublishServerScriptTests.cs index 126bb4d..7721820 100644 --- a/tests/VoiceCat.Tests/PublishServerScriptTests.cs +++ b/tests/VoiceCat.Tests/PublishServerScriptTests.cs @@ -4,6 +4,26 @@ namespace VoiceCat.Tests; public class PublishServerScriptTests { + [Theory] + [InlineData("clients/windows/publish-client.ps1")] + [InlineData("scripts/publish-server.ps1")] + public async Task PublishUsesRegeneratedIntermediateRuntimeLock(string relativePath) + { + string script = await File.ReadAllTextAsync(Path.Combine(FindRoot(), relativePath.Replace('/', Path.DirectorySeparatorChar))); + + Assert.Contains("NuGetLockFilePath=obj/packages.publish.", script); + Assert.Contains("RestoreLockedMode=false", script); + Assert.DoesNotContain("NuGetLockFilePath=packages.publish.", script); + } + + [Fact] + public async Task LicenseAuditIgnoresGeneratedBuildLocks() + { + string script = await File.ReadAllTextAsync(Path.Combine(FindRoot(), "scripts", "check-licenses.ps1")); + + Assert.Contains("(?:bin|obj)", script); + } + [Fact] public async Task DefaultPublishTargetsWindowsAndLinuxWhileRuntimeCanSelectOne() {