Skip to content

build-git-installers #125

build-git-installers

build-git-installers #125

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