fixup! build-git-installers.yml: extract tag validation script #312
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: build-git-installers | |
on: | |
push: | |
branches: | |
- workflow-scripts | |
tags: | |
- 'v[0-9]*vfs*' # matches "v<number><any characters>vfs<any characters>" | |
workflow_dispatch: | |
permissions: | |
id-token: write # required for Azure login via OIDC | |
env: | |
DO_WIN_CODESIGN: ${{ secrets.WIN_CODESIGN_CERT_SECRET_NAME != '' && secrets.WIN_CODESIGN_PASS_SECRET_NAME != '' }} | |
DO_WIN_GPGSIGN: ${{ secrets.WIN_GPG_KEYGRIP_SECRET_NAME != '' && secrets.WIN_GPG_PRIVATE_SECRET_NAME != '' && secrets.WIN_GPG_PASSPHRASE_SECRET_NAME != '' }} | |
REF_OVERRIDE: refs/tags/v2.50.1.vfs.0.1 | |
jobs: | |
# Check prerequisites for the workflow | |
prereqs: | |
runs-on: ubuntu-latest | |
outputs: | |
tag_name: ${{ steps.tag.outputs.name }} # The full name of the tag, e.g. v2.32.0.vfs.0.0 | |
tag_version: ${{ steps.tag.outputs.version }} # The version number (without preceding "v"), e.g. 2.32.0.vfs.0.0 | |
steps: | |
- name: Clone git | |
uses: actions/checkout@v4 | |
- name: Validate tag | |
run: | | |
# `actions/checkout` only downloads the peeled tag (i.e. the commit) | |
git fetch origin +$REF_OVERRIDE:$REF_OVERRIDE | |
./.github/scripts/validate-tag.sh "$REF_OVERRIDE" | |
- name: Set tag/version outputs | |
run: | | |
echo "name=${REF_OVERRIDE#refs/tags/}" >>$GITHUB_OUTPUT | |
version="${REF_OVERRIDE#refs/tags/v}" | |
echo "version=$(echo "$version" | sed 's/-/./g')" >>$GITHUB_OUTPUT | |
id: tag | |
# End check prerequisites for the workflow | |
# Build Windows installers (x86_64 & aarch64; installer & portable) | |
windows_pkg: | |
environment: release | |
needs: prereqs | |
strategy: | |
fail-fast: false | |
matrix: | |
arch: | |
- name: x86_64 | |
artifact: pkg-x86_64 | |
toolchain: x86_64 | |
mingwprefix: mingw64 | |
runner: windows-2022 | |
- name: aarch64 | |
artifact: pkg-aarch64 | |
toolchain: clang-aarch64 | |
mingwprefix: clangarm64 | |
runner: windows-11-arm | |
runs-on: ${{ matrix.arch.runner }} | |
env: | |
GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback" | |
HOME: "${{github.workspace}}\\home" | |
USERPROFILE: "${{github.workspace}}\\home" | |
steps: | |
- name: Configure user | |
shell: bash | |
run: | |
USER_NAME="${{github.actor}}" && | |
USER_EMAIL="${{github.actor}}@users.noreply.github.com" && | |
mkdir -p "$HOME" && | |
./.github/scripts/configure-git-user.sh --name "$USER_NAME" --email "$USER_EMAIL" | |
echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV | |
- uses: git-for-windows/setup-git-for-windows-sdk@v1 | |
with: | |
flavor: build-installers | |
architecture: ${{ matrix.arch.name }} | |
- name: Clone build-extra | |
shell: bash | |
run: | | |
git clone --filter=blob:none --single-branch -b main https://github.com/git-for-windows/build-extra /usr/src/build-extra | |
- name: Clone git | |
shell: bash | |
run: | | |
# Since we cannot directly clone a specified tag (as we would a branch with `git clone -b <branch name>`), | |
# this clone has to be done manually (via init->fetch->reset). | |
tag_name="${{ needs.prereqs.outputs.tag_name }}" && | |
git -c init.defaultBranch=main init && | |
git remote add -f origin https://github.com/git-for-windows/git && | |
git fetch "https://github.com/${{github.repository}}" refs/tags/${tag_name}:refs/tags/${tag_name} && | |
git reset --hard ${tag_name} | |
- name: Log in to Azure | |
uses: azure/login@v2 | |
with: | |
client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
- name: Download code signing secrets | |
id: codesign-secrets | |
if: env.DO_WIN_CODESIGN == 'true' | |
uses: ./.github/actions/akv-secret | |
with: | |
vault: ${{ secrets.AZURE_VAULT }} | |
secrets: | | |
${{ secrets.WIN_CODESIGN_CERT_SECRET_NAME }} base64> home/.sig/codesign.p12 | |
${{ secrets.WIN_CODESIGN_PASS_SECRET_NAME }} > home/.sig/codesign.pass | |
- name: Prepare home directory for code-signing | |
if: ${{ steps.codesign-secrets.outcome == 'success' }} | |
shell: bash | |
run: | | |
git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' | |
- name: Download GPG secrets | |
id: gpg-secrets | |
if: env.DO_WIN_GPGSIGN == 'true' | |
uses: ./.github/actions/akv-secret | |
with: | |
vault: ${{ secrets.AZURE_VAULT }} | |
secrets: | | |
${{ secrets.WIN_GPG_KEYGRIP_SECRET_NAME }} > $output:keygrip | |
${{ secrets.WIN_GPG_PRIVATE_SECRET_NAME }} base64> $output:private-key | |
${{ secrets.WIN_GPG_PASSPHRASE_SECRET_NAME }} > $output:passphrase | |
- name: Prepare home directory for GPG signing | |
if: ${{ steps.gpg-secrets.outputs.keygrip != '' && steps.gpg-secrets.outputs.private-key != '' }} | |
shell: bash | |
run: | | |
# This section ensures that the identity for the GPG key matches the git user identity, otherwise | |
# signing will fail | |
# Import the GPG private key | |
echo -n '${{ steps.gpg-secrets.outputs.private-key }}' | gpg $GPG_OPTIONS --import && | |
info="$(gpg --list-keys --with-colons '${{ steps.gpg-secrets.outputs.keygrip }}' | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" && | |
git config --global user.name "${info% <*}" && | |
git config --global user.email "<${info#*<}" | |
- name: Build mingw-w64-${{matrix.arch.toolchain}}-git | |
shell: bash | |
run: | | |
set -x | |
# Build the GPGKEY variable | |
export GPGKEY="${{ steps.gpg-secrets.outputs.keygrip }} --passphrase '${{ steps.gpg-secrets.outputs.passphrase }}' --yes --batch --no-tty --pinentry-mode loopback --digest-algo SHA256" && | |
# Make sure that there is a `/usr/bin/git` that can be used by `makepkg-mingw` | |
printf '#!/bin/sh\n\nexec /${{matrix.arch.mingwprefix}}/bin/git.exe "$@"\n' >/usr/bin/git && | |
# Build the package(s) | |
./.github/scripts/build-windows.sh \ | |
--arch "${{ matrix.arch.name }}" \ | |
--version "${{ needs.prereqs.outputs.tag_name }}" \ | |
--build-extra "/usr/src/build-extra" \ | |
--output "artifacts" | |
# GPG sign the packages if keygrip is available | |
if test -n "${{ steps.gpg-secrets.outputs.keygrip }}" | |
then | |
for tar in artifacts/*.tar* | |
do | |
/usr/src/build-extra/gnupg-with-gpgkey.sh --detach-sign --no-armor $tar | |
done | |
fi && | |
# Create the bundle | |
./.github/scripts/bundle-windows.sh \ | |
--version "${{ needs.prereqs.outputs.tag_name }}" \ | |
--pkg-dir "/usr/src/MINGW-packages/mingw-w64-git" \ | |
--output "$PWD/artifacts" | |
- name: Publish mingw-w64-${{matrix.arch.toolchain}}-git | |
uses: actions/upload-artifact@v4 | |
with: | |
name: "${{ matrix.arch.artifact }}" | |
path: artifacts | |
windows_artifacts: | |
environment: release | |
needs: [prereqs, windows_pkg] | |
env: | |
HOME: "${{github.workspace}}\\home" | |
strategy: | |
fail-fast: false | |
matrix: | |
arch: | |
- name: x86_64 | |
artifact: pkg-x86_64 | |
toolchain: x86_64 | |
mingwprefix: mingw64 | |
runner: windows-2022 | |
- name: aarch64 | |
artifact: pkg-aarch64 | |
toolchain: clang-aarch64 | |
mingwprefix: clangarm64 | |
runner: windows-11-arm | |
type: | |
- name: installer | |
fileprefix: Git | |
- name: portable | |
fileprefix: PortableGit | |
runs-on: ${{ matrix.arch.runner }} | |
steps: | |
- name: Download ${{ matrix.arch.artifact }} | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ matrix.arch.artifact }} | |
path: ${{ matrix.arch.artifact }} | |
- uses: git-for-windows/setup-git-for-windows-sdk@v1 | |
with: | |
flavor: build-installers | |
architecture: ${{ matrix.arch.name }} | |
- name: Clone build-extra | |
shell: bash | |
run: | | |
git clone --filter=blob:none --single-branch -b main https://github.com/git-for-windows/build-extra /usr/src/build-extra | |
- name: Log in to Azure | |
uses: azure/login@v2 | |
if: env.DO_WIN_CODESIGN == 'true' | |
with: | |
client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
- name: Check out repository (for akv-secret Action) | |
if: env.DO_WIN_CODESIGN == 'true' | |
uses: actions/checkout@v4 | |
with: | |
path: git | |
- name: Download code signing secrets | |
id: codesign-secrets | |
if: env.DO_WIN_CODESIGN == 'true' | |
uses: ./git/.github/actions/akv-secret | |
with: | |
vault: ${{ secrets.AZURE_VAULT }} | |
secrets: | | |
${{ secrets.WIN_CODESIGN_CERT_SECRET_NAME }} base64> home/.sig/codesign.p12 | |
${{ secrets.WIN_CODESIGN_PASS_SECRET_NAME }} > home/.sig/codesign.pass | |
- name: Prepare home directory for code-signing | |
if: ${{ steps.codesign-secrets.outcome == 'success' }} | |
shell: bash | |
run: | | |
git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' | |
- name: Apply installer customizations | |
shell: bash | |
run: | | |
set -x | |
./.github/scripts/customize-windows.sh \ | |
--arch "${{ matrix.arch.name }}" \ | |
--build-extra "/usr/src/build-extra" | |
- name: Build ${{matrix.type.name}} (${{matrix.arch.name}}) | |
shell: bash | |
run: | | |
set -x | |
# Build the installer, embedding PDBs | |
./.github/scripts/package-windows.sh \ | |
--arch "${{ matrix.arch.name }}" \ | |
--version "${{ needs.prereqs.outputs.tag_version }}" \ | |
--build-extra "/usr/src/build-extra" \ | |
--pkg-dir "${{ matrix.arch.artifact }}" \ | |
--type "${{ matrix.type.name }}" \ | |
--output artifacts && | |
if test portable = '${{matrix.type.name}}' && test -n "$(git config alias.signtool)" | |
then | |
git signtool artifacts/PortableGit-*.exe | |
fi && | |
openssl dgst -sha256 artifacts/${{matrix.type.fileprefix}}-*.exe | sed "s/.* //" >artifacts/sha-256.txt | |
- name: Verify that .exe files are code-signed | |
if: env.DO_WIN_CODESIGN == 'true' | |
shell: pwsh | |
run: | | |
$ret = 0 | |
$files = Get-ChildItem -Path artifacts -Filter "${{matrix.type.fileprefix}}-*.exe" | |
foreach ($file in $files) { | |
$signature = Get-AuthenticodeSignature -FilePath $file.FullName | |
if ($signature.Status -eq 'Valid') { | |
Write-Host "[ VALID ] $($file.FullName)" | |
} else { | |
Write-Host "[INVALID] $($file.FullName)" | |
Write-Host " Message: $($signature.StatusMessage)" | |
$ret = 1 | |
} | |
} | |
exit $ret | |
- name: Publish ${{matrix.type.name}}-${{matrix.arch.name}} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: win-${{matrix.type.name}}-${{matrix.arch.name}} | |
path: artifacts | |
# End build Windows installers | |
# Validate installers | |
validate-installers: | |
name: Validate installers | |
strategy: | |
matrix: | |
component: | |
- os: windows-latest | |
artifact: win-installer-x86_64 | |
command: $PROGRAMFILES\Git\cmd\git.exe | |
- os: windows-11-arm | |
artifact: win-installer-aarch64 | |
command: $PROGRAMFILES\Git\cmd\git.exe | |
runs-on: ${{ matrix.component.os }} | |
needs: [prereqs, windows_artifacts] | |
steps: | |
- name: Download artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{ matrix.component.artifact }} | |
- name: Install Windows | |
if: contains(matrix.component.artifact, 'win-installer') | |
shell: pwsh | |
run: | | |
$exePath = Get-ChildItem -Path ./*.exe | %{$_.FullName} | |
Start-Process -Wait -FilePath "$exePath" -ArgumentList "/SILENT /VERYSILENT /NORESTART /SUPPRESSMSGBOXES /ALLOWDOWNGRADE=1" | |
- name: Validate | |
shell: bash | |
run: | | |
"${{ matrix.component.command }}" --version | sed 's/git version //' >actual | |
echo "${{ needs.prereqs.outputs.tag_version }}" | sed 's/-rc/.rc/g' >expect | |
cmp expect actual || exit 1 | |
# End validate installers |