build-git-installers #125
Workflow file for this run
This file contains 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: | |
tags: | |
- 'v[0-9]*vfs*' # matches "v<number><any characters>vfs<any characters>" | |
jobs: | |
# Check prerequisites for the workflow | |
prereqs: | |
runs-on: ubuntu-latest | |
environment: release | |
env: | |
AZ_SUB: ${{ secrets.AZURE_SUBSCRIPTION }} | |
AZ_CREDS: ${{ secrets.AZURE_CREDENTIALS }} | |
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 | |
deb_signable: ${{ steps.deb.outputs.signable }} # Whether the credentials needed to sign the .deb package are available | |
steps: | |
- name: Validate tag | |
run: | | |
echo "$GITHUB_REF" | | |
grep '^refs/tags/v2\.\(0\|[1-9][0-9]*\)\.\(0\|[1-9][0-9]*\)\.vfs\.0\.\(0\|[1-9][0-9]*\)$' || { | |
echo "::error::${GITHUB_REF#refs/tags/} is not of the form v2.<X>.<Y>.vfs.0.<W>" >&2 | |
exit 1 | |
} | |
- name: Determine tag to build | |
run: | | |
echo "name=${GITHUB_REF#refs/tags/}" >>$GITHUB_OUTPUT | |
echo "version=${GITHUB_REF#refs/tags/v}" >>$GITHUB_OUTPUT | |
id: tag | |
- name: Determine whether signing certificates are present | |
run: echo "signable=$([[ $AZ_SUB != '' && $AZ_CREDS != '' ]] && echo 'true' || echo 'false')" >>$GITHUB_OUTPUT | |
id: deb | |
- name: Clone git | |
uses: actions/checkout@v3 | |
- name: Validate the tag identified with trigger | |
run: | | |
die () { | |
echo "::error::$*" >&2 | |
exit 1 | |
} | |
# `actions/checkout` only downloads the peeled tag (i.e. the commit) | |
git fetch origin +$GITHUB_REF:$GITHUB_REF | |
# Verify that the tag is annotated | |
test $(git cat-file -t "$GITHUB_REF") == "tag" || die "Tag ${{ steps.tag.outputs.name }} is not annotated" | |
# Verify tag follows rules in GIT-VERSION-GEN (i.e., matches the specified "DEF_VER" in | |
# GIT-VERSION-FILE) and matches tag determined from trigger | |
make GIT-VERSION-FILE | |
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 }}" | |
# End check prerequisites for the workflow | |
# Build and sign Mac OSX installers & upload artifacts | |
osx_build: | |
strategy: | |
matrix: | |
arch: | |
- name: arm64 | |
runner: macos-latest-xl-arm64] | |
runs-on: ${{ matrix.arch.runner }} | |
needs: prereqs | |
env: | |
VERSION: "${{ needs.prereqs.outputs.tag_version }}" | |
steps: | |
- name: Check out repository | |
uses: actions/checkout@v3 | |
with: | |
path: 'git' | |
- name: Install Git dependencies | |
run: | | |
set -x | |
brew install automake asciidoc xmlto docbook | |
brew link --force gettext | |
- name: Build payload | |
run: | | |
die () { | |
echo "$*" >&2 | |
exit 1 | |
} | |
# Configure the environment | |
set -ex | |
PATH=/usr/local/bin:$PATH | |
export CURL_LDFLAGS=$(curl-config --libs) | |
# Write to "version" file to force match with trigger payload version | |
echo "${{ needs.prereqs.outputs.tag_version }}" >>git/version | |
# Configure the Git build to pick up gettext | |
homebrew_prefix="$(brew --prefix)" | |
cat >git/config.mak <<EOF | |
LDFLAGS = -L$homebrew_prefix/lib -L/usr/local/opt/gettext/lib | |
CFLAGS = -I$homebrew_prefix/include -I/usr/local/opt/gettext/include | |
EOF | |
# On Apple Silicon, homebrew apparently does not install a `gcc` symlink | |
test x86_64 = "$(uname -m)" || | |
echo 'CC = gcc-13' >>config.mak | |
# To make use of the catalogs... | |
export XML_CATALOG_FILES=$homebrew_prefix/etc/xml/catalog | |
make -C git -j$(sysctl -n hw.physicalcpu) GIT-VERSION-FILE dist dist-doc | |
export GIT_BUILT_FROM_COMMIT=$(gunzip -c git/git-$VERSION.tar.gz | git get-tar-commit-id) || | |
die "Could not determine commit for build" | |
# Extract tarballs | |
mkdir payload manpages | |
tar -xvf git/git-$VERSION.tar.gz -C payload | |
tar -xvf git/git-manpages-$VERSION.tar.gz -C manpages | |
# Lay out payload | |
make -C git/.github/macos-installer V=1 payload | |
# This step is necessary because we cannot use the $VERSION | |
# environment variable or the tag_version output from the prereqs | |
# job in the upload-artifact task. | |
mkdir -p build_artifacts | |
cp -R stage/git-$(uname -m)-$VERSION/ build_artifacts | |
# We keep a list of executable files because their executable bits are | |
# removed when they are zipped, and we need to re-add. | |
find build_artifacts -type f -a -perm -u=x >executable-files.txt | |
- name: Upload macOS artifacts | |
uses: actions/upload-artifact@v3 | |
with: | |
name: tmp.osx-${{ matrix.arch.name }}-build | |
path: | | |
build_artifacts | |
- name: Upload list of executable files | |
uses: actions/upload-artifact@v3 | |
with: | |
name: tmp.executable-files | |
path: | | |
executable-files.txt | |
osx_sign_payload: | |
# ESRP service requires signing to run on Windows | |
runs-on: windows-latest | |
environment: release | |
needs: osx_build | |
strategy: | |
matrix: | |
arch: [arm64] | |
steps: | |
- name: Check out repository | |
uses: actions/checkout@v3 | |
with: | |
path: 'git' | |
- name: Download unsigned build artifacts | |
uses: actions/download-artifact@v3 | |
with: | |
name: tmp.osx-${{ matrix.arch }}-build | |
path: build_artifacts | |
- name: Zip unsigned build artifacts | |
shell: pwsh | |
run: | | |
Compress-Archive -Path build_artifacts build_artifacts/build_artifacts.zip | |
cd build_artifacts | |
Get-ChildItem -Exclude build_artifacts.zip | Remove-Item -Recurse -Force | |
- uses: azure/login@v1 | |
with: | |
creds: ${{ secrets.AZURE_CREDENTIALS }} | |
- name: Set up ESRP client | |
shell: pwsh | |
env: | |
AZURE_VAULT: ${{ secrets.AZURE_VAULT }} | |
AUTH_CERT: ${{ secrets.AZURE_VAULT_AUTH_CERT_NAME }} | |
REQUEST_SIGNING_CERT: ${{ secrets.AZURE_VAULT_REQUEST_SIGNING_CERT_NAME }} | |
run: | | |
git\.github\scripts\set-up-esrp.ps1 | |
- name: Run ESRP client | |
shell: pwsh | |
env: | |
AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }} | |
APPLE_KEY_CODE: ${{ secrets.APPLE_KEY_CODE }} | |
APPLE_SIGNING_OP_CODE: ${{ secrets.APPLE_SIGNING_OPERATION_CODE }} | |
run: | | |
python git\.github\scripts\run-esrp-signing.py build_artifacts ` | |
$env:APPLE_KEY_CODE $env:APPLE_SIGNING_OP_CODE ` | |
--params 'Hardening' '--options=runtime' | |
- name: Unzip signed build artifacts | |
shell: pwsh | |
run: | | |
Expand-Archive signed/build_artifacts.zip -DestinationPath signed | |
Remove-Item signed/build_artifacts.zip | |
- name: Upload signed payload | |
uses: actions/upload-artifact@v3 | |
with: | |
name: osx-signed-${{ matrix.arch }}-payload | |
path: | | |
signed | |
osx_pack: | |
strategy: | |
matrix: | |
arch: | |
- name: arm64 | |
runner: macos-latest-xl-arm64 | |
runs-on: ${{ matrix.arch.runner }} | |
needs: [prereqs, osx_sign_payload] | |
steps: | |
- name: Check out repository | |
uses: actions/checkout@v3 | |
with: | |
path: 'git' | |
- name: Download signed artifacts | |
uses: actions/download-artifact@v3 | |
with: | |
name: osx-signed-${{ matrix.arch.name }}-payload | |
- name: Download list of executable files | |
uses: actions/download-artifact@v3 | |
with: | |
name: tmp.executable-files | |
- name: Build macOS pkg | |
env: | |
VERSION: "${{ needs.prereqs.outputs.tag_version }}" | |
run: | | |
die () { | |
echo "$*" >&2 | |
exit 1 | |
} | |
set -ex | |
# Install findutils to use gxargs below | |
brew install findutils | |
# Configure the environment | |
export CURL_LDFLAGS=$(curl-config --libs) | |
# Add executable bits and move build_artifacts into | |
# the same directory as Makefile (so that executable bits | |
# will be recognized). | |
gxargs -r -d '\n' chmod a+x <executable-files.txt | |
mv build_artifacts git/.github/macos-installer/ | |
# Create pkg | |
PATH=/usr/local/bin:$PATH \ | |
make -C git/.github/macos-installer V=1 pkg || | |
die "Build failed" | |
- name: Upload unsigned pkg | |
uses: actions/upload-artifact@v3 | |
with: | |
name: tmp.osx-${{ matrix.arch.name }}-pkg | |
path: | | |
git/.github/macos-installer/disk-image | |
osx_sign_and_notarize_pkg: | |
strategy: | |
matrix: | |
arch: [arm64] | |
# ESRP service requires signing to run on Windows | |
runs-on: windows-latest | |
environment: release | |
needs: osx_pack | |
steps: | |
- name: Check out repository | |
uses: actions/checkout@v3 | |
with: | |
path: 'git' | |
- name: Download unsigned package | |
uses: actions/download-artifact@v3 | |
with: | |
name: tmp.osx-${{ matrix.arch }}-pkg | |
path: pkg | |
- name: Zip unsigned package | |
shell: pwsh | |
run: | | |
Compress-Archive -Path pkg/*.pkg pkg/msft-git-pkg.zip | |
cd pkg | |
Get-ChildItem -Exclude msft-git-pkg.zip | Remove-Item -Recurse -Force | |
- uses: azure/login@v1 | |
with: | |
creds: ${{ secrets.AZURE_CREDENTIALS }} | |
- name: Set up ESRP client | |
shell: pwsh | |
env: | |
AZURE_VAULT: ${{ secrets.AZURE_VAULT }} | |
AUTH_CERT: ${{ secrets.AZURE_VAULT_AUTH_CERT_NAME }} | |
REQUEST_SIGNING_CERT: ${{ secrets.AZURE_VAULT_REQUEST_SIGNING_CERT_NAME }} | |
run: | | |
git\.github\scripts\set-up-esrp.ps1 | |
- name: Sign package | |
shell: pwsh | |
env: | |
AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }} | |
APPLE_KEY_CODE: ${{ secrets.APPLE_KEY_CODE }} | |
APPLE_SIGNING_OP_CODE: ${{ secrets.APPLE_SIGNING_OPERATION_CODE }} | |
run: | | |
python git\.github\scripts\run-esrp-signing.py pkg $env:APPLE_KEY_CODE $env:APPLE_SIGNING_OP_CODE | |
- name: Unzip signed package | |
shell: pwsh | |
run: | | |
mkdir unsigned | |
Expand-Archive -LiteralPath signed\msft-git-pkg.zip -DestinationPath .\unsigned -Force | |
Remove-Item signed\msft-git-pkg.zip -Force | |
- name: Notarize signed package | |
shell: pwsh | |
env: | |
AZURE_AAD_ID: ${{ secrets.AZURE_AAD_ID }} | |
APPLE_KEY_CODE: ${{ secrets.APPLE_KEY_CODE }} | |
APPLE_NOTARIZATION_OP_CODE: ${{ secrets.APPLE_NOTARIZATION_OPERATION_CODE }} | |
run: | | |
python git\.github\scripts\run-esrp-signing.py unsigned $env:APPLE_KEY_CODE ` | |
$env:APPLE_NOTARIZATION_OP_CODE --params 'BundleId' 'com.microsoft.git' | |
- name: Upload signed and notarized pkg | |
uses: actions/upload-artifact@v3 | |
with: | |
name: osx-signed-${{ matrix.arch }}-pkg | |
path: | | |
signed | |
osx_publish_dmg: | |
strategy: | |
matrix: | |
arch: | |
- name: arm64 | |
runner: macos-latest-xl-arm64 | |
runs-on: ${{ matrix.arch.runner }} | |
needs: [prereqs, osx_sign_and_notarize_pkg] | |
steps: | |
- name: Check out repository | |
uses: actions/checkout@v3 | |
with: | |
path: 'git' | |
- name: Download signed package | |
uses: actions/download-artifact@v3 | |
with: | |
name: osx-signed-${{ matrix.arch.name }}-pkg | |
path: disk-image | |
- name: Build macOS disk image | |
env: | |
VERSION: "${{ needs.prereqs.outputs.tag_version }}" | |
run: | | |
die () { | |
echo "$*" >&2 | |
exit 1 | |
} | |
set -ex | |
# Move disk-image into the same directory as Makefile | |
mv disk-image git/.github/macos-installer/ | |
PATH=/usr/local/bin:$PATH \ | |
make -C git/.github/macos-installer V=1 image || die "Build failed" | |
- name: Publish disk image | |
uses: actions/upload-artifact@v3 | |
with: | |
name: osx-${{ matrix.arch.name }}-dmg | |
path: git/.github/macos-installer/*.dmg | |
# End build and sign Mac OSX installers | |
# Validate installers | |
validate-installers: | |
name: Validate installers | |
strategy: | |
matrix: | |
component: | |
- os: macos-latest-xl-arm64 | |
artifact: osx-signed-arm64-pkg | |
command: git | |
runs-on: ${{ matrix.component.os }} | |
needs: [prereqs, osx_publish_dmg] | |
steps: | |
- name: Download artifacts | |
uses: actions/download-artifact@v3 | |
with: | |
name: ${{ matrix.component.artifact }} | |
- name: Install Windows | |
if: contains(matrix.component.os, 'windows') | |
shell: pwsh | |
run: | | |
$exePath = Get-ChildItem -Path ./*.exe | %{$_.FullName} | |
Start-Process -Wait -FilePath "$exePath" -ArgumentList "/SILENT /VERYSILENT /NORESTART /SUPPRESSMSGBOXES /ALLOWDOWNGRADE=1" | |
- name: Install Linux | |
if: contains(matrix.component.os, 'ubuntu') | |
run: | | |
debpath=$(find ./*.deb) | |
sudo apt install $debpath | |
- name: Install macOS | |
if: contains(matrix.component.os, 'macos') | |
run: | | |
pkgpath=$(find ./*.pkg) | |
sudo installer -pkg $pkgpath -target / | |
- name: Validate | |
shell: bash | |
run: | | |
"${{ matrix.component.command }}" --version | sed 's/git version //' >actual | |
echo ${{ needs.prereqs.outputs.tag_version }} >expect | |
cmp expect actual || exit 1 | |
# End validate installers |