Skip to content

Build and deploy mingw-w64-git-lfs #522

Build and deploy mingw-w64-git-lfs

Build and deploy mingw-w64-git-lfs #522

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 }}