Skip to content

Commit e20e0f3

Browse files
committed
build-git-installers: update windows signing
This commit contains two temporary workflows: 1. windows-full: This workflow was designed to use the same key used for Linux signing for GPG signing. It also uses the Azure Code Signing action to sign Windows installers. 2. windows-minimal: This workflow was intended to test the minimal requirements for Windows builds to see whether it is possible to use Azure Code Signing as the singtool alias for exe signing. This workflow is already set up with tmate for testing on GitHub Actions runners (since the issue described below does not repro locally). While we were unable to get past an issue with the second workflow hanging instead of executing signing, hopefully this will provide a solid starting point if someone would like to re-attempt Azure Code Signing/GPG signing for microsoft/git in the future. Note: If signing is successfully implemented with the alias used in workflow microsoft#2, this alias should also be used for installer signing rather than the Azure Code Signing action so that the embedded uninstaller is signed in addition to the installers.
1 parent 7a89262 commit e20e0f3

File tree

2 files changed

+536
-0
lines changed

2 files changed

+536
-0
lines changed

.github/workflows/windows-full.yml

Lines changed: 382 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
name: windows-full
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v[0-9]*vfs*' # matches "v<number><any characters>vfs<any characters>"
7+
8+
jobs:
9+
# Check prerequisites for the workflow
10+
prereqs:
11+
runs-on: ubuntu-latest
12+
environment: release
13+
outputs:
14+
tag_name: ${{ steps.tag.outputs.name }} # The full name of the tag, e.g. v2.32.0.vfs.0.0
15+
tag_version: ${{ steps.tag.outputs.version }} # The version number (without preceding "v"), e.g. 2.32.0.vfs.0.0
16+
steps:
17+
- name: Validate tag
18+
run: |
19+
echo "$GITHUB_REF" |
20+
grep '^refs/tags/v2\.\(0\|[1-9][0-9]*\)\.\(0\|[1-9][0-9]*\)\.vfs\.0\.\(0\|[1-9][0-9]*\)$' || {
21+
echo "::error::${GITHUB_REF#refs/tags/} is not of the form v2.<X>.<Y>.vfs.0.<W>" >&2
22+
exit 1
23+
}
24+
- name: Determine tag to build
25+
run: |
26+
echo "name=${GITHUB_REF#refs/tags/}" >>$GITHUB_OUTPUT
27+
echo "version=${GITHUB_REF#refs/tags/v}" >>$GITHUB_OUTPUT
28+
id: tag
29+
- name: Clone git
30+
uses: actions/checkout@v3
31+
- name: Validate the tag identified with trigger
32+
run: |
33+
die () {
34+
echo "::error::$*" >&2
35+
exit 1
36+
}
37+
38+
# `actions/checkout` only downloads the peeled tag (i.e. the commit)
39+
git fetch origin +$GITHUB_REF:$GITHUB_REF
40+
41+
# Verify that the tag is annotated
42+
test $(git cat-file -t "$GITHUB_REF") == "tag" || die "Tag ${{ steps.tag.outputs.name }} is not annotated"
43+
44+
# Verify tag follows rules in GIT-VERSION-GEN (i.e., matches the specified "DEF_VER" in
45+
# GIT-VERSION-FILE) and matches tag determined from trigger
46+
make GIT-VERSION-FILE
47+
test "${{ steps.tag.outputs.version }}" == "$(sed -n 's/^GIT_VERSION = //p'< GIT-VERSION-FILE)" || die "GIT-VERSION-FILE tag does not match ${{ steps.tag.outputs.name }}"
48+
# End check prerequisites for the workflow
49+
50+
# Build and sign Windows installers & upload artifacts
51+
windows_pkg:
52+
runs-on: windows-2019
53+
environment: release
54+
needs: prereqs
55+
env:
56+
GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback"
57+
HOME: "${{github.workspace}}\\home"
58+
USERPROFILE: "${{github.workspace}}\\home"
59+
steps:
60+
- name: Configure user
61+
shell: bash
62+
run:
63+
USER_NAME="${{github.actor}}" &&
64+
USER_EMAIL="${{github.actor}}@users.noreply.github.com" &&
65+
mkdir -p "$HOME" &&
66+
git config --global user.name "$USER_NAME" &&
67+
git config --global user.email "$USER_EMAIL" &&
68+
echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV
69+
70+
- uses: git-for-windows/setup-git-for-windows-sdk@v1
71+
with:
72+
flavor: build-installers
73+
74+
- name: Clone build-extra
75+
shell: bash
76+
run: |
77+
git clone --filter=blob:none --single-branch -b main https://github.com/git-for-windows/build-extra /usr/src/build-extra
78+
79+
- name: Clone git
80+
shell: bash
81+
run: |
82+
# Since we cannot directly clone a specified tag (as we would a branch with `git clone -b <branch name>`),
83+
# this clone has to be done manually (via init->fetch->reset).
84+
85+
tag_name="${{ needs.prereqs.outputs.tag_name }}" &&
86+
git -c init.defaultBranch=main init &&
87+
git remote add -f origin https://github.com/git-for-windows/git &&
88+
git fetch "https://github.com/${{github.repository}}" refs/tags/${tag_name}:refs/tags/${tag_name} &&
89+
git reset --hard ${tag_name}
90+
91+
- name: Log into Azure
92+
uses: azure/login@v1
93+
with:
94+
creds: ${{ secrets.AZURE_CREDENTIALS }}
95+
96+
- name: Install Azure Code Signing Module
97+
shell: pwsh
98+
run: |
99+
Install-Module -Name AzureCodeSigning -RequiredVersion 0.2.24 -Force `
100+
-Repository PSGallery
101+
102+
- name: Prepare for exe code signing
103+
shell: bash
104+
run: |
105+
git config alias.signtool '!f() { printf "%s\n" "$@" >/tmp/catalog && \
106+
powershell -command "Invoke-AzureCodeSigning \
107+
-Endpoint https://wus2.codesigning.azure.net/ \
108+
-CodeSigningAccountName git-fundamentals-signing \
109+
-CertificateProfileName git-fundamentals-windows-signing \
110+
-FilesCatalog /tmp/catalog -FileDigest SHA256 \
111+
-TimestampRfc3161 http://timestamp.acs.microsoft.com \
112+
-TimestampDigest SHA256 }; f'
113+
114+
- name: Prepare for GPG signing
115+
env:
116+
AZURE_VAULT: ${{ secrets.AZURE_VAULT }}
117+
GPG_KEY_SECRET_NAME: ${{ secrets.GPG_KEY_SECRET_NAME }}
118+
GPG_PASSPHRASE_SECRET_NAME: ${{ secrets.GPG_PASSPHRASE_SECRET_NAME }}
119+
GPG_KEYGRIP_SECRET_NAME: ${{ secrets.GPG_KEYGRIP_SECRET_NAME }}
120+
shell: bash
121+
run: |
122+
# Download GPG key, passphrase, and keygrip from Azure Key Vault
123+
key=$(az keyvault secret show --name $GPG_KEY_SECRET_NAME --vault-name $AZURE_VAULT --query "value")
124+
passphrase=$(az keyvault secret show --name $GPG_PASSPHRASE_SECRET_NAME --vault-name $AZURE_VAULT --query "value")
125+
keygrip=$(az keyvault secret show --name $GPG_KEYGRIP_SECRET_NAME --vault-name $AZURE_VAULT --query "value")
126+
127+
# Remove quotes from downloaded values
128+
key=$(sed -e 's/^"//' -e 's/"$//' <<<"$key")
129+
passphrase=$(sed -e 's/^"//' -e 's/"$//' <<<"$passphrase")
130+
keygrip=$(sed -e 's/^"//' -e 's/"$//' <<<"$keygrip")
131+
132+
# Import GPG key
133+
echo "$key" | base64 -d | gpg $GPG_OPTIONS --import
134+
135+
# Configure GPG
136+
echo "allow-preset-passphrase" > ~/.gnupg/gpg-agent.conf
137+
gpg-connect-agent RELOADAGENT /bye
138+
gpg-connect-agent 'PRESET_PASSPHRASE "$keygrip" -1 "$passphrase"' /bye
139+
140+
- name: Prepare home directory for GPG signing
141+
if: env.GPG_FINGERPRINT_SECRET_NAME != ''
142+
shell: bash
143+
run: |
144+
# This section ensures that the identity for the GPG key matches the git user identity, otherwise
145+
# signing will fail
146+
147+
# Get GPG key fingerprint from Azure Key Vault
148+
GPGKEY=$(az keyvault secret show --name "$GPG_FINGERPRINT_SECRET_NAME" \
149+
--vault-name "$AZURE_VAULT" --query "value" \
150+
| sed -e 's/^"//' -e 's/"$//')
151+
152+
info="$(gpg --list-keys --with-colons "${GPGKEY%% *}" | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" &&
153+
git config --global user.name "${info% <*}" &&
154+
git config --global user.email "<${info#*<}"
155+
env:
156+
AZURE_VAULT: ${{ secrets.AZURE_VAULT }}
157+
GPG_FINGERPRINT_SECRET_NAME: ${{secrets.GPG_FINGERPRINT_SECRET_NAME}}
158+
159+
- name: Build mingw-w64-x86_64-git
160+
env:
161+
AZURE_VAULT: ${{ secrets.AZURE_VAULT }}
162+
GPG_FINGERPRINT_SECRET_NAME: ${{secrets.GPG_FINGERPRINT_SECRET_NAME}}
163+
shell: bash
164+
run: |
165+
set -x
166+
167+
# Get GPG key fingerprint from Azure Key Vault
168+
GPGKEY=$(az keyvault secret show --name "$GPG_FINGERPRINT_SECRET_NAME" \
169+
--vault-name "$AZURE_VAULT" --query "value" \
170+
| sed -e 's/^"//' -e 's/"$//')
171+
172+
# Make sure that there is a `/usr/bin/git` that can be used by `makepkg-mingw`
173+
printf '#!/bin/sh\n\nexec /mingw64/bin/git.exe "$@"\n' >/usr/bin/git &&
174+
175+
# Restrict `PATH` to MSYS2 and to Visual Studio (to let `cv2pdb` find the relevant DLLs)
176+
PATH="/mingw64/bin:/usr/bin:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64:/C/Windows/system32"
177+
178+
type -p mspdb140.dll || exit 1
179+
180+
sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-64-bit --build-src-pkg -o artifacts HEAD
181+
182+
- name: Sign tarballs with GPG
183+
shell: bash
184+
run: |
185+
if test -n "$GPGKEY"
186+
then
187+
for tar in artifacts/*.tar*
188+
do
189+
/usr/src/build-extra/gnupg-with-gpgkey.sh --detach-sign --no-armor $tar
190+
done
191+
fi &&
192+
193+
b=$PWD/artifacts &&
194+
version=${{ needs.prereqs.outputs.tag_name }} &&
195+
(cd /usr/src/MINGW-packages/mingw-w64-git &&
196+
cp PKGBUILD.$version PKGBUILD &&
197+
git commit -s -m "mingw-w64-git: new version ($version)" PKGBUILD &&
198+
git bundle create "$b"/MINGW-packages.bundle origin/main..main)
199+
200+
- name: Publish mingw-w64-x86_64-git
201+
uses: actions/upload-artifact@v3
202+
with:
203+
name: pkg-x86_64
204+
path: artifacts
205+
206+
create-windows-artifacts:
207+
runs-on: windows-2019
208+
environment: release
209+
needs: [prereqs, windows_pkg]
210+
env:
211+
HOME: "${{github.workspace}}\\home"
212+
strategy:
213+
matrix:
214+
artifact:
215+
- name: installer
216+
fileprefix: Git
217+
- name: portable
218+
fileprefix: PortableGit
219+
fail-fast: false
220+
steps:
221+
- name: Download pkg-x86_64
222+
uses: actions/download-artifact@v3
223+
with:
224+
name: pkg-x86_64
225+
path: pkg-x86_64
226+
227+
- uses: git-for-windows/setup-git-for-windows-sdk@v1
228+
with:
229+
flavor: build-installers
230+
231+
- name: Clone build-extra
232+
shell: bash
233+
run: |
234+
git clone --filter=blob:none --single-branch -b main https://github.com/git-for-windows/build-extra /usr/src/build-extra
235+
236+
- name: Retarget auto-update to microsoft/git
237+
shell: bash
238+
run: |
239+
set -x
240+
241+
b=/usr/src/build-extra &&
242+
243+
filename=$b/git-update-git-for-windows.config
244+
tr % '\t' >$filename <<-\EOF &&
245+
[update]
246+
%fromFork = microsoft/git
247+
EOF
248+
249+
sed -i -e '/^#include "file-list.iss"/a\
250+
Source: {#SourcePath}\\..\\git-update-git-for-windows.config; DestDir: {app}\\mingw64\\bin; Flags: replacesameversion; AfterInstall: DeleteFromVirtualStore' \
251+
-e '/^Type: dirifempty; Name: {app}\\{#MINGW_BITNESS}$/i\
252+
Type: files; Name: {app}\\{#MINGW_BITNESS}\\bin\\git-update-git-for-windows.config\
253+
Type: dirifempty; Name: {app}\\{#MINGW_BITNESS}\\bin' \
254+
$b/installer/install.iss
255+
256+
- name: Set alerts to continue until upgrade is taken
257+
shell: bash
258+
run: |
259+
set -x
260+
261+
b=/mingw64/bin &&
262+
263+
sed -i -e '6 a use_recently_seen=no' \
264+
$b/git-update-git-for-windows
265+
266+
- name: Set the installer Publisher to the Git Fundamentals team
267+
shell: bash
268+
run: |
269+
b=/usr/src/build-extra &&
270+
sed -i -e 's/^\(AppPublisher=\).*/\1The Git Fundamentals Team at GitHub/' $b/installer/install.iss
271+
272+
- name: Let the installer configure Visual Studio to use the installed Git
273+
shell: bash
274+
run: |
275+
set -x
276+
277+
b=/usr/src/build-extra &&
278+
279+
sed -i -e '/^ *InstallAutoUpdater();$/a\
280+
CustomPostInstall();' \
281+
-e '/^ *UninstallAutoUpdater();$/a\
282+
CustomPostUninstall();' \
283+
$b/installer/install.iss &&
284+
285+
cat >>$b/installer/helpers.inc.iss <<\EOF
286+
287+
procedure CustomPostInstall();
288+
begin
289+
if not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\15.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or
290+
not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\16.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or
291+
not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\17.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or
292+
not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\18.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or
293+
not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\19.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) or
294+
not RegWriteStringValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\20.0\TeamFoundation\GitSourceControl','GitPath',ExpandConstant('{app}')) then
295+
LogError('Could not register TeamFoundation\GitSourceControl');
296+
end;
297+
298+
procedure CustomPostUninstall();
299+
begin
300+
if not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\15.0\TeamFoundation\GitSourceControl','GitPath') or
301+
not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\16.0\TeamFoundation\GitSourceControl','GitPath') or
302+
not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\17.0\TeamFoundation\GitSourceControl','GitPath') or
303+
not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\18.0\TeamFoundation\GitSourceControl','GitPath') or
304+
not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\19.0\TeamFoundation\GitSourceControl','GitPath') or
305+
not RegDeleteValue(HKEY_CURRENT_USER,'Software\Microsoft\VSCommon\20.0\TeamFoundation\GitSourceControl','GitPath') then
306+
LogError('Could not register TeamFoundation\GitSourceControl');
307+
end;
308+
EOF
309+
310+
- name: Enable Scalar/C and the auto-updater in the installer by default
311+
shell: bash
312+
run: |
313+
set -x
314+
315+
b=/usr/src/build-extra &&
316+
317+
sed -i -e "/ChosenOptions:=''/a\\
318+
if (ExpandConstant('{param:components|/}')='/') then begin\n\
319+
WizardSelectComponents('autoupdate');\n\
320+
#ifdef WITH_SCALAR\n\
321+
WizardSelectComponents('scalar');\n\
322+
#endif\n\
323+
end;" $b/installer/install.iss
324+
325+
- name: Build 64-bit ${{matrix.artifact.name}}
326+
shell: bash
327+
run: |
328+
set -x
329+
330+
# Copy the PDB archive to the directory where `--include-pdbs` expects it
331+
b=/usr/src/build-extra &&
332+
mkdir -p $b/cached-source-packages &&
333+
cp pkg-x86_64/*-pdb* $b/cached-source-packages/ &&
334+
335+
# Build the installer, embedding PDBs
336+
eval $b/please.sh make_installers_from_mingw_w64_git --include-pdbs \
337+
--version=${{ needs.prereqs.outputs.tag_version }} \
338+
-o artifacts --${{matrix.artifact.name}} \
339+
--pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz \
340+
--pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz &&
341+
342+
if test portable = '${{matrix.artifact.name}}' && test -n "$(git config alias.signtool)"
343+
then
344+
git signtool artifacts/PortableGit-*.exe
345+
fi &&
346+
openssl dgst -sha256 artifacts/${{matrix.artifact.fileprefix}}-*.exe | sed "s/.* //" >artifacts/sha-256.txt
347+
348+
- name: Log into Azure
349+
uses: azure/login@v1
350+
with:
351+
creds: ${{ secrets.AZURE_CREDENTIALS }}
352+
353+
- name: Install Azure Code Signing Module
354+
shell: pwsh
355+
run: |
356+
Install-Module -Name AzureCodeSigning -RequiredVersion 0.2.24 -Force `
357+
-Repository PSGallery
358+
359+
- name: Sign installers with Azure Code Signing
360+
uses: azure/[email protected]
361+
with:
362+
endpoint: https://wus2.codesigning.azure.net/
363+
code-signing-account-name: git-fundamentals-signing
364+
certificate-profile-name: git-fundamentals-windows-signing
365+
files-folder: ${{ github.workspace }}\artifacts
366+
files-folder-filter: exe
367+
file-digest: SHA256
368+
timestamp-rfc3161: http://timestamp.acs.microsoft.com
369+
timestamp-digest: SHA256
370+
371+
- name: Verify that .exe files are code-signed
372+
shell: bash
373+
run: |
374+
PATH=$PATH:"/c/Program Files (x86)/Windows Kits/10/App Certification Kit/" \
375+
signtool verify //pa artifacts/${{matrix.artifact.fileprefix}}-*.exe
376+
377+
- name: Publish ${{matrix.artifact.name}}-x86_64
378+
uses: actions/upload-artifact@v3
379+
with:
380+
name: win-${{matrix.artifact.name}}-x86_64
381+
path: artifacts
382+
# End build Windows installers

0 commit comments

Comments
 (0)