Skip to content

M274 (v3)#1974

Merged
mjcheetham merged 15 commits into
releases/shippedfrom
milestones/m274.3
May 14, 2026
Merged

M274 (v3)#1974
mjcheetham merged 15 commits into
releases/shippedfrom
milestones/m274.3

Conversation

@mjcheetham
Copy link
Copy Markdown
Member

Changes:

mjcheetham and others added 15 commits May 13, 2026 11:37
Our release agent pools use 10.0.300. Our GitHub Agents use 10.0.203.
Let's just be less picky about the exact verison of "10.x".

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
global.json: enable roll forward in .NET SDK (port to master)
Remove all MicroBuild.Core PackageReference declarations and the
associated <FilesToSign> ItemGroups from GVFS.Payload, GVFS.Installers,
and FastFetch, and remove MicroBuild.Core from Directory.Packages.props.

Also drop the BeforeTargets="SignFiles" hooks from the CreatePayload
and CreateInstaller targets — without MicroBuild.Core's targets the
SignFiles target no longer exists, and the hooks are unnecessary now
that signing is performed externally by the release pipeline.

This commit is a pure removal of the in-build signing wiring; signing
itself moves to ESRP-driven steps in the release pipeline in a follow-up
commit. The GitHub Actions CI / PR build never signed anything and is
unaffected.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Add a Condition="'$(SkipCreateInstaller)' != 'true'" to the
CreateInstaller MSBuild target so callers can opt out of the Inno
Setup compile step.

This lets the release pipeline build all of the managed binaries
first (via Build.bat with the env var set), ESRP-sign them in place,
and only then invoke the Inno Setup compile to produce
SetupGVFS.<version>.exe — packaging the already-signed binaries in a
single, deterministic pass instead of building, deleting, and
rebuilding the installer.

Default behavior is unchanged: with the property unset (the case for
local builds and the GitHub Actions PR/CI workflow), CreateInstaller
fires as before during the regular Build target.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
The validate job's 'Look for prior successful runs' step finds a prior
successful run that is commit- or tree-same and records its URL via
core.notice and as the validate.outputs.skip output, which downstream
jobs surface to users.

When the prior run was itself a skip-run (i.e. its only successful work
was recording a notice pointing at a yet earlier run), we end up with a
chain of skip-runs each pointing at the previous skip-run, rather than
at the run that actually built and tested the tree. Following such a
chain by hand to find the real build is tedious.

Bottom out that chain in the script: after identifying a candidate run,
inspect its Validation job's annotations for the same 'Skipping: There
already is a successful run: <url>' notice. If present, fetch the
referenced run, verify it is still completed and successful, and repeat
until we reach a run that is not itself a skip-run. Use that URL for
both the notice and the job output, so consumers always see the real
underlying run.

Also add console logs along the way (initial match, each chain hop,
stop conditions) to make future debugging straightforward, and grant
the workflow checks: read so the script can call checks.listAnnotations.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
build: collapse chains of skipped workflow runs
… ESRP

Rewrite the release pipeline to extend the 1ES Pipeline Templates
directly and to perform code signing via inline ADO tasks, replacing
the existing MicroBuild.1ES.Official.yml@MicroBuildTemplate +
MicroBuild.Core <FilesToSign> mechanism.

This new pipeline matches the pattern already used by microsoft/git
and git-ecosystem/git-credential-manager.

We build the Payload and FastFetch with SkipCreateInstaller=true so
the Inno Setup compile is deferred until after ESRP signing, then
build the installer in a dedicated dotnet build step
(--no-dependencies prevents the Payload layout from re-running and
overwriting the freshly signed binaries).

We also add a release stage with a 1ES releaseJob that publishes a
draft GitHub Release on microsoft/VFSForGit attaching the installer
asset.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Download the Symbols pipeline artifact alongside the Installer in the
release stage, zip it up via ArchiveFiles@2, and attach it to the
draft GitHub Release so consumers (and crash-dump triage) can grab
the matching .pdb / native debug symbols for the binaries shipped in
SetupGVFS.<ver>.exe.

Both downloads now land under $(Pipeline.Workspace)/_final so the
GitHubRelease@1 'assets' glob picks up SetupGVFS.*.exe and
Symbols.zip from the same staging directory.

Also enable the auto-generated change log on the release while we're
already in the GitHubRelease@1 step.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Add a UseDotNet@2 task with useGlobalJson: true before the build step
so the agent uses exactly the SDK version pinned in global.json

This matches the behavior of the GitHub Actions build workflow, which
already uses actions/setup-dotnet with global-json-file.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Previously Build.bat warned and continued when it could not locate VS
MSBuild (via either PATH or vswhere), silently skipping the native
C++ projects (GitHooksLoader, GVFS.NativeTests, GVFS.PostIndexChangedHook,
GVFS.ReadObjectHook, GVFS.VirtualFileSystemHook). That meant a build
on a machine without the C++ workload would happily produce an
installer with the native binaries missing.

VS MSBuild and the C++ workload are not optional for any GVFS build
that's expected to run, so make a missing toolchain a hard error
instead. Anyone hitting it should install Visual Studio with the
'Desktop development with C++' workload (or VS Build Tools with
VCTools).

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
GVFS sets PublishAot=true in Directory.Build.props for every managed
project, which means publishing GVFS.exe and friends needs the native
C++ toolchain (link.exe, the Windows SDK, etc.) at build time. The
1ES win-x86_64-ado1es image used by the new release pipeline has no VS
installed so the Native AOT publish step fails with:

    error : Platform linker not found.

..per the documented NativeAOT prerequisites
(https://aka.ms/nativeaot-prerequisites), which call for VS 2022 with
the 'Desktop development with C++' workload.

Add a PowerShell script that ensures the C++ workload is present
before Build.bat runs, and wire it into release.yml. The script:

  * Bootstraps vswhere.exe from its GitHub release if the standard
    Program Files location does not have it (so it works on minimal
    images too).

  * Uses 'vswhere -requires NativeDesktop VCTools -requiresAny' to
    decide whether the workload is already installed on any existing
    Visual Studio install. If yes, exit 0 and let the build run.

  * If a Visual Studio install exists but lacks the workload, run
    its setup.exe modify to add the appropriate workload ID
    (NativeDesktop for full VS, VCTools for Build Tools).

  * If no Visual Studio is installed at all, download the VS Build
    Tools bootstrapper from aka.ms and install it with the VCTools
    workload from scratch.

  * Treat exit codes 0 and 3010 (success, reboot needed) as success
    for both modify and fresh install.

  * Re-run the same vswhere requirement check post-install to
    verify.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
VFS for Git's runtime and several of its unit tests P/Invoke into
ProjectedFSLib.dll (e.g. Microsoft.Windows.ProjFS.ProjFSNative
.PrjDoesNameContainWildCards via ActiveEnumeration). That DLL is only
present on disk when the 'Client-ProjFS' Windows optional feature is
enabled.

The 1ES win-x86_64-ado1es image used by the new release pipeline does
not have that feature enabled, so RunUnitTests.bat fails with:

    System.DllNotFoundException : Unable to load DLL
    'ProjectedFSLib.dll' or one of its dependencies. (0x8007007E)
       at Microsoft.Windows.ProjFS.ProjFSNative.PrjDoesNameContainWildCards(...)
       at GVFS.Platform.Windows.ActiveEnumeration.SaveFilter(...)
       at GVFS.UnitTests.Windows.Virtualization.ActiveEnumerationTests
          .CannotSetMoreThanOneFilter()

Add a small PowerShell helper that enables the feature, and run it as
a build prereq. The script is a no-op when the feature is already
enabled, so it's safe to keep across image refreshes.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Visual Studio's MSBuild for native C++ projects emits a
<binary>.exe.lastcodeanalysissucceeded marker file next to each
produced executable to record that PREfast / code analysis ran
successfully on it. Those marker files are pure build-time
bookkeeping with no runtime purpose, but the GVFS.Payload layout
step xcopies the entire native bin\x64\<Config>\ folder for each
of GitHooksLoader, GVFS.PostIndexChangedHook, GVFS.ReadObjectHook
and GVFS.VirtualFileSystemHook -- so the markers end up in the
Payload, get packaged into SetupGVFS.exe, and finally land on
end-user machines as e.g. GitHooksLoader.exe.lastcodeanalysissucceeded
in 'C:\Program Files\VFS for Git\'.

Extend the existing layout.bat cleanup block (which already strips
*.runtimeconfig.json, *.deps.json, and orphaned managed PDBs) to
also recursively delete *.lastcodeanalysissucceeded from the
output directory so they're never shipped.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Refactor the three EsrpCodeSigning@6 invocations in release.yml
(Payload binaries, FastFetch, installer) to use a shared
.azure-pipelines/esrp/sign.yml step template, modeled on the same
template in microsoft/git.

The template:

  * Forwards the per-call inputs (displayName, folderPath, pattern,
    inlineOperation) to EsrpCodeSigning@6.

  * Provides defaults for the ESRP connection parameters that point
    at the standard pipeline variables ($(esrpAppConnectionName),
    $(esrpClientId), etc.), so callers don't repeat them.

  * Runs an inline PowerShell@2 step right after each signing
    operation that removes the CodeSignSummary-<guid>.md report
    ESRP CLI drops into the signing folder. Without this, those
    .md files would otherwise end up packaged into SetupGVFS.exe
    (Payload), or uploaded as part of the FastFetch and Installer
    pipeline artifacts.

Net effect on release.yml is a small reduction in line count and,
more importantly, cleanup is no longer something a future caller
can forget to wire up.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
Replace Microbuild with 1ES PT + ESRP
@mjcheetham mjcheetham requested review from dscho and tyrielv May 14, 2026 15:16
@mjcheetham mjcheetham enabled auto-merge May 14, 2026 15:17
@mjcheetham mjcheetham merged commit 3980ba3 into releases/shipped May 14, 2026
108 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants