From d2be8bc72b0583cf235e9b802505c072e9ec89a5 Mon Sep 17 00:00:00 2001 From: Adam Boniecki <20281641+abonie@users.noreply.github.com> Date: Mon, 12 Oct 2026 10:22:15 +0200 Subject: [PATCH 1/5] Provision Git for DartLab PR checkout and Apex tests Provision the Git distribution bundled with DartLab and expose it to both snapshot checkout and independent Apex build/test processes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 34f3e808-c404-4337-8e8c-76fcea75b3ed --- eng/pipelines/apex-integration/README.md | 13 +++ eng/pipelines/apex-integration/run-apex.ps1 | 6 ++ eng/pipelines/apex-integration/stage.yml | 5 + eng/tests/ApexGit.Tests.ps1 | 108 ++++++++++++++++++++ 4 files changed, 132 insertions(+) create mode 100644 eng/tests/ApexGit.Tests.ps1 diff --git a/eng/pipelines/apex-integration/README.md b/eng/pipelines/apex-integration/README.md index 7c5a141dd1d..9eb84d0a539 100644 --- a/eng/pipelines/apex-integration/README.md +++ b/eng/pipelines/apex-integration/README.md @@ -5,6 +5,15 @@ CloudTest machine, builds and deploys the PR's F# VSIX, then runs the Apex tests It avoids the dependency skew of older preinstalled CI images. The chosen VS drop must still support the PR's package pins; a recent drop is not a compatibility guarantee. +Before checking out source, the bootstrap uses `DartLab.Modules.Git`'s `Install-Git` +to copy the Git distribution bundled with the selected DartLab Production package +to `C:\Test\Git`. No separate installer or latest-version download is used. +Bootstrap and `run-apex.ps1` each prepend `C:\Test\Git\cmd` to their process PATH; +the Apex build and test children inherit it. CloudTest operations run in independent +processes, so setup does not rely on a previous operation's PATH changes. +Provisioning failures, an unusable Git executable, or a missing installation stop +the run rather than falling back to an unverified machine installation. + ## Requesting a run Post **`/dart `** or **`/pr-val `** as the entire comment on an open @@ -96,10 +105,14 @@ Local regression commands (no product build or DartLab access required): ```powershell pwsh -NoProfile -File .github\scripts\pr-validation.Tests.ps1 powershell -NoProfile -ExecutionPolicy Bypass -File eng\tests\SetupPrValidation.Tests.ps1 +powershell -NoProfile -ExecutionPolicy Bypass -File eng\tests\ApexGit.Tests.ps1 ``` The script tests use temporary local Git repositories and a mocked GitHub PR response. They cover merge identity, ref races, closed/changed PRs and failure before checkout. +The Git provisioning tests run offline with the installer boundary mocked. They +cover missing initial PATH, independent Apex process setup, build/test child PATH +inheritance, and provisioning failures without changing machine-wide PATH. The PowerShell 7 tests run the Actions helper offline with a fake HTTP boundary. They cover command syntax, authorization of the original commenter (also on reruns), private membership lookup with the separate App token, the queued snapshot and PR feedback. diff --git a/eng/pipelines/apex-integration/run-apex.ps1 b/eng/pipelines/apex-integration/run-apex.ps1 index 65515b73669..2ba6b9c5f8b 100644 --- a/eng/pipelines/apex-integration/run-apex.ps1 +++ b/eng/pipelines/apex-integration/run-apex.ps1 @@ -7,6 +7,12 @@ param( Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' +$gitDirectory = 'C:\Test\Git\cmd' +if (-not (Test-Path -LiteralPath (Join-Path $gitDirectory 'git.exe') -PathType Leaf)) { + throw 'DartLab Git was not provisioned before running Apex.' +} +$env:PATH = "$gitDirectory;$env:PATH" + $repositoryRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..\..') Set-Location $repositoryRoot diff --git a/eng/pipelines/apex-integration/stage.yml b/eng/pipelines/apex-integration/stage.yml index 1b8e701bd55..3e526d59b8d 100644 --- a/eng/pipelines/apex-integration/stage.yml +++ b/eng/pipelines/apex-integration/stage.yml @@ -127,6 +127,11 @@ stages: displayName: Verify and check out PR snapshot scriptBlock: | $ErrorActionPreference = 'Stop' + Import-Module DartLab.Modules.Git -ErrorAction Stop + Install-Git -InstallationDirectory 'C:\Test\Git' -Scope Process + $env:PATH = "C:\Test\Git\cmd;$env:PATH" + & 'C:\Test\Git\cmd\git.exe' --version + if ($LASTEXITCODE -ne 0) { throw 'The provisioned DartLab Git is not usable.' } $sourceRoot = 'C:\Test\FSharp' if (Test-Path -LiteralPath $sourceRoot) { throw "$sourceRoot already exists; refusing to reuse an unverified checkout." diff --git a/eng/tests/ApexGit.Tests.ps1 b/eng/tests/ApexGit.Tests.ps1 new file mode 100644 index 00000000000..ecc1e36920f --- /dev/null +++ b/eng/tests/ApexGit.Tests.ps1 @@ -0,0 +1,108 @@ +$ErrorActionPreference = 'Stop' +$apex = Join-Path $PSScriptRoot '..\pipelines\apex-integration' +$root = Join-Path $PSScriptRoot ("apex-git-fixture-" + [Guid]::NewGuid()) +$installation = Join-Path $root 'Git' +$git = (Get-Command git.exe -CommandType Application | Select-Object -First 1).Source +$gitRoot = Split-Path (Split-Path $git -Parent) -Parent +$previousPath = $env:PATH +$systemPath = "$env:SystemRoot\System32" +$powershell = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" +$yaml = Get-Content (Join-Path $apex 'stage.yml') -Raw +$bootstrap = [regex]::Match($yaml, '(?ms)displayName: Verify and check out PR snapshot\r?\n scriptBlock: \|\r?\n(?