Build and deploy mingw-w64-git-lfs #522
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-and-deploy | |
run-name: Build${{ inputs.build_only == '' && ' and deploy' || '' }} ${{ !startsWith(inputs.package, 'mingw-w64-') && inputs.repo != 'MSYS2-packages' && inputs.package != 'git-extra' && inputs.package != 'git-for-windows-keyring' && 'mingw-w64-' || '' }}${{ inputs.package }}${{ inputs.architecture && format(' ({0})', inputs.architecture) || '' }} | |
on: | |
workflow_dispatch: | |
inputs: | |
package: | |
description: 'The package to build' | |
required: true | |
build_only: | |
description: 'Skip deployment (if non-empty)' | |
required: false | |
repo: | |
description: 'The repo containing the package definition' | |
required: true | |
ref: | |
description: 'The ref containing the package definition' | |
required: true | |
architecture: | |
description: 'The architecture to build for (only for MSYS packages and all arm64 builds)' | |
required: false | |
actor: | |
description: The GitHub user on whose behalf this workflow is run | |
required: false | |
env: | |
PACKAGE_TO_BUILD: "${{ github.event.inputs.package }}" | |
BUILD_ONLY: "${{ github.event.inputs.build_only }}" | |
OWNER: "git-for-windows" | |
REPO: "${{ github.event.inputs.repo }}" | |
REF: "${{ github.event.inputs.ref }}" | |
ARCHITECTURE: "${{ github.event.inputs.architecture }}" | |
GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback" | |
ACTOR: "${{ github.event.inputs.actor || github.triggering_actor }}" | |
CREATE_CHECK_RUN: true | |
jobs: | |
build: | |
runs-on: ${{ github.event.inputs.architecture == 'aarch64' && fromJSON('["Windows", "ARM64"]') || 'windows-latest' }} | |
steps: | |
- uses: actions/checkout@v4 | |
# Since we want to operate on _another_ repository, we sadly cannot use: | |
# | |
# permissions: | |
# checks: write | |
# | |
# Therefore, we registered a GitHub App and stored the data required to | |
# act as that App in repository secrets `GH_APP_ID`, `GH_APP_PRIVATE_KEY`. | |
- name: Mirror Check Run to ${{ env.OWNER }}/${{ env.REPO }} | |
if: env.CREATE_CHECK_RUN != 'false' | |
uses: ./.github/actions/check-run-action | |
with: | |
app-id: ${{ secrets.GH_APP_ID }} | |
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} | |
owner: ${{ env.OWNER }} | |
repo: ${{ env.REPO }} | |
rev: ${{ env.REF }} | |
check-run-name: "${{ env.BUILD_ONLY && 'build' || 'deploy' }}${{ env.ARCHITECTURE && format('_{0}', env.ARCHITECTURE) || '' }}" | |
title: "Build${{ !env.BUILD_ONLY && ' and deploy' || '' }} ${{ env.PACKAGE_TO_BUILD }}" | |
summary: "${{ env.BUILD_ONLY && 'Building' || 'Deploying' }} ${{ env.PACKAGE_TO_BUILD }}" | |
text: "For details, see [this run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id}})." | |
details-url: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id}}" | |
- name: Identify actor | |
id: actor | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const githubApiRequest = require('./github-api-request') | |
const answer = await githubApiRequest( | |
console, | |
'${{ secrets.GITHUB_TOKEN }}', | |
'GET', | |
`/users/${process.env.ACTOR}` | |
) | |
core.setOutput('name', answer.name) | |
core.setOutput('email', answer.email || `${process.env.ACTOR}@users.noreply.github.com`) | |
- name: Configure build | |
shell: bash | |
run: | | |
USER_NAME="${{ steps.actor.outputs.name }}" && | |
USER_EMAIL="${{ steps.actor.outputs.email }}" && | |
HOME="${{ runner.temp }}\\home" && | |
echo "HOME=$HOME" >>$GITHUB_ENV && | |
mkdir -p "$HOME" && | |
git config --global user.name "$USER_NAME" && | |
git config --global user.email "$USER_EMAIL" && | |
echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV && | |
if test MSYS2-packages != "$REPO" && | |
test git-extra != "$PACKAGE_TO_BUILD" && | |
test git-for-windows-keyring != "$PACKAGE_TO_BUILD" && | |
test "z${PACKAGE_TO_BUILD#mingw-w64-}" = "z$PACKAGE_TO_BUILD" | |
then | |
echo "PACKAGE_TO_BUILD=mingw-w64-$PACKAGE_TO_BUILD" >>$GITHUB_ENV | |
fi | |
- name: Download Git for Windows SDK | |
uses: git-for-windows/setup-git-for-windows-sdk@v1 | |
id: setup-sdk | |
with: | |
flavor: ${{ env.PACKAGE_TO_BUILD == 'mingw-w64-git' && 'build-installers' || 'full' }} | |
architecture: ${{ env.ARCHITECTURE || 'x86_64' }} | |
msys: ${{ env.REPO == 'MSYS2-packages' || env.PACKAGE_TO_BUILD == 'git-for-windows-keyring' }} | |
- name: work around curl v8.11.0-1 problem | |
if: env.PACKAGE_TO_BUILD == 'curl' && env. REF == 'd58b04ae4163fe6c6c25b330bea0930d7bb627ac' | |
shell: bash | |
run: | | |
# `git fetch` does not work with that libcurl version. For details, | |
# see https://github.com/git-for-windows/MSYS2-packages/pull/199 | |
test ! -f /var/lib/pacman/local/libcurl-8.11.0-1/desc || | |
for pkg in libcurl curl | |
do | |
case "$ARCHITECTURE" in | |
i686) url=https://wingit.blob.core.windows.net/i686/$pkg-8.10.1-1-i686.pkg.tar.xz;; | |
x86_64) url=https://wingit.blob.core.windows.net/x86-64/$pkg-8.10.1-1-x86_64.pkg.tar.xz;; | |
esac | |
for suffix in '' .sig | |
do | |
curl --retry 5 -fLO $url$suffix || exit 1 | |
done | |
pacman -U --noconfirm ${url##*/} || exit 1 | |
done | |
# Sadly, this does not work because the Pacman repository's index only | |
# ever lists the latest package version: | |
# pacman -S --noconfirm libcurl=8.10.1-1 curl=8.10.1-1 | |
- name: Clone ${{ env.REPO }} | |
shell: bash | |
run: | | |
mkdir -p /usr/src && | |
git init -b main /usr/src/$REPO && | |
git -C /usr/src/$REPO remote add origin "https://github.com/$OWNER/$REPO" && | |
git -C /usr/src/$REPO fetch --depth 1 origin $REF && | |
git -C /usr/src/$REPO reset --hard FETCH_HEAD | |
- name: check if the package was already deployed | |
shell: bash | |
run: | | |
./update-scripts/ensure-not-yet-deployed.sh${{ env.ARCHITECTURE != '' && format(' --architecture={0}', env.ARCHITECTURE) || '' }} "/usr/src/$REPO/$PACKAGE_TO_BUILD" | |
- name: Clone build-extra (unless cloned already) | |
if: env.REPO != 'build-extra' | |
shell: bash | |
run: git clone --depth 1 --single-branch -b main https://github.com/git-for-windows/build-extra /usr/src/build-extra | |
- name: update the SDK ("pacman -Syyu") | |
timeout-minutes: 20 | |
shell: powershell | |
run: | | |
& ("${{ steps.setup-sdk.outputs.result }}\update-via-pacman.ps1") | |
- name: rebase `.dll` base addresses | |
if: env.ARCHITECTURE == 'i686' | |
shell: powershell | |
run: | | |
if (Test-Path D:\git-sdk-32-full -PathType Container) { | |
cd D:\git-sdk-32-full | |
} else { | |
cd C:\git-sdk-32-full | |
} | |
if (!$?) { exit(1); } | |
$env:MSYSTEM = "MINGW32" | |
$env:PATH = "$(Get-Location)\usr\bin;" + $env:PATH | |
$env:MSYS2_PATH_TYPE = "minimal" | |
# Disable pacman's post-transaction hook that would mess everything up, if it exists | |
sh.exe -lc "set -x && rm -f /usr/share/libalpm/hooks/rebase.hook" | |
sh.exe -lc "set -x && find /usr/lib/perl5/*_perl -name \*.dll >perl-dlls.txt" | |
type perl-dlls.txt | |
dash -x /usr/bin/rebaseall -p -T perl-dlls.txt | |
# Work around for: | |
# - address space needed by 'Cwd.dll' is already occupied | |
# - address space needed by 'Dumper.dll' is already occupied | |
# etc | |
bash -lc "set -x && rebase -b 0x61500000 /usr/lib/perl5/core_perl/auto/*/{*,*/*}.dll" | |
# Work around for: | |
# - address space needed by 'Cwd.dll' is already occupied | |
bash -lc "set -x && rebase -v -b 0x63f00000 /usr/lib/perl5/core_perl/auto/Cwd/Cwd.dll" | |
# verify the base address | |
bash -lc "set -x && rebase -v -i /usr/lib/perl5/core_perl/auto/Cwd/Cwd.dll" | |
- name: Get GPG key(s) | |
timeout-minutes: 5 | |
shell: bash | |
env: | |
CARCH: x86_64 # dummy, to allow sourcing cv2pdb's PKGBUILD as-is | |
run: | | |
cd "/usr/src/$REPO/$PACKAGE_TO_BUILD" && | |
. PKGBUILD && | |
for key in "${validpgpkeys[@]}" 57759F748D223F034D8BE870BB3AA74136C569BB | |
do | |
gpg $GPG_OPTIONS --recv-keys --batch --yes --keyserver hkp://keyserver.ubuntu.com "$key" && | |
echo "$key:6:" | gpg $GPG_OPTIONS --import-ownertrust || | |
exit 1 | |
done | |
- name: Prepare home directory for GPG signing | |
if: env.GPGKEY != '' | |
shell: bash | |
run: | | |
echo '${{secrets.PRIVGPGKEY}}' | tr % '\n' | gpg $GPG_OPTIONS --import && | |
mkdir -p "$HOME" && | |
git config --global gpg.program "/usr/src/build-extra/gnupg-with-gpgkey.sh" && | |
info="$(gpg --list-keys --with-colons "${GPGKEY%% *}" | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" && | |
git config --global user.name "${info% <*}" && | |
git config --global user.email "<${info#*<}" | |
echo "PACKAGER=$info" >>$GITHUB_ENV | |
env: | |
GPGKEY: ${{secrets.GPGKEY}} | |
- name: Prepare home directory for code-signing | |
if: env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' | |
env: | |
CODESIGN_P12: ${{secrets.CODESIGN_P12}} | |
CODESIGN_PASS: ${{secrets.CODESIGN_PASS}} | |
shell: bash | |
run: | | |
mkdir -p "$HOME"/.sig && | |
echo "$CODESIGN_P12" | tr % '\n' | base64 -d >"$HOME"/.sig/codesign.p12 && | |
echo "$CODESIGN_PASS" >"$HOME"/.sig/codesign.pass | |
git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' | |
echo "SIGNTOOL=git signtool" >>$GITHUB_ENV | |
- name: Build ${{env.PACKAGE_TO_BUILD}} | |
timeout-minutes: ${{ env.PACKAGE_TO_BUILD== 'mingw-w64-llvm' && 360 || 150 }} | |
env: | |
GPGKEY: ${{secrets.GPGKEY}} | |
MAKEPKG: ${{ env.REPO != 'MSYS2-packages' && env.PACKAGE_TO_BUILD != 'git-for-windows-keyring' && 'makepkg-mingw' || 'makepkg' }} | |
shell: bash | |
run: | | |
set -x && | |
# Restrict `PATH` to MSYS2 | |
MSYS2_PATH_TYPE=minimal && | |
. /etc/profile && | |
dir="$(cygpath -au artifacts)" && | |
mkdir -p "$dir" && | |
case "$ARCHITECTURE" in | |
aarch64) | |
GIT_EXE="/clangarm64/bin/git.exe" | |
BUILD_SRC= | |
;; | |
*) | |
GIT_EXE="/mingw64/bin/git.exe" | |
BUILD_SRC="YesPlease" | |
;; | |
esac && | |
{ | |
test -f /usr/bin/git || | |
printf '#!/bin/sh\n\nexec '$GIT_EXE' "$@"\n' >/usr/bin/git | |
} && | |
MINGW_ARCHS_TO_BUILD=$( | |
case "$ARCHITECTURE,$PACKAGE_TO_BUILD" in | |
aarch64,*) echo "clangarm64";; | |
*,mingw-w64-wintoast) echo "mingw32 mingw64 clangarm64";; # We're (cross-)compiling via Visual Studio | |
*,mingw-w64-git-credential-manager) echo "mingw32 mingw64 clangarm64";; # We're downloading the pre-built x86 artifacts and using them for all three platforms | |
*,mingw-w64-git-lfs) echo "mingw32 mingw64 clangarm64";; # We're downloading the pre-built artifacts from Git LFS' official release page | |
*) echo "mingw32 mingw64";; | |
esac | |
) | |
cd "/usr/src/$REPO/$PACKAGE_TO_BUILD" && | |
MAKEFLAGS=-j6 PKGEXT='.pkg.tar.xz' MINGW_ARCH=$MINGW_ARCHS_TO_BUILD $MAKEPKG -s --noconfirm && | |
cp *.pkg.tar* "$dir/" && | |
if test -n "$BUILD_SRC" | |
then | |
MAKEFLAGS=-j6 SRCEXT='.src.tar.gz' MINGW_ARCH=mingw64 $MAKEPKG --allsource && | |
cp *.src.tar* "$dir/" | |
fi && | |
# Ensure that the Git worktree is still clean | |
ls -la && | |
if ! git update-index --ignore-submodules --refresh || | |
! git diff-files --ignore-submodules || | |
! git diff-index --cached --ignore-submodules HEAD | |
then | |
echo "::error::Uncommitted changes after build!" >&2 | |
git diff | |
exit 1 | |
fi | |
- name: update check-run | |
if: env.CREATE_CHECK_RUN != 'false' | |
uses: ./.github/actions/check-run-action | |
with: | |
app-id: ${{ secrets.GH_APP_ID }} | |
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} | |
append-text: 'The build was successful!' | |
- name: Upload artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: artifacts | |
path: artifacts | |
- name: Prepare home directory for deploying to the Pacman repository | |
if: env.BUILD_ONLY != 'true' && env.AZURE_BLOBS_TOKEN != '' | |
env: | |
AZURE_BLOBS_TOKEN: ${{secrets.AZURE_BLOBS_TOKEN}} | |
shell: bash | |
run: | | |
echo "::add-mask::$(echo "$AZURE_BLOBS_TOKEN" | base64 -w 0)" && | |
echo "$AZURE_BLOBS_TOKEN" >"$HOME"/.azure-blobs-token | |
- name: ${{ env.BUILD_ONLY == 'true' && 'Test-deploy' || 'Deploy' }} Pacman packages | |
if: env.BUILD_ONLY == 'true' || env.AZURE_BLOBS_TOKEN != '' | |
shell: bash | |
env: | |
GPGKEY: ${{secrets.GPGKEY}} | |
PACMANDRYRUN: ${{env.BUILD_ONLY}} | |
AZURE_BLOBS_TOKEN: ${{secrets.AZURE_BLOBS_TOKEN}} | |
run: /usr/src/build-extra/pacman-helper.sh quick_add artifacts/* | |
- name: Clean up temporary files | |
if: always() | |
shell: bash | |
run: | | |
gpgconf --kill dirmngr && | |
gpgconf --kill gpg-agent && | |
{ rm -rf "$HOME" || echo "Gracefully leaving files undeleted" >&2; } | |
- name: mark check run as completed | |
if: env.CREATE_CHECK_RUN != 'false' && always() | |
uses: ./.github/actions/check-run-action | |
with: | |
app-id: ${{ secrets.GH_APP_ID }} | |
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} | |
append-text: "${{ job.status == 'success' && 'Done!' || format('Completed: {0}', job.status) }}." | |
conclusion: ${{ job.status }} |