mirror of
https://github.com/qmk/qmk_firmware.git
synced 2026-10-01 06:19:16 +02:00
Bootstrap: environmental sanitisation, package install robustness (#26433)
* Sanitise more. * Let's brute-force Gentoo prep. * Quiet, Gentoo. * Intel macOS, `brew` unsupported. * Intel macOS, `brew` unsupported. * Throttle. * Apparently there's a free `macos-26-intel` runner. * More safety. * More safety.
This commit is contained in:
@@ -83,32 +83,34 @@ jobs:
|
|||||||
- name: Install base dependencies
|
- name: Install base dependencies
|
||||||
run: |
|
run: |
|
||||||
# Attempt to run the package installation up to 10 times to mitigate transient network issues
|
# Attempt to run the package installation up to 10 times to mitigate transient network issues
|
||||||
|
ok=''
|
||||||
for n in $(seq 1 10); do
|
for n in $(seq 1 10); do
|
||||||
{
|
{
|
||||||
echo "Attempt #$n of 10 to install base dependencies:"
|
echo "Attempt #$n of 10 to install base dependencies:"
|
||||||
case "${{ matrix.distribution }}" in
|
case "${{ matrix.distribution }}" in
|
||||||
*ubuntu*|*debian*)
|
*ubuntu*|*debian*)
|
||||||
apt-get update
|
apt-get update &&
|
||||||
apt-get install -y sudo git passwd
|
apt-get install -y sudo git passwd
|
||||||
;;
|
;;
|
||||||
*fedora*|*rockylinux*|*almalinux*)
|
*fedora*|*rockylinux*|*almalinux*)
|
||||||
dnf install -y sudo git passwd findutils # findutils=xargs
|
dnf install -y sudo git passwd findutils # findutils=xargs
|
||||||
;;
|
;;
|
||||||
*suse*)
|
*suse*)
|
||||||
zypper --non-interactive refresh
|
zypper --non-interactive refresh &&
|
||||||
zypper --non-interactive install sudo git shadow findutils tar # findutils=xargs
|
zypper --non-interactive install sudo git shadow findutils tar # findutils=xargs
|
||||||
;;
|
;;
|
||||||
*gentoo*)
|
*gentoo*)
|
||||||
emaint sync
|
{ emaint sync -a || emerge --sync --quiet || emerge-webrsync -q ; } &&
|
||||||
emerge --noreplace --ask=n sudo dev-vcs/git shadow findutils # findutils=xargs
|
emerge --noreplace --ask=n sudo dev-vcs/git shadow findutils # findutils=xargs
|
||||||
;;
|
;;
|
||||||
*archlinux*|*cachyos*|*manjaro*)
|
*archlinux*|*cachyos*|*manjaro*)
|
||||||
pacman -Syu --noconfirm
|
pacman -Syu --noconfirm &&
|
||||||
pacman -S --noconfirm sudo git
|
pacman -S --noconfirm sudo git
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
} && break || sleep 10
|
} && { ok=1; break ; } || sleep 10
|
||||||
done
|
done
|
||||||
|
[ -n "$ok" ] || exit 1
|
||||||
|
|
||||||
# Fix PAM configuration for sudo in containers
|
# Fix PAM configuration for sudo in containers
|
||||||
# Fix /etc/shadow permissions - common issue in container environments
|
# Fix /etc/shadow permissions - common issue in container environments
|
||||||
@@ -196,10 +198,21 @@ jobs:
|
|||||||
- macos-15 # Apple Silicon ARM64
|
- macos-15 # Apple Silicon ARM64
|
||||||
- macos-15-intel # Intel x64
|
- macos-15-intel # Intel x64
|
||||||
- macos-26 # Apple Silicon ARM64
|
- macos-26 # Apple Silicon ARM64
|
||||||
|
- macos-26-intel # Intel x64
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Install base dependencies
|
||||||
|
run: |
|
||||||
|
# Attempt to run the brew update up to 10 times to mitigate transient issues
|
||||||
|
for n in $(seq 1 10); do
|
||||||
|
brew update && exit 0
|
||||||
|
brew update-reset || true
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
exit 1
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v7
|
uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
|
|||||||
+81
-12
@@ -43,6 +43,49 @@
|
|||||||
# corrupt captured output and break pattern matching throughout this script.
|
# corrupt captured output and break pattern matching throughout this script.
|
||||||
unset GREP_OPTIONS GREP_COLOR GREP_COLORS
|
unset GREP_OPTIONS GREP_COLOR GREP_COLORS
|
||||||
|
|
||||||
|
# Force the C locale so `tr`/`grep`/`sed`/`sort` behave the same on every
|
||||||
|
# system, and clear other variables which alter tool behavior.
|
||||||
|
export LC_ALL=C
|
||||||
|
unset CDPATH POSIXLY_CORRECT TAR_OPTIONS
|
||||||
|
|
||||||
|
# Drop out of any inherited Python venv; `deactivate` doesn't exist in this
|
||||||
|
# process, so strip its $PATH entries and marker variables by hand.
|
||||||
|
if [ -n "${VIRTUAL_ENV:-}" ]; then
|
||||||
|
clean_path=''
|
||||||
|
old_ifs="${IFS}"
|
||||||
|
IFS=':'
|
||||||
|
for path_entry in $PATH; do
|
||||||
|
case "$path_entry" in
|
||||||
|
"$VIRTUAL_ENV"/bin | "$VIRTUAL_ENV"/Scripts) ;;
|
||||||
|
*) clean_path="${clean_path:+${clean_path}:}${path_entry}" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
IFS="${old_ifs}"
|
||||||
|
PATH="${clean_path}"
|
||||||
|
export PATH
|
||||||
|
unset VIRTUAL_ENV VIRTUAL_ENV_PROMPT clean_path old_ifs path_entry
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Wipe all PYTHON* variables (keeping PYTHON_TARGET_VERSION, which this
|
||||||
|
# script uses) so the user's Python settings can't leak into the
|
||||||
|
# interpreters and builds managed by `uv`.
|
||||||
|
saved_python_target_version="${PYTHON_TARGET_VERSION:-}"
|
||||||
|
for env_var_name in $(env | LC_ALL=C sed -n 's/^\(PYTHON[A-Za-z0-9_]*\)=.*/\1/p'); do
|
||||||
|
unset "$env_var_name" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
[ -z "$saved_python_target_version" ] || export PYTHON_TARGET_VERSION="$saved_python_target_version"
|
||||||
|
unset saved_python_target_version env_var_name
|
||||||
|
export PYTHONNOUSERSITE=1
|
||||||
|
|
||||||
|
# Clear conda/pip/uv overrides which would affect dependency resolution or
|
||||||
|
# builds; proxy, TLS, and index/mirror variables stay for corporate networks.
|
||||||
|
unset CONDA_PREFIX CONDA_DEFAULT_ENV
|
||||||
|
unset PIP_REQUIRE_VIRTUALENV PIP_TARGET PIP_PREFIX PIP_USER
|
||||||
|
unset SETUPTOOLS_USE_DISTUTILS
|
||||||
|
unset UV_NO_BUILD_ISOLATION UV_OFFLINE UV_NO_INDEX \
|
||||||
|
UV_CONSTRAINT UV_BUILD_CONSTRAINT UV_OVERRIDE \
|
||||||
|
UV_SYSTEM_PYTHON UV_NO_MANAGED_PYTHON
|
||||||
|
|
||||||
BOOTSTRAP_TMPDIR="$(mktemp -d /tmp/qmk-bootstrap-failure.XXXXXX)"
|
BOOTSTRAP_TMPDIR="$(mktemp -d /tmp/qmk-bootstrap-failure.XXXXXX)"
|
||||||
trap 'rm -rf "$BOOTSTRAP_TMPDIR" >/dev/null 2>&1 || true' EXIT
|
trap 'rm -rf "$BOOTSTRAP_TMPDIR" >/dev/null 2>&1 || true' EXIT
|
||||||
FAILURE_FILE="${BOOTSTRAP_TMPDIR}/fail"
|
FAILURE_FILE="${BOOTSTRAP_TMPDIR}/fail"
|
||||||
@@ -175,6 +218,15 @@ __EOT__
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_release_tag() {
|
||||||
|
# An empty tag means the GitHub API call failed, usually from rate limiting.
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
echo "Could not determine the latest $1 release." >&2
|
||||||
|
echo "If GitHub API rate limits are the cause, set GITHUB_TOKEN to raise them." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
fn_os() {
|
fn_os() {
|
||||||
local os_name=$(echo ${1:-} | tr 'A-Z' 'a-z')
|
local os_name=$(echo ${1:-} | tr 'A-Z' 'a-z')
|
||||||
if [ -z "$os_name" ]; then
|
if [ -z "$os_name" ]; then
|
||||||
@@ -285,6 +337,10 @@ __EOT__
|
|||||||
print_package_manager_deps_and_delay() {
|
print_package_manager_deps_and_delay() {
|
||||||
get_package_manager_deps | tr ' ' '\n' | sort | xargs -I'{}' echo " - {}" >&2
|
get_package_manager_deps | tr ' ' '\n' | sort | xargs -I'{}' echo " - {}" >&2
|
||||||
exit_if_execution_failed
|
exit_if_execution_failed
|
||||||
|
if [ -n "${1:-}" ]; then
|
||||||
|
echo >&2
|
||||||
|
echo "$1" >&2
|
||||||
|
fi
|
||||||
preinstall_delay || exit 1
|
preinstall_delay || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +350,11 @@ __EOT__
|
|||||||
macos)
|
macos)
|
||||||
if [ -n "$(command -v brew 2>/dev/null || true)" ]; then
|
if [ -n "$(command -v brew 2>/dev/null || true)" ]; then
|
||||||
echo "It will also install the following system packages using 'brew':" >&2
|
echo "It will also install the following system packages using 'brew':" >&2
|
||||||
print_package_manager_deps_and_delay
|
local intel_note=""
|
||||||
|
if [ "$(fn_arch)" = "X64" ]; then
|
||||||
|
intel_note="NOTE: Homebrew no longer provides pre-built packages for Intel Macs, so some of the above may be built from source. This can take a long time."
|
||||||
|
fi
|
||||||
|
print_package_manager_deps_and_delay "$intel_note"
|
||||||
|
|
||||||
brew update
|
brew update
|
||||||
|
|
||||||
@@ -308,12 +368,14 @@ __EOT__
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ -n "${existing:-}" ]; then
|
# Homebrew no longer builds Intel macOS bottles (tier 3); when a
|
||||||
brew upgrade $existing
|
# bottle is missing, retry the formula as a source build.
|
||||||
fi
|
for dep in ${existing:-}; do
|
||||||
if [ -n "${new:-}" ]; then
|
brew upgrade "$dep" || brew upgrade --build-from-source "$dep"
|
||||||
brew install $new
|
done
|
||||||
fi
|
for dep in ${new:-}; do
|
||||||
|
brew install "$dep" || brew install --build-from-source "$dep"
|
||||||
|
done
|
||||||
else
|
else
|
||||||
echo "Please install 'brew' to continue. See https://brew.sh/ for more information." >&2
|
echo "Please install 'brew' to continue. See https://brew.sh/ for more information." >&2
|
||||||
exit 1
|
exit 1
|
||||||
@@ -437,6 +499,7 @@ __EOT__
|
|||||||
install_toolchains() {
|
install_toolchains() {
|
||||||
# Get the latest toolchain release from https://github.com/qmk/qmk_toolchains
|
# Get the latest toolchain release from https://github.com/qmk/qmk_toolchains
|
||||||
local latest_toolchains_release=$(github_api_call repos/qmk/qmk_toolchains/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
local latest_toolchains_release=$(github_api_call repos/qmk/qmk_toolchains/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
||||||
|
check_release_tag qmk_toolchains "$latest_toolchains_release"
|
||||||
# Download the specific release asset with a matching keyword
|
# Download the specific release asset with a matching keyword
|
||||||
local toolchain_url=$(github_api_call repos/qmk/qmk_toolchains/releases/tags/$latest_toolchains_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep -E "qmk_toolchains-.*$(fn_os)$(fn_arch)")
|
local toolchain_url=$(github_api_call repos/qmk/qmk_toolchains/releases/tags/$latest_toolchains_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep -E "qmk_toolchains-.*$(fn_os)$(fn_arch)")
|
||||||
if [ -z "$toolchain_url" ]; then
|
if [ -z "$toolchain_url" ]; then
|
||||||
@@ -464,6 +527,7 @@ __EOT__
|
|||||||
|
|
||||||
# Get the latest flashing tools release from https://github.com/qmk/qmk_flashutils
|
# Get the latest flashing tools release from https://github.com/qmk/qmk_flashutils
|
||||||
local latest_flashutils_release=$(github_api_call repos/qmk/qmk_flashutils/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
local latest_flashutils_release=$(github_api_call repos/qmk/qmk_flashutils/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
||||||
|
check_release_tag qmk_flashutils "$latest_flashutils_release"
|
||||||
# Download the specific release asset with a matching keyword
|
# Download the specific release asset with a matching keyword
|
||||||
local flashutils_url=$(github_api_call repos/qmk/qmk_flashutils/releases/tags/$latest_flashutils_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep -E "qmk_flashutils-.*$osarchvariant")
|
local flashutils_url=$(github_api_call repos/qmk/qmk_flashutils/releases/tags/$latest_flashutils_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep -E "qmk_flashutils-.*$osarchvariant")
|
||||||
if [ -z "$flashutils_url" ]; then
|
if [ -z "$flashutils_url" ]; then
|
||||||
@@ -486,10 +550,7 @@ __EOT__
|
|||||||
install_linux_udev_rules() {
|
install_linux_udev_rules() {
|
||||||
# Get the latest qmk_udev release
|
# Get the latest qmk_udev release
|
||||||
local latest_udev_release=$(github_api_call repos/qmk/qmk_udev/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
local latest_udev_release=$(github_api_call repos/qmk/qmk_udev/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
||||||
if [ -z "$latest_udev_release" ]; then
|
check_release_tag qmk_udev "$latest_udev_release"
|
||||||
echo "Could not determine latest qmk_udev release." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "Using qmk_udev release: $latest_udev_release" >&2
|
echo "Using qmk_udev release: $latest_udev_release" >&2
|
||||||
|
|
||||||
# Download the udev rules file
|
# Download the udev rules file
|
||||||
@@ -541,6 +602,7 @@ __EOT__
|
|||||||
install_windows_drivers() {
|
install_windows_drivers() {
|
||||||
# Get the latest driver installer release from https://github.com/qmk/qmk_driver_installer
|
# Get the latest driver installer release from https://github.com/qmk/qmk_driver_installer
|
||||||
local latest_driver_installer_release=$(github_api_call repos/qmk/qmk_driver_installer/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
local latest_driver_installer_release=$(github_api_call repos/qmk/qmk_driver_installer/releases/latest - | grep -oE '"tag_name": "[^"]+' | grep -oE '[^"]+$')
|
||||||
|
check_release_tag qmk_driver_installer "$latest_driver_installer_release"
|
||||||
# Download the specific release asset
|
# Download the specific release asset
|
||||||
local driver_installer_url=$(github_api_call repos/qmk/qmk_driver_installer/releases/tags/$latest_driver_installer_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep '\.exe')
|
local driver_installer_url=$(github_api_call repos/qmk/qmk_driver_installer/releases/tags/$latest_driver_installer_release - | grep -oE '"browser_download_url": "[^"]+"' | grep -oE 'https://[^"]+' | grep '\.exe')
|
||||||
if [ -z "$driver_installer_url" ]; then
|
if [ -z "$driver_installer_url" ]; then
|
||||||
@@ -600,7 +662,14 @@ __EOT__
|
|||||||
setup_paths
|
setup_paths
|
||||||
|
|
||||||
# Work out where we want to install the distribution and tools now that `uv` is installed
|
# Work out where we want to install the distribution and tools now that `uv` is installed
|
||||||
export QMK_DISTRIB_DIR="$(posix_ish_path "${QMK_DISTRIB_DIR:-$(printf 'import platformdirs\nprint(platformdirs.user_data_dir("qmk"))' | uv_command run --quiet --python $PYTHON_TARGET_VERSION --with platformdirs -)}")"
|
export QMK_DISTRIB_DIR="$(posix_ish_path "${QMK_DISTRIB_DIR:-$(printf 'import platformdirs\nprint(platformdirs.user_data_dir("qmk"))' | uv_command run --quiet --no-project --python $PYTHON_TARGET_VERSION --with platformdirs -)}")"
|
||||||
|
|
||||||
|
# `export` masks any failure of the `uv` invocation above, so bail out here
|
||||||
|
# rather than continue with an empty directory.
|
||||||
|
if [ -z "$QMK_DISTRIB_DIR" ]; then
|
||||||
|
echo "Could not determine the QMK distribution directory." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Clear out the distrib directory if necessary
|
# Clear out the distrib directory if necessary
|
||||||
if [ -z "${SKIP_CLEAN:-}" ] || [ -z "${SKIP_QMK_TOOLCHAINS:-}" -a -z "${SKIP_QMK_FLASHUTILS:-}" ]; then
|
if [ -z "${SKIP_CLEAN:-}" ] || [ -z "${SKIP_QMK_TOOLCHAINS:-}" -a -z "${SKIP_QMK_FLASHUTILS:-}" ]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user