Skip to content

Commit f2bc533

Browse files
authored
Merge pull request microsoft#1853 from mjcheetham/gh-msgit
Download Microsoft Git from GitHub releases
2 parents 60f78a4 + c69ba8e commit f2bc533

9 files changed

Lines changed: 234 additions & 75 deletions

File tree

.github/workflows/build.yaml

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,38 @@ on:
55
branches: [ master, releases/shipped ]
66
push:
77
branches: [ master, releases/shipped ]
8+
workflow_dispatch:
9+
inputs:
10+
git_version:
11+
description: 'Microsoft Git version tag to include in the build (leave empty for default)'
12+
required: false
13+
type: string
14+
15+
env:
16+
GIT_VERSION: ${{ github.event.inputs.git_version || 'v2.50.1.vfs.0.1' }}
817

918
jobs:
19+
validate:
20+
runs-on: windows-2025
21+
name: Validation
22+
steps:
23+
- name: Checkout source
24+
uses: actions/checkout@v4
25+
26+
- name: Validate Microsoft Git version
27+
shell: pwsh
28+
env:
29+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30+
run: |
31+
& "$env:GITHUB_WORKSPACE\.github\workflows\scripts\validate_release.ps1" `
32+
-Repository microsoft/git `
33+
-Tag $env:GIT_VERSION && `
34+
Write-Host ::notice title=Validation::Using microsoft/git version $env:GIT_VERSION
35+
1036
build:
1137
runs-on: windows-2025
1238
name: Build and Unit Test
39+
needs: validate
1340

1441
strategy:
1542
matrix:
@@ -41,6 +68,13 @@ jobs:
4168
shell: cmd
4269
run: src\scripts\CreateBuildArtifacts.bat ${{ matrix.configuration }} artifacts
4370

71+
- name: Download microsoft/git installers
72+
shell: cmd
73+
env:
74+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
75+
run: |
76+
gh release download %GIT_VERSION% --repo microsoft/git --pattern "Git*.exe" --dir artifacts\GVFS.Installers
77+
4478
- name: Upload functional tests drop
4579
uses: actions/upload-artifact@v4
4680
with:
@@ -59,20 +93,15 @@ jobs:
5993
name: Installers_${{ matrix.configuration }}
6094
path: artifacts\GVFS.Installers
6195

62-
- name: Upload NuGet packages
63-
uses: actions/upload-artifact@v4
64-
with:
65-
name: NuGetPackages_${{ matrix.configuration }}
66-
path: artifacts\NuGetPackages
67-
6896
functional_test:
69-
runs-on: windows-2025
97+
runs-on: ${{ matrix.architecture == 'arm64' && 'windows-11-arm' || 'windows-2025' }}
7098
name: Functional Tests
7199
needs: build
72100

73101
strategy:
74102
matrix:
75103
configuration: [ Debug, Release ]
104+
architecture: [ x86_64, arm64 ]
76105

77106
steps:
78107
- name: Download installers
@@ -103,7 +132,7 @@ jobs:
103132
if: always()
104133
uses: actions/upload-artifact@v4
105134
with:
106-
name: InstallationLogs_${{ matrix.configuration }}
135+
name: InstallationLogs_${{ matrix.configuration }}_${{ matrix.architecture }}
107136
path: install\logs
108137

109138
- name: Run functional tests
@@ -117,14 +146,14 @@ jobs:
117146
if: always()
118147
uses: actions/upload-artifact@v4
119148
with:
120-
name: FunctionalTests_Results_${{ matrix.configuration }}
149+
name: FunctionalTests_Results_${{ matrix.configuration }}_${{ matrix.architecture }}
121150
path: TestResult.xml
122151

123152
- name: Upload Git trace2 output
124153
if: always()
125154
uses: actions/upload-artifact@v4
126155
with:
127-
name: GitTrace2_${{ matrix.configuration }}
156+
name: GitTrace2_${{ matrix.configuration }}_${{ matrix.architecture }}
128157
path: C:\temp\git-trace2.log
129158

130159
- name: ProjFS details (post-test)
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
param(
2+
[Parameter(Mandatory=$true)]
3+
[string]$Tag,
4+
5+
[Parameter(Mandatory=$true)]
6+
[string]$Repository
7+
)
8+
9+
function Write-GitHubActionsCommand {
10+
param(
11+
[Parameter(Mandatory=$true)]
12+
[string]$Command,
13+
14+
[Parameter(Mandatory=$true)]
15+
[string]$Message,
16+
17+
[Parameter(Mandatory=$true)]
18+
[string]$Title
19+
)
20+
21+
Write-Host "::$Command title=$Title::$Message"
22+
}
23+
24+
25+
function Write-GitHubActionsWarning {
26+
param(
27+
[Parameter(Mandatory=$true)]
28+
[string]$Message,
29+
30+
[Parameter(Mandatory=$false)]
31+
[string]$Title = "Warning"
32+
)
33+
34+
if ($env:GITHUB_ACTIONS -eq "true") {
35+
Write-GitHubActionsCommand -Command "warning" -Message $Message -Title $Title
36+
} else {
37+
Write-Host "! Warning: $Message" -ForegroundColor Yellow
38+
}
39+
}
40+
41+
function Write-GitHubActionsError {
42+
param(
43+
[Parameter(Mandatory=$true)]
44+
[string]$Message,
45+
46+
[Parameter(Mandatory=$false)]
47+
[string]$Title = "Error"
48+
)
49+
50+
if ($env:GITHUB_ACTIONS -eq "true") {
51+
Write-GitHubActionsCommand -Command "error" -Message $Message -Title $Title
52+
} else {
53+
Write-Host "x Error: $Message" -ForegroundColor Red
54+
}
55+
}
56+
57+
if ([string]::IsNullOrWhiteSpace($Tag)) {
58+
Write-GitHubActionsError -Message "Tag parameter is required"
59+
exit 1
60+
}
61+
62+
if ([string]::IsNullOrWhiteSpace($Repository)) {
63+
Write-GitHubActionsError -Message "Repository parameter is required"
64+
exit 1
65+
}
66+
67+
Write-Host "Validating $Repository release '$Tag'..."
68+
69+
# Prepare headers for GitHub API
70+
$headers = @{
71+
'Accept' = 'application/vnd.github.v3+json'
72+
'User-Agent' = 'VFSForGit-Build'
73+
}
74+
75+
if ($env:GITHUB_TOKEN) {
76+
$headers['Authorization'] = "Bearer $env:GITHUB_TOKEN"
77+
}
78+
79+
# Check if the tag exists in microsoft/git repository
80+
try {
81+
$releaseResponse = Invoke-RestMethod `
82+
-Uri "https://api.github.com/repos/$Repository/releases/tags/$Tag" `
83+
-Headers $headers
84+
85+
Write-Host "✓ Tag '$Tag' found in $Repository" -ForegroundColor Green
86+
Write-Host " Release : $($releaseResponse.name)"
87+
Write-Host " Published : $($releaseResponse.published_at.ToString('u'))"
88+
89+
# Check if this a pre-release
90+
if ($releaseResponse.prerelease -eq $true) {
91+
Write-GitHubActionsWarning `
92+
-Message "Using a pre-released version of $Repository" `
93+
-Title "Pre-release $Repository version"
94+
}
95+
96+
# Get the latest release for comparison
97+
try {
98+
$latestResponse = Invoke-RestMethod `
99+
-Uri "https://api.github.com/repos/$Repository/releases/latest" `
100+
-Headers $headers
101+
$latestTag = $latestResponse.tag_name
102+
103+
# Check if this is the latest release
104+
if ($Tag -eq $latestTag) {
105+
Write-Host "✓ Using the latest release" -ForegroundColor Green
106+
exit 0
107+
}
108+
109+
# Not the latest!
110+
$warningTitle = "Outdated $Repository release"
111+
$warningMsg = "Not using latest release of $Repository (latest: $latestTag)"
112+
Write-GitHubActionsWarning -Message $warningMsg -Title $warningTitle
113+
} catch {
114+
Write-GitHubActionsWarning -Message "Could not check latest release info for ${Repository}: $($_.Exception.Message)"
115+
}
116+
} catch {
117+
if ($_.Exception.Response.StatusCode -eq 404) {
118+
Write-GitHubActionsError -Message "Tag '$Tag' does not exist in $Repository"
119+
exit 1
120+
} else {
121+
Write-GitHubActionsError -Message "Error validating release '$Tag': $($_.Exception.Message)"
122+
exit 1
123+
}
124+
}

GVFS/GVFS.FunctionalTests/Tools/GitHelpers.cs

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,55 @@ public static ProcessResult InvokeGitAgainstGVFSRepo(
6363
string command,
6464
Dictionary<string, string> environmentVariables = null,
6565
bool removeWaitingMessages = true,
66-
bool removeUpgradeMessages = true)
66+
bool removeUpgradeMessages = true,
67+
bool removePartialHydrationMessages = true,
68+
bool removeFSMonitorMessages = true)
6769
{
6870
ProcessResult result = GitProcess.InvokeProcess(gvfsRepoRoot, command, environmentVariables);
69-
string errors = result.Errors;
71+
string output = FilterMessages(result.Output, false, false, false, removePartialHydrationMessages, removeFSMonitorMessages);
72+
string errors = FilterMessages(result.Errors, true, removeWaitingMessages, removeUpgradeMessages, removePartialHydrationMessages, removeFSMonitorMessages);
7073

71-
if (!string.IsNullOrEmpty(errors) && (removeWaitingMessages || removeUpgradeMessages))
74+
return new ProcessResult(
75+
output,
76+
errors,
77+
result.ExitCode);
78+
}
79+
80+
private static IEnumerable<string> SplitLinesKeepingNewlines(string input)
81+
{
82+
for (int start = 0; start < input.Length; )
7283
{
73-
IEnumerable<string> errorLines = errors.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
74-
IEnumerable<string> filteredErrorLines = errorLines.Where(line =>
84+
int nextLine = input.IndexOf('\n', start) + 1;
85+
86+
if (nextLine == 0)
7587
{
76-
if (string.IsNullOrWhiteSpace(line) ||
88+
// No more newlines, yield the rest
89+
nextLine = input.Length;
90+
}
91+
92+
yield return input.Substring(start, nextLine - start);
93+
start = nextLine;
94+
}
95+
}
96+
97+
private static string FilterMessages(
98+
string input,
99+
bool removeEmptyLines,
100+
bool removeWaitingMessages,
101+
bool removeUpgradeMessages,
102+
bool removePartialHydrationMessages,
103+
bool removeFSMonitorMessages)
104+
{
105+
if (!string.IsNullOrEmpty(input) && (removeWaitingMessages || removeUpgradeMessages || removePartialHydrationMessages || removeFSMonitorMessages))
106+
{
107+
IEnumerable<string> lines = SplitLinesKeepingNewlines(input);
108+
IEnumerable<string> filteredLines = lines.Where(line =>
109+
{
110+
if ((removeEmptyLines && string.IsNullOrWhiteSpace(line)) ||
77111
(removeUpgradeMessages && line.StartsWith("A new version of VFS for Git is available.")) ||
78-
(removeWaitingMessages && line.StartsWith("Waiting for ")))
112+
(removeWaitingMessages && line.StartsWith("Waiting for ")) ||
113+
(removePartialHydrationMessages && line.StartsWith("You are in a partially-hydrated checkout with ")) ||
114+
(removeFSMonitorMessages && line.TrimEnd().EndsWith(" is incompatible with fsmonitor")))
79115
{
80116
return false;
81117
}
@@ -85,13 +121,10 @@ public static ProcessResult InvokeGitAgainstGVFSRepo(
85121
}
86122
});
87123

88-
errors = filteredErrorLines.Any() ? string.Join(Environment.NewLine, filteredErrorLines) : string.Empty;
124+
return filteredLines.Any() ? string.Join("", filteredLines) : string.Empty;
89125
}
90126

91-
return new ProcessResult(
92-
result.Output,
93-
errors,
94-
result.ExitCode);
127+
return input;
95128
}
96129

97130
public static void ValidateGitCommand(

GVFS/GVFS.Installers/GVFS.Installers.csproj

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
<ItemGroup>
1515
<PackageReference Include="Tools.InnoSetup" Version="6.3.1" />
16-
<PackageReference Include="GitForWindows.GVFS.Installer" Version="$(GitPackageVersion)" />
17-
<PackageReference Include="GitForWindows.GVFS.Portable" Version="$(GitPackageVersion)" />
1816
<PackageReference Include="MicroBuild.Core" Version="0.2.0" ExcludeAssets="none" />
1917
</ItemGroup>
2018

@@ -24,13 +22,8 @@
2422

2523
<ItemGroup>
2624
<None Include="Setup.iss" />
27-
<Content Include="$(PkgGitForWindows_GVFS_Installer)\tools\*" />
28-
<Content Include="$(PkgGitForWindows_GVFS_Portable)\tools\*" />
2925
<Content Include="install.bat" />
3026
<Content Include="info.bat" />
31-
<NuspecTemplate Include="GVFS.Installers.template.nuspec"
32-
TargetPath="GVFS.Installers.nuspec"
33-
Properties="$version$=$(GVFSVersion)" />
3427
</ItemGroup>
3528

3629
<ItemGroup>
@@ -44,10 +37,6 @@
4437
<Exec Command='"$(PkgTools_InnoSetup)\tools\ISCC.exe" /DLayoutDir="$(LayoutPath)" /DGVFSVersion=$(GVFSVersion) Setup.iss /O"$(OutputPath)"' />
4538
</Target>
4639

47-
<Target Name="CreateNuspecFile" AfterTargets="CreateInstaller">
48-
<CompileTemplatedFile Template="@(NuspecTemplate)" OutputFile="$(OutputPath)\%(TargetPath)" />
49-
</Target>
50-
5140
<Target Name="CleanInstaller" BeforeTargets="AfterClean">
5241
<ItemGroup>
5342
<FilesToDelete Include="$(OutputPath)**\*"/>

GVFS/GVFS.Installers/GVFS.Installers.template.nuspec

Lines changed: 0 additions & 15 deletions
This file was deleted.

GVFS/GVFS.Installers/info.bat

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,31 @@ SET VFS_BUND_PROJFSLIB=C:\Program Files\VFS for Git\ProjFS\ProjectedFSLib.dll
99
SET VFS_EXEC=C:\Program Files\VFS for Git\GVFS.exe
1010
SET GIT_EXEC=C:\Program Files\Git\cmd\git.exe
1111

12+
REM Lookup the current Windows version
13+
FOR /F "tokens=*" %%i IN ('powershell -Command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"') DO SET OS_VER=%%i
14+
15+
ECHO Print system information...
16+
ECHO OS version: %OS_VER%
17+
ECHO CPU architecture: %PROCESSOR_ARCHITECTURE%
18+
19+
ECHO.
1220
ECHO Checking ProjFS Windows feature...
1321
powershell -Command "Get-WindowsOptionalFeature -Online -FeatureName Client-ProjFS"
1422

23+
ECHO.
1524
ECHO Checking ProjFS and GVFS services...
1625
ECHO GVFS.Service:
1726
sc query GVFS.Service
1827

28+
ECHO.
1929
ECHO Test.GVFS.Service:
2030
sc query Test.GVFS.Service
2131

32+
ECHO.
2233
ECHO prjflt:
2334
sc query prjflt
2435

36+
ECHO.
2537
ECHO Checking ProjFS files...
2638
IF EXIST "%SYS_PRJFLT%" (
2739
ECHO [ FOUND ] %SYS_PRJFLT%

0 commit comments

Comments
 (0)