#!/usr/bin/env bash # yams/scripts/local-ci/matrix.sh # # Simulate the Ubuntu GitHub Actions job in a Docker container. # # What it does inside the container: # 1) Configure, build, and test YAMS # 2) Install into a local prefix (inside the mounted repo) # 3) Configure, build, and test a minimal downstream consumer against find_package(Yams) # # Requirements on host: # - Docker available on PATH # - This repository checked out locally # # Example: # bash scripts/local-ci/matrix.sh # bash scripts/local-ci/matrix.sh --cmake-args "-DYAMS_ENABLE_COVERAGE=ON" # # Notes: # - The container image is built from docker/local-ci/ubuntu.Dockerfile (Ubuntu 24.04) # - macOS jobs cannot be containerized; this script targets Linux (Ubuntu) CI parity. # - EXTRA CMake args are passed via strings and expanded with 'eval' inside the container. # Only pass trusted content. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" # Defaults IMAGE_DEFAULT="yams/ci-ubuntu:24.04" DOCKERFILE_DEFAULT="${REPO_ROOT}/docker/local-ci/ubuntu.Dockerfile" REPO_DIR_DEFAULT="${REPO_ROOT}" GENERATOR_DEFAULT="Ninja" BUILD_TYPE_DEFAULT="Release" INSTALL_PREFIX_DEFAULT="/work/prefix" JOBS_DEFAULT="" # resolved inside container via nproc if empty EXTRA_CMAKE_ARGS_DEFAULT="" # e.g. '-DYAMS_USE_VCPKG=ON' CONSUMER_CMAKE_ARGS_DEFAULT="" # e.g. '-DCMAKE_VERBOSE_MAKEFILE=ON' PULL_FLAG="" usage() { cat <&2 usage exit 2;; esac done # Basic checks if ! command -v docker >/dev/null 2>&1; then echo "Error: Docker not found on PATH" >&2 exit 1 fi if [[ ! -d "${REPO_DIR}" ]]; then echo "Error: Repo directory not found: ${REPO_DIR}" >&2 exit 1 fi if [[ "${SKIP_BUILD}" != "1" ]]; then if [[ ! -f "${DOCKERFILE}" ]]; then echo "Error: Dockerfile not found: ${DOCKERFILE}" >&2 exit 1 fi echo "==> Building local CI Docker image: ${IMAGE}" docker build ${PULL_FLAG} -t "${IMAGE}" -f "${DOCKERFILE}" "${REPO_DIR}" else echo "==> Skipping image build. Using existing image: ${IMAGE}" fi # Resolve absolute repo path for mounting REPO_ABS="$(cd "${REPO_DIR}" && pwd)" echo "==> Running CI simulation in container" echo " Repo: ${REPO_ABS}" echo " Image: ${IMAGE}" echo " Generator: ${GENERATOR}" echo " Build type: ${BUILD_TYPE}" echo " Install prefix: ${INSTALL_PREFIX}" echo " Jobs: ${JOBS:-'(auto)'}" echo " Extra CMake: ${EXTRA_CMAKE_ARGS:-'(none)'}" echo " Consumer CMake: ${CONSUMER_CMAKE_ARGS:-'(none)'}" # Run CI steps in container # Pass configuration via environment variables to avoid quoting issues. docker run --rm \ -v "${REPO_ABS}:/work:rw" \ -w /work \ -e GEN="${GENERATOR}" \ -e BUILD_TYPE="${BUILD_TYPE}" \ -e INSTALL_PREFIX="${INSTALL_PREFIX}" \ -e JOBS="${JOBS}" \ -e EXTRA_CMAKE_ARGS="${EXTRA_CMAKE_ARGS}" \ -e CONSUMER_EXTRA_CMAKE_ARGS="${CONSUMER_CMAKE_ARGS}" \ "${IMAGE}" bash -lc ' set -euxo pipefail # Determine jobs inside container if not provided if [[ -z "${JOBS:-}" ]]; then if command -v nproc >/dev/null 2>&1; then JOBS="$(nproc)" else JOBS="4" fi fi # 1) Clean previous artifacts rm -rf build consumer_build "${INSTALL_PREFIX}" || true mkdir -p "${INSTALL_PREFIX}" # 2) Configure main project # Use eval to allow EXTRA_CMAKE_ARGS to inject -D definitions and other flags. eval cmake -S . -B build -G \"${GEN}\" \ -DCMAKE_BUILD_TYPE=\"${BUILD_TYPE}\" \ -DYAMS_BUILD_PROFILE=dev \ -DYAMS_BUILD_TESTS=ON \ -DCMAKE_INSTALL_PREFIX=\"${INSTALL_PREFIX}\" \ ${EXTRA_CMAKE_ARGS} # 3) Build & test main project cmake --build build -j "${JOBS}" ctest --test-dir build --output-on-failure # 4) Install main project (headers + libs + package config) cmake --install build # 5) Configure consumer project against installed prefix (if present) if [[ -d test/consumer ]]; then eval cmake -S test/consumer -B consumer_build -G \"${GEN}\" \ -DCMAKE_PREFIX_PATH=\"${INSTALL_PREFIX}\" \ ${CONSUMER_EXTRA_CMAKE_ARGS} # 6) Build & test consumer cmake --build consumer_build -j "${JOBS}" ctest --test-dir consumer_build --output-on-failure else echo "Skipping downstream consumer: directory 'test/consumer' not found." fi echo "Container CI steps completed successfully." ' echo "==> Local containerized CI completed successfully."