Skip to content

Commit 5c10997

Browse files
committed
windows release: build, sign, and publish
Add the Windows release process to: 1. Build and sign the payload 2. Use the signed payload to build and sign the user and system installers 3. Publish the signed installers, payload, and symbols This change also removes the no-longer-needed Payload.Windows project and removes the 'core' suffix from the Windows installers.
1 parent b4826d0 commit 5c10997

File tree

8 files changed

+194
-122
lines changed

8 files changed

+194
-122
lines changed

.github/workflows/continuous-integration.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,4 @@ jobs:
4242
run: dotnet build --configuration MacRelease
4343

4444
- name: Test
45-
run: dotnet test --no-restore --verbosity normal
45+
run: dotnet test --verbosity normal

.github/workflows/release.yml

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,121 @@ jobs:
237237
uses: actions/upload-artifact@v3
238238
with:
239239
name: osx-sign
240-
path: signed/*.pkg
240+
path: signed/*.pkg
241+
242+
# ================================
243+
# Windows
244+
# ================================
245+
win-sign:
246+
name: Build and Sign Windows
247+
runs-on: windows-latest
248+
steps:
249+
- uses: actions/checkout@v3
250+
with:
251+
fetch-depth: 0 # Indicate full history so Nerdbank.GitVersioning works.
252+
253+
- name: Set up dotnet
254+
uses: actions/setup-dotnet@v2
255+
with:
256+
dotnet-version: 6.0.201
257+
258+
# Install Nerdbank.GitVersioning
259+
- uses: dotnet/nbgv@master
260+
with:
261+
setCommonVars: true
262+
263+
- name: Install dependencies
264+
run: dotnet restore
265+
266+
- name: Build
267+
run: |
268+
dotnet build --configuration=WindowsRelease
269+
270+
- name: Run Windows unit tests
271+
run: |
272+
dotnet test --configuration=WindowsRelease
273+
274+
- name: Lay out Windows payload and symbols
275+
shell: pwsh
276+
run: |
277+
cd src/windows/Installer.Windows/
278+
./layout.ps1 -Configuration WindowsRelease -Output payload -SymbolOutput symbols
279+
mkdir unsigned-payload
280+
Get-ChildItem -Path payload/* -Include *.exe, *.dll | Move-Item -Destination unsigned-payload
281+
282+
- uses: azure/login@v1
283+
with:
284+
creds: ${{ secrets.AZURE_CREDENTIALS }}
285+
286+
- name: Set up ESRP client
287+
shell: pwsh
288+
env:
289+
AZURE_STORAGE_KEY: ${{ secrets.AZURE_STORAGE_KEY }}
290+
AZURE_VAULT: ${{ secrets.AZURE_VAULT }}
291+
AUTH_CERT: ${{ secrets.AZURE_VAULT_AUTH_CERT_NAME }}
292+
REQUEST_SIGNING_CERT: ${{ secrets.AZURE_VAULT_REQUEST_SIGNING_CERT_NAME }}
293+
run: |
294+
.github\set_up_esrp.ps1
295+
296+
- name: Run ESRP client for unsigned payload
297+
shell: pwsh
298+
env:
299+
AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }}
300+
# We temporarily need two AAD IDs, as we're using an SSL certificate associated
301+
# with an older App Registration until we have the required hardware to approve
302+
# the new certificate in SSL Admin.
303+
AZURE_AAD_ID_SSL: ${{ secrets.AZURE_AAD_ID_SSL }}
304+
WINDOWS_KEY_CODE: ${{ secrets.WINDOWS_KEY_CODE }}
305+
WINDOWS_OP_CODE: ${{ secrets.WINDOWS_OPERATION_CODE }}
306+
run: |
307+
python .github\run_esrp_signing.py `
308+
src/windows/Installer.Windows/unsigned-payload `
309+
$env:WINDOWS_KEY_CODE $env:WINDOWS_OP_CODE `
310+
--params 'OpusName' 'Microsoft' `
311+
'OpusInfo' 'http://www.microsoft.com' `
312+
'FileDigest' '/fd "SHA256"' 'PageHash' '/NPH' `
313+
'TimeStamp' '/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256'
314+
315+
- name: Lay out signed payload
316+
shell: pwsh
317+
run: |
318+
mkdir signed-payload
319+
Move-Item -Path signed/* -Destination signed-payload
320+
# ESRP will not sign the *.exe.config or NOTICE files, but they are needed to build the installers.
321+
# Due to this, we copy them after signing.
322+
Get-ChildItem -Path src/windows/Installer.Windows/payload/* -Include *.exe.config, NOTICE | Move-Item -Destination signed-payload
323+
Remove-Item signed -Recurse -Force
324+
325+
- name: Build with signed payload
326+
shell: pwsh
327+
run: |
328+
dotnet build src/windows/Installer.Windows /p:PayloadPath=$env:GITHUB_WORKSPACE/signed-payload /p:NoLayout=true --configuration=WindowsRelease
329+
330+
- name: Run ESRP client for installers
331+
shell: pwsh
332+
env:
333+
AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }}
334+
# We temporarily need two AAD IDs, as we're using an SSL certificate associated
335+
# with an older App Registration until we have the required hardware to approve
336+
# the new certificate in SSL Admin.
337+
AZURE_AAD_ID_SSL: ${{ secrets.AZURE_AAD_ID_SSL }}
338+
WINDOWS_KEY_CODE: ${{ secrets.WINDOWS_KEY_CODE }}
339+
WINDOWS_OP_CODE: ${{ secrets.WINDOWS_OPERATION_CODE }}
340+
run: |
341+
python .github\run_esrp_signing.py `
342+
.\out\windows\Installer.Windows\bin\WindowsRelease\net472 `
343+
$env:WINDOWS_KEY_CODE `
344+
$env:WINDOWS_OP_CODE `
345+
--params 'OpusName' 'Microsoft' `
346+
'OpusInfo' 'http://www.microsoft.com' `
347+
'FileDigest' '/fd "SHA256"' 'PageHash' '/NPH' `
348+
'TimeStamp' '/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256'
349+
350+
- name: Publish final artifacts
351+
uses: actions/upload-artifact@v3
352+
with:
353+
name: win-sign
354+
path: |
355+
signed
356+
signed-payload
357+
src/windows/Installer.Windows/symbols

Git-Credential-Manager.sln

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Installer.Mac", "src\osx\In
3131
EndProject
3232
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Installer.Windows", "src\windows\Installer.Windows\Installer.Windows.csproj", "{85903170-9E52-4B53-A6E4-3F416F684FAE}"
3333
EndProject
34-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Payload.Windows", "src\windows\Payload.Windows\Payload.Windows.csproj", "{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}"
35-
EndProject
3634
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Atlassian.Bitbucket", "src\shared\Atlassian.Bitbucket\Atlassian.Bitbucket.csproj", "{B49881A6-E734-490E-8EA7-FB0D9E296CFB}"
3735
EndProject
3836
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Atlassian.Bitbucket.Tests", "src\shared\Atlassian.Bitbucket.Tests\Atlassian.Bitbucket.Tests.csproj", "{025E5329-A0B1-4BA9-9203-B70B44A5F9E0}"
@@ -229,16 +227,6 @@ Global
229227
{85903170-9E52-4B53-A6E4-3F416F684FAE}.WindowsRelease|Any CPU.Build.0 = Release|Any CPU
230228
{85903170-9E52-4B53-A6E4-3F416F684FAE}.LinuxDebug|Any CPU.ActiveCfg = Debug|Any CPU
231229
{85903170-9E52-4B53-A6E4-3F416F684FAE}.LinuxRelease|Any CPU.ActiveCfg = Release|Any CPU
232-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
233-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.MacDebug|Any CPU.ActiveCfg = Debug|Any CPU
234-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.MacRelease|Any CPU.ActiveCfg = Release|Any CPU
235-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.Release|Any CPU.ActiveCfg = Release|Any CPU
236-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.WindowsDebug|Any CPU.ActiveCfg = Debug|Any CPU
237-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.WindowsDebug|Any CPU.Build.0 = Debug|Any CPU
238-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.WindowsRelease|Any CPU.ActiveCfg = Release|Any CPU
239-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.WindowsRelease|Any CPU.Build.0 = Release|Any CPU
240-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.LinuxDebug|Any CPU.ActiveCfg = Debug|Any CPU
241-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549}.LinuxRelease|Any CPU.ActiveCfg = Release|Any CPU
242230
{B49881A6-E734-490E-8EA7-FB0D9E296CFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
243231
{B49881A6-E734-490E-8EA7-FB0D9E296CFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
244232
{B49881A6-E734-490E-8EA7-FB0D9E296CFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -499,7 +487,6 @@ Global
499487
{3D279E2D-E011-45CF-8EA8-3D71D1300443} = {A7FC1234-95E3-4496-B5F7-4306F41E6A0E}
500488
{74FA0AA4-B5C1-4F3B-B182-277FC2D50715} = {3D279E2D-E011-45CF-8EA8-3D71D1300443}
501489
{85903170-9E52-4B53-A6E4-3F416F684FAE} = {66722747-1B61-40E4-A89B-1AC8E6D62EA9}
502-
{8DBBAB0A-970D-4BE3-958C-8CDC92F76549} = {66722747-1B61-40E4-A89B-1AC8E6D62EA9}
503490
{B49881A6-E734-490E-8EA7-FB0D9E296CFB} = {D5277A0E-997E-453A-8CB9-4EFCC8B16A29}
504491
{025E5329-A0B1-4BA9-9203-B70B44A5F9E0} = {D5277A0E-997E-453A-8CB9-4EFCC8B16A29}
505492
{2B3CD8FF-84A6-4B53-A28B-D7A75B0AB4D7} = {66722747-1B61-40E4-A89B-1AC8E6D62EA9}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,11 @@ Installing GCM as a standalone package on Windows will forcibly override the ver
176176

177177
There are two flavors of standalone installation on Windows:
178178

179-
- User (preferred) (`gcmcoreuser-win*`):
179+
- User (preferred) (`gcmuser-win*`):
180180

181181
Does not require administrator rights. Will install only for the current user and updates only the current user's Git configuration.
182182

183-
- System (`gcmcore-win*`):
183+
- System (`gcm-win*`):
184184

185185
Requires administrator rights. Will install for all users on the system and update the system-wide Git configuration.
186186

src/windows/Installer.Windows/Installer.Windows.csproj

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,51 +5,29 @@
55
<PropertyGroup>
66
<TargetFramework>net472</TargetFramework>
77
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
8-
<PayloadPath>$(PlatformOutPath)Payload.Windows\bin\$(Configuration)\net472\win-x86</PayloadPath>
98
<EnableDefaultItems>false</EnableDefaultItems>
9+
<PayloadPath>$(PlatformOutPath)Installer.Windows\bin\$(Configuration)\net472\win-x86</PayloadPath>
1010
</PropertyGroup>
1111

1212
<ItemGroup>
1313
<None Include="Setup.iss" />
1414
</ItemGroup>
1515

16-
<ItemGroup>
17-
<ProjectReference Include="../Payload.Windows/Payload.Windows.csproj" ReferenceOutputAssembly="false" />
18-
</ItemGroup>
19-
2016
<ItemGroup>
2117
<PackageReference Include="Tools.InnoSetup" Version="6.0.5" />
22-
<PackageReference Include="Microsoft.VisualStudioEng.MicroBuild.Core" Version="1.0.0">
23-
<PrivateAssets>all</PrivateAssets>
24-
</PackageReference>
2518
</ItemGroup>
2619

27-
<!-- Since the installer file name includes the generated build number from Nerdbank.GitVersioning
28-
we must create the FilesToSign item inside of a target that depends on GetBuildVersion and runs
29-
before we attempt to sign any files or validate they exist. -->
30-
<Target Name="CreateFilesToSignItems" DependsOnTargets="GetBuildVersion" BeforeTargets="PrepareForRun">
31-
<ItemGroup>
32-
<FilesToSign Include="$(OutDir)gcmcore*-win-x86-$(BuildVersionSimple).exe">
33-
<Authenticode>Microsoft400</Authenticode>
34-
<InProject>false</InProject>
35-
</FilesToSign>
36-
</ItemGroup>
37-
</Target>
38-
3920
<!-- Implicit SDK targets import (so we can override the default targets below) -->
4021
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
4122

42-
<!-- Check all the files to sign exist -->
43-
<Target Name="ValidateSigningDependencies" AfterTargets="PrepareForRun" Inputs="@(FilesToSign)" Outputs="$(OutDir)validatesign.timestamp">
44-
<Error Text="File to sign not found: %(FilesToSign.Identity)" Condition="!Exists('%(FilesToSign.Identity)')" />
45-
<WriteLinesToFile File="$(OutDir)validatesign.timestamp" Lines="@(FilesToSign)" Overwrite="true" />
46-
</Target>
47-
4823
<Target Name="CoreCompile" Condition="'$(OSPlatform)'=='windows'">
4924
<PropertyGroup>
5025
<InnoSetupCommandSystem>"$(NuGetPackageRoot)Tools.InnoSetup\6.0.5\tools\ISCC.exe" /DPayloadDir="$(PayloadPath)" /DInstallTarget=system "$(RepoSrcPath)\windows\Installer.Windows\Setup.iss" /O"$(OutputPath)"</InnoSetupCommandSystem>
5126
<InnoSetupCommandUser>"$(NuGetPackageRoot)Tools.InnoSetup\6.0.5\tools\ISCC.exe" /DPayloadDir="$(PayloadPath)" /DInstallTarget=user "$(RepoSrcPath)\windows\Installer.Windows\Setup.iss" /O"$(OutputPath)"</InnoSetupCommandUser>
5227
</PropertyGroup>
28+
29+
<Message Text="Lay Out" Importance="High" />
30+
<Exec Condition="'$(NoLayout)'!='true'" Command="powershell.exe –NonInteractive –ExecutionPolicy Unrestricted -Command &quot;&amp; {&amp;'$(MSBuildProjectDirectory)\layout.ps1' -Configuration '$(Configuration)' -Output '$(PayloadPath)'}&quot;" />
5331
<Message Text="$(InnoSetupCommandSystem)" Importance="High" />
5432
<Exec Command="$(InnoSetupCommandSystem)" />
5533
<Message Text="$(InnoSetupCommandUser)" Importance="High" />

src/windows/Installer.Windows/Setup.iss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
#if InstallTarget == "user"
1919
#define GcmAppId "{{aa76d31d-432c-42ee-844c-bc0bc801cef3}}"
2020
#define GcmLongName "Git Credential Manager (User)"
21-
#define GcmSetupExe "gcmcoreuser"
21+
#define GcmSetupExe "gcmuser"
2222
#define GcmConfigureCmdArgs ""
2323
#elif InstallTarget == "system"
2424
#define GcmAppId "{{fdfae50a-1bc1-4ead-9228-1e1c275e8d12}}"
2525
#define GcmLongName "Git Credential Manager"
26-
#define GcmSetupExe "gcmcore"
26+
#define GcmSetupExe "gcm"
2727
#define GcmConfigureCmdArgs "--system"
2828
#else
2929
#error Installer target property 'InstallTarget' must be 'user' or 'system'
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Inputs
2+
param ([Parameter(Mandatory)] $CONFIGURATION, [Parameter(Mandatory)] $OUTPUT, $SYMBOLOUTPUT)
3+
4+
Write-Output "Output: $OUTPUT"
5+
6+
# Directories
7+
$THISDIR = $pwd.path
8+
$ROOT = (Get-Item $THISDIR).parent.parent.parent.FullName
9+
$SRC = "$ROOT/src"
10+
$GCM_SRC = "$SRC/shared/Git-Credential-Manager"
11+
$BITBUCKET_UI_SRC = "$SRC/windows/Atlassian.Bitbucket.UI.Windows"
12+
$GITHUB_UI_SRC = "$SRC/windows/GitHub.UI.Windows"
13+
$GITLAB_UI_SRC = "$SRC/windows/GitLab.UI.Windows"
14+
15+
# Perform pre-execution checks
16+
$PAYLOAD = "$OUTPUT"
17+
if ($SYMBOLOUTPUT)
18+
{
19+
$SYMBOLS = "$SYMBOLOUTPUT"
20+
} else {
21+
$SYMBOLS = "$PAYLOAD.sym"
22+
}
23+
24+
# Clean up any old payload and symbols directories
25+
if (Test-Path -Path $PAYLOAD)
26+
{
27+
Write-Output "Cleaning old payload directory '$PAYLOAD'..."
28+
Remove-Item -Recurse "$PAYLOAD" -Force
29+
}
30+
31+
if (Test-Path -Path $SYMBOLS)
32+
{
33+
Write-Output "Cleaning old symbols directory '$SYMBOLS'..."
34+
Remove-Item -Recurse "$SYMBOLS" -Force
35+
}
36+
37+
# Ensure payload and symbol directories exist
38+
mkdir -p "$PAYLOAD","$SYMBOLS"
39+
40+
# Publish core application executables
41+
Write-Output "Publishing core application..."
42+
dotnet publish "$GCM_SRC" `
43+
--framework net472 `
44+
--configuration "$CONFIGURATION" `
45+
--runtime win-x86 `
46+
--output "$PAYLOAD"
47+
48+
Write-Output "Publishing Bitbucket UI helper..."
49+
dotnet publish "$BITBUCKET_UI_SRC" `
50+
--configuration "$CONFIGURATION" `
51+
--output "$PAYLOAD"
52+
53+
Write-Output "Publishing GitHub UI helper..."
54+
dotnet publish "$GITHUB_UI_SRC" `
55+
--configuration "$CONFIGURATION" `
56+
--output "$PAYLOAD"
57+
58+
Write-Output "Publishing GitLab UI helper..."
59+
dotnet publish "$GITLAB_UI_SRC" `
60+
--configuration "$CONFIGURATION" `
61+
--output "$PAYLOAD"
62+
63+
# Collect symbols
64+
Write-Output "Collecting managed symbols..."
65+
Move-Item -Path "$PAYLOAD/*.pdb" -Destination "$SYMBOLS"
66+
67+
Write-Output "Layout complete."

src/windows/Payload.Windows/Payload.Windows.csproj

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

0 commit comments

Comments
 (0)