Skip to content

chore: bump prebuilt -> d3cc49d (v1.3.65 binaries + staged installers) #18

chore: bump prebuilt -> d3cc49d (v1.3.65 binaries + staged installers)

chore: bump prebuilt -> d3cc49d (v1.3.65 binaries + staged installers) #18

name: Linux Integration Test
# Runs the full install + smoke-test suite inside per-distro containers to prove
# the two-family model (glibc floor + static musl) covers all mainstream Linux:
# RHEL/Rocky 8/9/10 (UBI, dnf) · Debian/Ubuntu (apt) · Alpine (apk, musl)
# Selection keys off libc, not distro name, so glibc distros share one artifact
# set and Alpine uses the musl one.
#
# Coverage by trigger:
# - push / pull_request → rhel-9 + debian-12 (fast glibc baseline)
# - weekly schedule → all: rhel 8/9/10 + debian + alpine
# - manual dispatch → choose profile + distros (8,9,10,debian,alpine,all)
# Least-privilege default; jobs override this where they need more.
permissions:
contents: read
on:
push:
branches: [main]
paths:
- ci/Dockerfile.linux-test
- ci/Dockerfile.debian-test
- ci/Dockerfile.alpine-test
- ci/linux-test-entrypoint.sh
- scripts/internal/install-cli.sh
- scripts/launch.sh
- tests/run-tests.sh
- scripts/internal/install-mode.sh
- tools/**
pull_request:
branches: [main]
paths:
- ci/Dockerfile.linux-test
- ci/Dockerfile.debian-test
- ci/Dockerfile.alpine-test
- ci/linux-test-entrypoint.sh
- scripts/internal/install-cli.sh
- scripts/launch.sh
- tests/run-tests.sh
- scripts/internal/install-mode.sh
- tools/**
schedule:
- cron: '0 7 * * 1'
workflow_dispatch:
inputs:
profile:
description: 'Install profile'
required: false
default: 'cpp-dev'
type: choice
options: [minimal, cpp-dev, devops, full]
distros:
description: 'Which distros (comma list: 8,9,10,debian,alpine — or "all")'
required: false
default: 'all'
concurrency:
group: linux-integration-${{ github.ref }}
cancel-in-progress: false
jobs:
# Pick the distro matrix from the trigger. Each entry carries the base image
# and the Dockerfile that knows that distro's package manager.
set-matrix:
name: Select distro matrix
runs-on: ubuntu-latest
outputs:
include: ${{ steps.pick.outputs.include }}
steps:
- id: pick
env:
EVENT: ${{ github.event_name }}
DISTROS: ${{ github.event.inputs.distros }}
run: |
r8='{"distro":"rhel-8","image":"registry.access.redhat.com/ubi8/ubi:8.10","dockerfile":"ci/Dockerfile.linux-test"}'
r9='{"distro":"rhel-9","image":"registry.access.redhat.com/ubi9/ubi:9.5","dockerfile":"ci/Dockerfile.linux-test"}'
r10='{"distro":"rhel-10","image":"registry.access.redhat.com/ubi10/ubi:10.0","dockerfile":"ci/Dockerfile.linux-test"}'
deb='{"distro":"debian-12","image":"debian:12","dockerfile":"ci/Dockerfile.debian-test"}'
alp='{"distro":"alpine-3.21","image":"alpine:3.21","dockerfile":"ci/Dockerfile.alpine-test"}'
case "$EVENT" in
schedule)
sel="$r8,$r9,$r10,$deb,$alp" ;;
workflow_dispatch)
case "${DISTROS:-all}" in
all|"") sel="$r8,$r9,$r10,$deb,$alp" ;;
*)
sel=""
[[ ",$DISTROS," == *",8,"* ]] && sel="$sel${sel:+,}$r8"
[[ ",$DISTROS," == *",9,"* ]] && sel="$sel${sel:+,}$r9"
[[ ",$DISTROS," == *",10,"* ]] && sel="$sel${sel:+,}$r10"
[[ ",$DISTROS," == *",debian,"* ]] && sel="$sel${sel:+,}$deb"
[[ ",$DISTROS," == *",alpine,"* ]] && sel="$sel${sel:+,}$alp"
[[ -z "$sel" ]] && sel="$r9" ;;
esac ;;
*)
# push / pull_request → glibc baseline: rhel-9 + debian-12
sel="$r9,$deb" ;;
esac
echo "include=[$sel]" >> "$GITHUB_OUTPUT"
echo "Selected matrix: [$sel]"
test:
name: ${{ matrix.distro }} integration
needs: set-matrix
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.set-matrix.outputs.include) }}
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
lfs: true
- name: Init prebuilt submodule (sparse + blobless)
run: |
set -uo pipefail
# prebuilt is ~10 GB (all OS variants: grpc Windows, dotnet, every
# LLVM build, ...). A Linux integration run only needs a handful of
# tool dirs, so do a blobless partial clone + cone sparse-checkout of
# just those. Falls back to a full submodule checkout on any error so
# this optimization can never wedge the run.
URL=$(git config -f .gitmodules submodule.prebuilt.url)
SHA=$(git ls-tree HEAD prebuilt | awk '{print $3}')
echo "prebuilt ${SHA} (sparse) from ${URL}"
rm -rf prebuilt .git/modules/prebuilt
if git clone --filter=blob:none --no-checkout "${URL}" prebuilt \
&& git -C prebuilt sparse-checkout set --cone \
bin \
toolchains/llvm toolchains/lcov toolchains/ninja \
build-tools/cmake languages/python lib/zlib \
dev-tools/conan dev-tools/sqlite frameworks/grpc \
&& git -C prebuilt checkout -q "${SHA}"; then
echo "sparse prebuilt OK ($(du -sh prebuilt | cut -f1))"
else
echo "sparse checkout failed — falling back to full submodule update" >&2
rm -rf prebuilt .git/modules/prebuilt
git submodule update --init --depth 1 prebuilt
fi
git -C prebuilt lfs pull 2>/dev/null || true
- name: Init tools submodule
run: git submodule update --init tools
- name: Build test image (${{ matrix.distro }})
run: |
# Pass both ARG names; each Dockerfile reads the one it declares
# (UBI_IMAGE for the RHEL image, BASE_IMAGE for debian/alpine).
docker build -f ${{ matrix.dockerfile }} \
--build-arg UBI_IMAGE=${{ matrix.image }} \
--build-arg BASE_IMAGE=${{ matrix.image }} \
-t airgap-devkit-test:${{ matrix.distro }} .
- name: Run install + smoke tests
env:
PROFILE_INPUT: ${{ github.event.inputs.profile || 'cpp-dev' }}
run: |
PROFILE="$PROFILE_INPUT"
case "$PROFILE" in
minimal|cpp-dev|devops|full) ;;
*) echo "Invalid profile: $PROFILE"; exit 1 ;;
esac
echo "Running ${{ matrix.distro }} integration test — profile: $PROFILE"
docker run --rm -e DEVKIT_PROFILE="$PROFILE" airgap-devkit-test:${{ matrix.distro }}