build-git-installers #246
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>" | |
permissions: | |
id-token: write # required for Azure login via OIDC | |
jobs: | |
prereqs: | |
runs-on: ubuntu-latest | |
environment: release | |
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: Determine tag to build | |
run: | | |
echo "name=${GITHUB_REF#refs/tags/}" >>$GITHUB_OUTPUT | |
echo "version=${GITHUB_REF#refs/tags/v}" >>$GITHUB_OUTPUT | |
id: tag | |
# End check prerequisites for the workflow | |
# Build and sign Debian package | |
create-linux-artifacts: | |
runs-on: ubuntu-latest | |
container: | |
image: ubuntu:16.04 # expanded security maintenance until 04/02/2026, according to https://endoflife.date/ubuntu | |
volumes: | |
# override /__e/node20 because GitHub Actions uses a version that requires too-recent glibc | |
- /tmp:/__e/node20 | |
needs: prereqs | |
environment: release | |
steps: | |
- name: Install git dependencies | |
run: | | |
set -ex | |
apt-get update -q | |
apt-get install -y -q --no-install-recommends \ | |
build-essential debsigs \ | |
tcl tk gettext asciidoc xmlto \ | |
libcurl4-gnutls-dev libpcre2-dev zlib1g-dev libexpat-dev \ | |
gnupg-agent \ | |
curl ca-certificates | |
# Install a Node.js version that works in older Ubuntu containers (read: does not require very recent glibc) | |
NODE_VERSION=v20.18.1 && | |
NODE_URL=https://unofficial-builds.nodejs.org/download/release/$NODE_VERSION/node-$NODE_VERSION-linux-x64-glibc-217.tar.gz && | |
curl -Lo /tmp/node.tar.gz $NODE_URL && | |
tar -C /__e/node20 -x --strip-components=1 -f /tmp/node.tar.gz | |
- uses: mxschmitt/action-tmate@v3 | |
with: | |
detached: true | |
- name: Install Azure CLI | |
run: | | |
curl -sL https://aka.ms/InstallAzureCLIDeb | bash | |
- name: Log into 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: Prepare for GPG signing | |
env: | |
AZURE_VAULT: ${{ secrets.AZURE_VAULT }} | |
GPG_KEY_SECRET_NAME: ${{ secrets.GPG_KEY_SECRET_NAME }} | |
GPG_PASSPHRASE_SECRET_NAME: ${{ secrets.GPG_PASSPHRASE_SECRET_NAME }} | |
GPG_KEYGRIP_SECRET_NAME: ${{ secrets.GPG_KEYGRIP_SECRET_NAME }} | |
run: | | |
# Download GPG key, passphrase, and keygrip from Azure Key Vault | |
key="$(az keyvault secret show --name "$GPG_KEY_SECRET_NAME" --vault-name "$AZURE_VAULT" --query "value" --output tsv)" | |
passphrase="$(az keyvault secret show --name "$GPG_PASSPHRASE_SECRET_NAME" --vault-name "$AZURE_VAULT" --query "value" --output tsv)" | |
keygrip="$(az keyvault secret show --name "$GPG_KEYGRIP_SECRET_NAME" --vault-name "$AZURE_VAULT" --query "value" --output tsv)" | |
# Import GPG key | |
echo "$key" | base64 -d | gpg --import --no-tty --batch --yes | |
# Configure GPG | |
echo "allow-preset-passphrase" > ~/.gnupg/gpg-agent.conf | |
# let gpg 1.4 work with gpg-agent 2.1 (see https://unix.stackexchange.com/a/407849) | |
export GPG_AGENT_INFO=${HOME}/.gnupg/S.gpg-agent:0:1 | |
echo "::notice::GPG_AGENT_INFO=$GPG_AGENT_INFO" | |
echo "GPG_AGENT_INFO=$GPG_AGENT_INFO" >>$GITHUB_ENV | |
printf '%s' "$passphrase" | | |
/usr/lib/gnupg2/gpg-preset-passphrase --preset "$keygrip" | |
- name: Clone git | |
uses: actions/checkout@v4 | |
with: | |
path: git | |
- name: Build and create Debian package | |
run: | | |
set -ex | |
die () { | |
echo "$*" >&2 | |
exit 1 | |
} | |
echo "${{ needs.prereqs.outputs.tag_version }}" >>git/version | |
make -C git GIT-VERSION-FILE | |
VERSION="${{ needs.prereqs.outputs.tag_version }}" | |
ARCH="$(dpkg-architecture -q DEB_HOST_ARCH)" | |
if test -z "$ARCH"; then | |
die "Could not determine host architecture!" | |
fi | |
PKGNAME="microsoft-git_$VERSION" | |
PKGDIR="$(dirname $(pwd))/$PKGNAME" | |
rm -rf "$PKGDIR" | |
mkdir -p "$PKGDIR" | |
DESTDIR="$PKGDIR" make -C git -j5 V=1 DEVELOPER=1 \ | |
USE_LIBPCRE=1 \ | |
USE_CURL_FOR_IMAP_SEND=1 NO_OPENSSL=1 \ | |
NO_CROSS_DIRECTORY_HARDLINKS=1 \ | |
ASCIIDOC8=1 ASCIIDOC_NO_ROFF=1 \ | |
ASCIIDOC='TZ=UTC asciidoc' \ | |
prefix=/usr/local \ | |
gitexecdir=/usr/local/lib/git-core \ | |
libexecdir=/usr/local/lib/git-core \ | |
htmldir=/usr/local/share/doc/git/html \ | |
install install-doc install-html | |
cd .. | |
mkdir "$PKGNAME/DEBIAN" | |
# Based on https://packages.ubuntu.com/xenial/vcs/git | |
cat >"$PKGNAME/DEBIAN/control" <<EOF | |
Package: microsoft-git | |
Version: $VERSION | |
Section: vcs | |
Priority: optional | |
Architecture: $ARCH | |
Depends: libcurl3-gnutls, liberror-perl, libexpat1, libpcre2-8-0, perl, perl-modules, zlib1g | |
Maintainer: GitClient <[email protected]> | |
Description: Git client built from the https://github.com/microsoft/git repository, | |
specialized in supporting monorepo scenarios. Includes the Scalar CLI. | |
EOF | |
dpkg-deb -Zxz --build "$PKGNAME" | |
# Move Debian package for later artifact upload | |
mv "$PKGNAME.deb" "$GITHUB_WORKSPACE" | |
- name: Sign Debian package | |
run: | | |
# Sign Debian package | |
version="${{ needs.prereqs.outputs.tag_version }}" | |
debsigs --sign=origin --verify --check microsoft-git_"$version".deb | |
- name: Upload artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: linux-artifacts | |
path: | | |
*.deb | |
# End build and sign Debian package | |
# Validate installers | |
validate-installers: | |
name: Validate installers | |
strategy: | |
matrix: | |
component: | |
- os: ubuntu-latest | |
artifact: linux-artifacts | |
command: git | |
runs-on: ${{ matrix.component.os }} | |
needs: [prereqs, create-linux-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: Install Linux | |
if: contains(matrix.component.artifact, 'linux') | |
run: | | |
debpath=$(find ./*.deb) | |
sudo apt install $debpath | |
- name: Install macOS | |
if: contains(matrix.component.artifact, 'macos') | |
run: | | |
# avoid letting Homebrew's `git` in `/opt/homebrew/bin` override `/usr/local/bin/git` | |
arch="$(uname -m)" | |
test arm64 != "$arch" || | |
brew uninstall git | |
pkgpath=$(find ./*universal*.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 | |
- name: Validate universal binary CPU architecture | |
if: contains(matrix.component.os, 'macos') | |
shell: bash | |
run: | | |
set -ex | |
git version --build-options >actual | |
cat actual | |
grep "cpu: $(uname -m)" actual | |
# End validate installers |