Skip to content

build-git-installers #243

build-git-installers

build-git-installers #243

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
- 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
eval $(gpg-agent --daemon)
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