diff --git a/.azure-pipelines/PipelineSteps/BatchGeneration/batch-generate-modules.ps1 b/.azure-pipelines/PipelineSteps/BatchGeneration/batch-generate-modules.ps1 new file mode 100644 index 000000000000..17db89246bfc --- /dev/null +++ b/.azure-pipelines/PipelineSteps/BatchGeneration/batch-generate-modules.ps1 @@ -0,0 +1,48 @@ +param ( + [string]$MatrixKey, + [string]$Target, + [string]$RepoRoot, + [string]$ArtifactRoot +) + +Write-Host "Matrix Key: $MatrixKey" +Write-Host "Building targets: $Target" + +$buildModulesPath = Join-Path $RepoRoot 'tools' 'BuildScripts' 'BuildModules.ps1' +$modules = $Target -split ',' +$results = @() + +foreach ($module in $modules) { + $startTime = Get-Date + $result = @{ + Module = $module + Status = "Success" + DurationSeconds = 0 + Error = "" + } + try { + Write-Host "Building module: $module" + #TODO(Bernard) Remove log after test + if ($module -eq 'Communication') { + throw "Module '$module' is not allowed for this operation." + } + & $buildModulesPath -TargetModule $module -ForceRegenerate -InvokedByPipeline + } catch { + Write-Warning "Failed to build module: $module" + $result.Status = "Failed" + $result.Error = $_.Exception.Message + } finally { + $endTime = Get-Date + $result.DurationSeconds = ($endTime - $startTime).TotalSeconds + $results += $result + } +} + +git add . +$patchPath = Join-Path $ArtifactRoot "changed.patch" +git diff --cached > $patchPath + +$reportPath = Join-Path $ArtifactRoot "BuildReport-$MatrixKey.json" +$results | ConvertTo-Json -Depth 3 | Out-File -FilePath $reportPath -Encoding utf8 + +Write-Host "Build report written to $reportPath" diff --git a/.azure-pipelines/PipelineSteps/BatchGeneration/create-branch.ps1 b/.azure-pipelines/PipelineSteps/BatchGeneration/create-branch.ps1 new file mode 100644 index 000000000000..450921b95f1e --- /dev/null +++ b/.azure-pipelines/PipelineSteps/BatchGeneration/create-branch.ps1 @@ -0,0 +1,22 @@ +[CmdletBinding(DefaultParameterSetName="AllSet")] +param ( + [string]$Owner, + [string]$Repo, + [string]$BaseBranch, + [string]$NewBranch, + [string]$Token +) + +$headers = @{ Authorization = "Bearer $Token"; "User-Agent" = "ADO-Pipeline" } +$branchInfo = Invoke-RestMethod -Uri "https://api.github.com/repos/$Owner/$Repo/git/ref/heads/$BaseBranch" -Headers $headers +$sha = $branchInfo.object.sha + +$body = @{ + ref = "refs/heads/$NewBranch" + sha = $sha +} | ConvertTo-Json + +Invoke-RestMethod -Uri "https://api.github.com/repos/$Owner/$Repo/git/refs" ` + -Method Post -Headers $headers -Body $body -ContentType "application/json" + +Write-Host "Created branch '$NewBranch' from '$BBaseBranch'" diff --git a/.azure-pipelines/PipelineSteps/BatchGeneration/filter.ps1 b/.azure-pipelines/PipelineSteps/BatchGeneration/filter.ps1 new file mode 100644 index 000000000000..2346e35a60af --- /dev/null +++ b/.azure-pipelines/PipelineSteps/BatchGeneration/filter.ps1 @@ -0,0 +1,89 @@ +[CmdletBinding(DefaultParameterSetName="AllSet")] +param ( + [int]$MaxParalleAnalyzeJobs = 3, + [int]$MaxParalleTestWindowsJobs = 3, + [int]$MaxParalleTestLinuxJobs = 3, + [int]$MaxParalleTestMacJobs = 3, + [string[]]$ChangedFiles +) + +$autorestFolders = @{} +for ($i = 0; $i -lt $ChangedFiles.Count; $i++) { + if ($ChangedFiles[$i] -match '^(src|generated)/([^/]+)/([^/]+\.autorest)/') { + $parent = $Matches[2] + $child = $Matches[3] + $key = "$parent/$child" + + $autorestFolders[$key] = $true + } +} + +$changedSubModules = $autorestFolders.Keys +# TODO(Bernard) Remove test data after test +# $changedSubModules = @("A", "B", "C", "D", "E", "F", "G") +Write-Host "Chagned sub modules: " +foreach ($subModule in $changedSubModules) { + Write-Host $subModule +} + +function Split-List { + param ( + [array]$subModules, + [int]$maxParallelJobs + ) + + $count = $subModules.Count + $n = [Math]::Min($count, $maxParallelJobs) + + if ($n -eq 0) { + return @() + } + + $result = @() + + for ($i = 0; $i -lt $n; $i++) { + $result += ,@() + } + + for ($i = 0; $i -lt $count; $i++) { + $groupIndex = $i % $n + $result[$groupIndex] += $subModules[$i] + } + + return ,$result +} + +function Write-Matrix { + param ( + [string]$variableName, + [array]$groupedSubModules + ) + + $index = 0 + foreach ($subModules in $groupedSubModules) { + $moduleNamesStr = $subModules -join ',' + $key = ($index + 1).ToString() + "-" + $subModules.Count + $MatrixStr = "$MatrixStr,'$key':{'Target':'$moduleNamesStr','MatrixKey':'$key'}" + $index++ + } + + if ($MatrixStr -and $MatrixStr.Length -gt 1) { + $MatrixStr = $MatrixStr.Substring(1) + } + Write-Host "##vso[task.setVariable variable=$variableName;isOutput=true]{$MatrixStr}" + Write-Host "variable=$variableName; value=$MatrixStr" + } + +$groupedAnalyzeModules = Split-List -subModules $changedSubModules -maxParallelJobs $MaxParalleAnalyzeJobs +Write-Matrix -variableName 'AnalyzeTargets' -groupedSubModules $groupedAnalyzeModules + +$groupedTestWindowsModules = Split-List -subModules $changedSubModules -maxParallelJobs $MaxParalleTestWindowsJobs +Write-Matrix -variableName 'TestWindowsTargets' -groupedSubModules $groupedTestWindowsModules + +$groupedTestLinuxModules = Split-List -subModules $changedSubModules -maxParallelJobs $MaxParalleTestLinuxJobs +Write-Matrix -variableName 'TestLinuxTargets' -groupedSubModules $groupedTestLinuxModules + +# $groupedTestMacModules = Split-List -subModules $changedSubModules -maxParallelJobs $MaxParalleTestMacJobs +# Write-Matrix -variableName 'TestMacTargets' -groupedSubModules $groupedTestMacModules + +Write-Host "##vso[task.setVariable variable=TestMacTargets;isOutput=true]{}" \ No newline at end of file diff --git a/.azure-pipelines/PipelineSteps/BatchGeneration/prepare.ps1 b/.azure-pipelines/PipelineSteps/BatchGeneration/prepare.ps1 new file mode 100644 index 000000000000..16a781448dc1 --- /dev/null +++ b/.azure-pipelines/PipelineSteps/BatchGeneration/prepare.ps1 @@ -0,0 +1,83 @@ +[CmdletBinding(DefaultParameterSetName="AllSet")] +param ( + [string]$RepoRoot, + [int]$MaxParallelJobs = 3 +) + +$moduleRoot = Join-Path $RepoRoot 'src' +$subModules = @() + +Get-ChildItem -Path $moduleRoot -Directory | ForEach-Object { + $module = $_ + Get-ChildItem -Path $module.FullName -Directory | Where-Object { + $_.Name -like '*.autorest' + } | ForEach-Object { + $sub_module = $_ + $subModules += ,@($module.Name, $sub_module.Name) + } +} + +$subModules = @( + # V3 + @("Cdn","Cdn.Autorest"), + @("ImageBuilder", "ImageBuilder.Autorest"), + + # V4 + @("Chaos", "Chaos.Autorest"), + @("DeviceRegistry", "DeviceRegistry.Autorest"), + @("Astro", "Astro.Autorest"), + + # V4 Multi sub-modules + @("Communication","EmailService.Autorest") + # @("Communication", "EmailServicedata.Autorest") +) + +Write-Host "Total matched sub modules: $($subModules.Count)" + +function Split-List { + param ( + [array]$subModules, + [int]$maxParallelJobs + ) + + $count = $subModules.Count + $n = [Math]::Min($count, $maxParallelJobs) + if ($n -eq 0) { + return @() + } + + $result = @() + $sizePerGroup = [Math]::Ceiling($count / $n) + + for ($i = 0; $i -lt $count; $i += $sizePerGroup) { + $group = $subModules[$i..([Math]::Min($i + $sizePerGroup - 1, $count - 1))] + $result += ,$group + } + + return $result +} + +$devidedSubModules = Split-List -subModules $subModules -maxParallelJobs $MaxParallelJobs + +Write-Host "Total matched devides: $($devidedSubModules.Count)" + +$index = 0 +foreach ($subModules in $devidedSubModules) { + Write-Host "Outer Group ${index}:" + $subIndex = 0 + foreach ($subModule in $subModules) { + Write-Host "Inner Group ${subIndex}: $($subModule -join ',')" + $subIndex++ + } + + $moduleNames = $subModules | ForEach-Object { $_[0] } + $moduleNamesStr = $moduleNames -join ',' + $key = ($index + 1).ToString() + "-" + $subModules.Count + $MatrixStr = "$MatrixStr,'$key':{'Target':'$moduleNamesStr','MatrixKey':'$key'}" + $index++ +} + +if ($MatrixStr -and $MatrixStr.Length -gt 1) { + $MatrixStr = $MatrixStr.Substring(1) +} +Write-Host "##vso[task.setVariable variable=generateTargets;isOutput=true]{$MatrixStr}" diff --git a/.azure-pipelines/PipelineSteps/BatchGeneration/test-module.ps1 b/.azure-pipelines/PipelineSteps/BatchGeneration/test-module.ps1 new file mode 100644 index 000000000000..41d0c6fe7cb7 --- /dev/null +++ b/.azure-pipelines/PipelineSteps/BatchGeneration/test-module.ps1 @@ -0,0 +1,45 @@ +param ( + [string]$MatrixKey, + [string]$Target, + [string]$TestEnvName, + [string]$RepoRoot, + [string]$ArtifactRoot +) + +Write-Host "Matrix Key: $MatrixKey" +Write-Host "Test $($TestEnvName): $Target" + +$modules = $Target -split ',' +$results = @() + +foreach ($module in $modules) { + $startTime = Get-Date + $result = @{ + Module = $module + Status = "Success" + DurationSeconds = 0 + Error = "" + } + + try { + Write-Host "Testing module: $module" + $subModulePath = Join-Path $RepoRoot 'src' $module + # TODO(Bernard) Remove log after test + Write-Host "Sub module path: $subModulePath" + Set-Location -Path $subModulePath + & ".\test-module.ps1" + } + catch { + Write-Warning "Failed to test module: $module" + $result.Status = "Failed" + $result.Error = $_.Exception.Message + } + finally { + $endTime = Get-Date + $result.DurationSeconds = ($endTime - $startTime).TotalSeconds + $results += $result + } +} + +$reportPath = Join-Path $ArtifactRoot "Test$($TestEnvName)Report-$MatrixKey.json" +$results | ConvertTo-Json -Depth 3 | Out-File -FilePath $reportPath -Encoding utf8 diff --git a/.azure-pipelines/batch-generation.yml b/.azure-pipelines/batch-generation.yml new file mode 100644 index 000000000000..4537cd46f09c --- /dev/null +++ b/.azure-pipelines/batch-generation.yml @@ -0,0 +1,322 @@ +variables: + IntermediateStepTimeoutInMinutes: 30 + GenerateTimeoutInMinutes: 120 + BuildTimeoutInMinutes: 120 + AnalysisTimeoutInMinutes: 120 + TestTimeoutInMinutes: 180 + MaxParalleGenerateJobs: 3 + MaxParalleBuildJobs: 3 + MaxParalleAnalyzeJobs: 4 + MaxParalleTestWindowsJobs: 1 + MaxParalleTestLinuxJobs: 2 + MaxParalleTestMacJobs: 3 + WindowsAgentPoolName: pool-windows-2019 + LinuxAgentPoolName: pool-ubuntu-2004 + MacOSAgentPoolName: 'Azure Pipelines' + MacOSAgentPoolVMImage: macOS-latest + GenerationBranch: batch-generation/branch-$(Build.BuildId) + +trigger: none + +jobs: +- job: prepare + displayName: Generate Build Targets Matrix + timeoutInMinutes: ${{ variables.IntermediateStepTimeoutInMinutes }} + pool: ${{ variables.WindowsAgentPoolName }} + steps: + + # TODO: (Bernard) Uncomment the no checkout step after automatically install repo into agnets + # - checkout: none + + - template: util/get-github-pat-steps.yml + + - task: PowerShell@2 + displayName: 'Create Batch Generation Branch' + inputs: + targetType: inline + pwsh: true + script: | + $newBranch = "$(GenerationBranch)" + $token = "$(GitHubToken)" + + $createBranchPath = Join-Path "$(Build.SourcesDirectory)" '.azure-pipelines' 'PipelineSteps' 'BatchGeneration' 'create-branch.ps1' + # TODO: (Bernard) Change BaseBranch to main after test + & $createBranchPath -Owner 'Azure' -Repo 'azure-powershell' -BaseBranch 'bernard-pipeline-generation' -NewBranch $newBranch -Token $token + + - task: PowerShell@2 + name: mtrx + displayName: 'Generate Build Targets Matrix' + inputs: + targetType: inline + pwsh: true + script: | + $prepareModulesPath = Join-Path "$(Build.SourcesDirectory)" '.azure-pipelines' 'PipelineSteps' 'BatchGeneration' 'prepare.ps1' + & $prepareModulesPath -RepoRoot "$(Build.SourcesDirectory)" -MaxParallelJobs "${{ variables.MaxParalleBuildJobs }}" + +- job: generate + displayName: "Batch Generate: " + dependsOn: prepare + condition: and(succeeded(), ne(variables['generateTargets'], '')) + timeoutInMinutes: ${{ variables.GenerateTimeoutInMinutes }} + pool: ${{ variables.WindowsAgentPoolName }} + strategy: + matrix: $[ dependencies.prepare.outputs['mtrx.generateTargets'] ] + maxParallel: ${{ variables.MaxParalleGenerateJobs }} + + steps: + - checkout: self + persistCredentials: true + fetchTags: false + + - task: PowerShell@2 + name: generate + displayName: 'Regenerate Modules' + inputs: + targetType: inline + pwsh: true + script: | + git fetch origin "${{ variables.GenerationBranch }}" + git checkout "${{ variables.GenerationBranch }}" + + $batchGenerateModulesPath = Join-Path "$(Build.SourcesDirectory)" '.azure-pipelines' 'PipelineSteps' 'BatchGeneration' 'batch-generate-modules.ps1' + & $batchGenerateModulesPath -MatrixKey "$(MatrixKey)" -Target "$(Target)" -RepoRoot "$(Build.SourcesDirectory)" -ArtifactRoot "$(Build.ArtifactStagingDirectory)" + + workingDirectory: $(Build.SourcesDirectory) + + - task: PublishPipelineArtifact@1 + displayName: 'Save patch' + inputs: + targetPath: '$(Build.ArtifactStagingDirectory)' + artifact: 'build-$(MatrixKey)' + condition: always() + +# - job: build +# displayName: "Build:" +# dependsOn: prepare +# timeoutInMinutes: ${{ variables.BuildTimeoutInMinutes }} +# pool: ${{ variables.WindowsAgentPoolName }} +# strategy: +# matrix: $[ dependencies.prepare.outputs['mtrx.buildTargets'] ] +# maxParallel: ${{ variables.MaxParalleBuildJobs }} + +# steps: +# - checkout: self +# persistCredentials: true +# fetchTags: false + +# # - checkout: azure-powershell-devops +# # path: "azure-powershell-devops" + +# # - template: util/get-github-pat-steps.yml + +# - task: PowerShell@2 +# name: build +# displayName: 'Build Targets' +# inputs: +# targetType: inline +# pwsh: true +# script: | +# git fetch origin "${{ variables.GenerationBranch }}" +# git checkout "${{ variables.GenerationBranch }}" + +# $batchGenerateModulesPath = Join-Path "$(Build.SourcesDirectory)" '.azure-pipelines' 'PipelineSteps' 'BatchGeneration' 'batch-generate-modules.ps1' +# & $batchGenerateModulesPath -MatrixKey "$(MatrixKey)" -Target "$(Target)" -RepoRoot "$(Build.SourcesDirectory)" -ArtifactRoot "$(Build.ArtifactStagingDirectory)" + +# workingDirectory: $(Build.SourcesDirectory) + +# - task: PublishPipelineArtifact@1 +# displayName: 'Save patch' +# inputs: +# targetPath: '$(Build.ArtifactStagingDirectory)' +# artifact: 'build-$(MatrixKey)' +# condition: always() + +- job: filter + displayName: 'Filter Changed Modules' + dependsOn: generate + condition: always() + timeoutInMinutes: ${{ variables.IntermediateStepTimeoutInMinutes }} + pool: ${{ variables.WindowsAgentPoolName }} + steps: + - checkout: self + persistCredentials: true + fetchTags: false + + - task: PowerShell@2 + name: checkout + displayName: 'Checkout Generation Branch' + inputs: + targetType: inline + pwsh: true + script: | + git fetch origin "${{ variables.GenerationBranch }}" + git checkout "${{ variables.GenerationBranch }}" + + - download: current + patterns: '**/*.patch' + displayName: 'Download all .patch artifacts' + + - task: PowerShell@2 + name: apply + displayName: 'Apply all patches' + inputs: + targetType: inline + pwsh: true + script: | + git config user.email "65331932+azure-powershell-bot@users.noreply.github.com" + git config user.name "azure-powershell-bot" + + Write-Host "Applying all .patch files to ${{ variables.GenerationBranch }}..." + $patchFiles = Get-ChildItem -Path "$env:PIPELINE_WORKSPACE" -Recurse -Filter *.patch + + # $patchFiles = Get-ChildItem -Path "$env:PIPELINE_WORKSPACE" -Recurse -Filter *.patch | + # Where-Object { $_.Directory.Parent.FullName -eq $env:PIPELINE_WORKSPACE } + + foreach ($patch in $patchFiles) { + Write-Host "Applying patch: $($patch.FullName)" + git apply --whitespace=fix "$($patch.FullName)" + } + + git add . + git commit -m "Apply matrix job patches to ${{ variables.GenerationBranch }}" + git push origin "${{ variables.GenerationBranch }}" + + - task: PowerShell@2 + name: mtrx + displayName: 'Generate Test Targets Matrix' + inputs: + targetType: inline + pwsh: true + script: | + $base = git merge-base HEAD origin/main + $changedFiles = git diff --name-only $base HEAD + + $sourceBranchName = "$(Build.SourceBranch)".Replace('refs/heads/', '') + git checkout $sourceBranchName + + $filterModulesPath = Join-Path "$(Build.SourcesDirectory)" '.azure-pipelines' 'PipelineSteps' 'BatchGeneration' 'filter.ps1' + & $filterModulesPath -MaxParalleAnalyzeJobs "${{ variables.MaxParalleAnalyzeJobs }}" -MaxParalleTestWindowsJobs "${{ variables.MaxParalleTestWindowsJobs }}" -MaxParalleTestLinuxJobs "${{ variables.MaxParalleTestLinuxJobs }}" -MaxParalleTestMacJobs "${{ variables.MaxParalleTestMacJobs }}" -ChangedFiles $changedFiles + + # - checkout: none + + # - script: | + # git init + # git remote add origin https://github.com/Azure/azure-powershell.git + # git fetch origin main --depth=1 + # git checkout FETCH_HEAD -- .azure-pipelines/ + + # displayName: 'Checkout Pipeline Templates' + + # - template: util/get-github-pat-steps.yml + + # - script: | + # $token = "$(GitHubToken)" + # changedModules=$(curl -s -H "Authorization: Bearer $token" \ + # https://api.github.com/repos/Azure/azure-powershell/compare/main...${{ variables.GenerationBranch }} \ + # | jq -r '.files[].filename' \ + # | grep -E '^(src|generated)/[^/]+/[^/]+\.autorest/' \ + # | sed -E 's#^(src|generated)/##' \ + # | awk -F/ '{print $1 "/" $2}' \ + # | sort -u) + + # IFS=$'\n' read -r -d '' -a changedModulePath <<< "$changedModules" + + # for path in "${changedModulePath[@]}"; do + # echo "$path" + # done + +- job: analyze + displayName: "Analyze:" + dependsOn: filter + condition: and(succeeded(), ne(variables['AnalyzeTargets'], '')) + timeoutInMinutes: ${{ variables.AnalysisTimeoutInMinutes }} + pool: ${{ variables.WindowsAgentPoolName }} + strategy: + matrix: $[ dependencies.filter.outputs['mtrx.AnalyzeTargets'] ] + maxParallel: ${{ variables.MaxParalleAnalyzeJobs }} + + steps: + - checkout: none + + - task: PowerShell@2 + name: analyze + displayName: 'Analyze modules' + inputs: + targetType: inline + pwsh: true + script: | + Write-Host "Matrix Key: $(MatrixKey)" + Write-Host "Analyze Targets: $(Target)" + +- job: test_windows + displayName: "Test Windows:" + dependsOn: filter + condition: and(succeeded(), ne(variables['TestWindowsTargets'], '')) + timeoutInMinutes: ${{ variables.TestTimeoutInMinutes }} + pool: ${{ variables.WindowsAgentPoolName }} + strategy: + matrix: $[ dependencies.filter.outputs['mtrx.TestWindowsTargets'] ] + maxParallel: ${{ variables.MaxParalleTestWindowsJobs }} + + steps: + - checkout: none + + - task: PowerShell@2 + name: test + displayName: 'Test Windows' + inputs: + targetType: inline + pwsh: true + script: | + $testModulesPath = Join-Path "$(Build.SourcesDirectory)" '.azure-pipelines' 'PipelineSteps' 'BatchGeneration' 'test-module.ps1' + & $testModulesPath -MatrixKey "$(MatrixKey)" -Target "$(Target)" -TestEnvName 'Windows' -RepoRoot "$(Build.SourcesDirectory)" -ArtifactRoot "$(Build.ArtifactStagingDirectory)" + + +- job: test_linux + displayName: "Test Linux:" + dependsOn: filter + condition: and(succeeded(), ne(variables['TestLinuxTargets'], '')) + timeoutInMinutes: ${{ variables.TestTimeoutInMinutes }} + pool: ${{ variables.LinuxAgentPoolName }} + strategy: + matrix: $[ dependencies.filter.outputs['mtrx.TestLinuxTargets'] ] + maxParallel: ${{ variables.MaxParalleTestLinuxJobs }} + + steps: + - checkout: none + + - task: PowerShell@2 + name: test + displayName: 'Test Linux' + inputs: + targetType: inline + pwsh: true + script: | + $testModulesPath = Join-Path "$(Build.SourcesDirectory)" '.azure-pipelines' 'PipelineSteps' 'BatchGeneration' 'test-module.ps1' + & $testModulesPath -MatrixKey "$(MatrixKey)" -Target "$(Target)" -TestEnvName 'Linux' -RepoRoot "$(Build.SourcesDirectory)" -ArtifactRoot "$(Build.ArtifactStagingDirectory)" + +- job: test_mac + displayName: "Test Mac:" + dependsOn: filter + condition: and(succeeded(), ne(variables['TestMacTargets'], '')) + timeoutInMinutes: ${{ variables.TestTimeoutInMinutes }} + pool: + name: ${{ variables.MacOSAgentPoolName }} + vmImage: ${{ variables.MacOSAgentPoolVMImage }} + strategy: + matrix: $[ dependencies.filter.outputs['mtrx.TestMacTargets'] ] + maxParallel: ${{ variables.MaxParalleTestMacJobs }} + + steps: + - checkout: none + + - task: PowerShell@2 + name: test + displayName: 'Test Mac' + inputs: + targetType: inline + pwsh: true + script: | + $testModulesPath = Join-Path "$(Build.SourcesDirectory)" '.azure-pipelines' 'PipelineSteps' 'BatchGeneration' 'test-module.ps1' + & $testModulesPath -MatrixKey "$(MatrixKey)" -Target "$(Target)" -TestEnvName 'Mac' -RepoRoot "$(Build.SourcesDirectory)" -ArtifactRoot "$(Build.ArtifactStagingDirectory)" + diff --git a/.azure-pipelines/test.ps1 b/.azure-pipelines/test.ps1 new file mode 100644 index 000000000000..450da14c3360 --- /dev/null +++ b/.azure-pipelines/test.ps1 @@ -0,0 +1,9 @@ + +$RepoRoot = Get-Location +$buildProjPath = Join-Path $RepoRoot 'build.proj' + +$filesChangedOutputPath = Join-Path $RepoRoot 'artifacts' 'FilesChanged.txt' +$subTasksFilePath = Join-Path $RepoRoot 'artifacts' 'SubTasksFile.txt' +$IsSecurityCheck = $null + +dotnet msbuild $buildProjPath /t:FilterBuild "/p:FilesChangedOutputPath=$FilesChangedOutputPath;SubTasksFilePath=$SubTasksFilePath;IsSecurityCheck=$IsSecurityCheck"