# .build.yml # # SourceHut build manifest for YAMS (single Linux target). # Key points: # - Compute version from Git ref (GIT_REF) or release channel (RELEASE_CHANNEL) at runtime; no manifest expressions. # - Persist computed version into ~/.buildenv for subsequent tasks. # - Add static build tags for search/badges. # - Gate packaging steps so they run for tag builds and for nightly/weekly channels. # - Install Conan via pipx (or venv fallback), since Debian doesn't provide python3-conan. image: debian/trixie # Other possible images: # image: ubuntu/22.04 # image: debian/stable # Static metadata for search and badges (unrelated to Git tags) tags: - linux - release - cmake - conan - yams - nightly - weekly environment: # Define consistent directories. BUILD_DIR: build/yams-release STAGE_DIR: stage # Optional: set this to "nightly" or "weekly" via scheduler/env to produce # date/week-based releases on non-tag builds. # RELEASE_CHANNEL: packages: # Build dependencies (Debian/apt) - build-essential # gcc, make, etc. - cmake - ninja-build - zip - ccache - dpkg-dev - fakeroot - lld - clang - llvm - python3 - python3-pip - python3-venv - pipx - git - libncurses-dev - libtinfo-dev - pkg-config # Optional feature dependencies (enable async I/O, archive extraction, media metadata) - liburing-dev # enables io_uring async path instead of fallback - libarchive-dev # enables archive extraction features - libtag1-dev # enables taglib (audio metadata) detection - libsqlite3-dev # enables SQLite database support - libssl-dev - libcurl4-openssl-dev - libsqlite3-dev - libncurses-dev - protobuf-compiler - libprotobuf-dev tasks: # Determine version from the Git ref and persist to ~/.buildenv for later tasks. - compute_version: | set -e # Detect repository root (some runners check out into ./, others into ./yams) if [ -d yams ] && [ -f yams/CMakeLists.txt ]; then REPO_DIR="yams" else REPO_DIR="." fi cd "${REPO_DIR}" CHANNEL="${RELEASE_CHANNEL:-}" # Auto-channelize main branch builds as nightly when not tagged if [[ -z "${CHANNEL}" && "${GIT_REF:-}" == "refs/heads/main" ]]; then CHANNEL="nightly" export RELEASE_CHANNEL="nightly" # Persist for subsequent tasks which may source this echo "RELEASE_CHANNEL=nightly" >> ~/.buildenv fi # Determine numeric base version from latest tag (strip leading v), fallback to 0.0.0 RAW_TAG_NUMERIC="$(git describe --tags --abbrev=0 2>/dev/null || echo 0.0.0)" BASE_NUMERIC_VERSION="${RAW_TAG_NUMERIC#v}" if [ "$CHANNEL" = "nightly" ]; then CLEAN_VERSION_DISPLAY="nightly-$(date -u +%Y%m%d)" CLEAN_VERSION_CMAKE="${BASE_NUMERIC_VERSION}" elif [ "$CHANNEL" = "weekly" ]; then CLEAN_VERSION_DISPLAY="weekly-$(date -u +%G)w$(date -u +%V)" CLEAN_VERSION_CMAKE="${BASE_NUMERIC_VERSION}" else # Prefer tag-triggered builds; otherwise use last tag as numeric if [[ "${GIT_REF:-}" =~ ^refs/tags/ ]]; then RAW_TAG="${GIT_REF#refs/tags/}" CLEAN_VERSION_DISPLAY="${RAW_TAG#v}" CLEAN_VERSION_CMAKE="${RAW_TAG#v}" else CLEAN_VERSION_DISPLAY="${BASE_NUMERIC_VERSION}" CLEAN_VERSION_CMAKE="${BASE_NUMERIC_VERSION}" fi fi # Persist for subsequent tasks echo "YAMS_VERSION=${CLEAN_VERSION_DISPLAY}" >> ~/.buildenv echo "YAMS_VERSION_CMAKE=${CLEAN_VERSION_CMAKE}" >> ~/.buildenv echo "Computed YAMS_VERSION(display)=${CLEAN_VERSION_DISPLAY}, YAMS_VERSION_CMAKE=${CLEAN_VERSION_CMAKE} (GIT_REF=${GIT_REF:-n/a}, RELEASE_CHANNEL=${CHANNEL:-n/a})" - setup: | set -e # Ensure pipx/venv/pip path is prepared export PATH="${HOME}/.local/bin:${PATH}" # Configure git identity and signing key (requested) git config --global user.name "Trevon" || true git config --global user.email "git@trevon.dev" || true git config --global user.signingkey "C1E8284DAE319BA313FCB40038686EA797D7A8A7" || true # Note: actual signed commits/tags require the private key in the agent; we only set identity here. # Configure ccache (optional acceleration) export CCACHE_DIR="${HOME}/.cache/ccache" mkdir -p "${CCACHE_DIR}" echo "CCACHE_DIR=${CCACHE_DIR}" >> ~/.buildenv if command -v ccache >/dev/null 2>&1; then ccache --set-config=max_size=2G || true ccache --zero-stats || true ccache -s || true fi # Install Conan via pipx when available; otherwise fallback to user pip or an isolated venv if ! command -v conan >/dev/null 2>&1; then if command -v pipx >/dev/null 2>&1; then pipx install 'conan<3' --pip-args='--upgrade' || true fi fi if ! command -v conan >/dev/null 2>&1; then python3 -m pip install --user --upgrade 'conan<3' || true hash -r fi if ! command -v conan >/dev/null 2>&1; then python3 -m venv /opt/conan . /opt/conan/bin/activate python -m pip install --upgrade pip setuptools wheel python -m pip install 'conan<3' export PATH="/opt/conan/bin:${PATH}" hash -r fi # Persist Conan PATH and CPU count for subsequent tasks and fail fast if missing if command -v conan >/dev/null 2>&1; then CONAN_DIR="$(dirname "$(command -v conan)")" echo "PATH=${CONAN_DIR}:\$PATH" >> ~/.buildenv else echo "Conan is not available after installation attempts" >&2 exit 1 fi CONAN_CPU_COUNT="${CONAN_CPU_COUNT:-$(nproc || getconf _NPROCESSORS_ONLN || echo 2)}" echo "CONAN_CPU_COUNT=${CONAN_CPU_COUNT}" >> ~/.buildenv # Detect and move into repository root if [ -d yams ] && [ -f yams/CMakeLists.txt ]; then REPO_DIR="yams" else REPO_DIR="." fi cd "${REPO_DIR}" # Configure the Conan profile. # Prefer clang to avoid GCC 15 regressions with onnxruntime export CC=clang export CXX=clang++ echo "CC=clang" >> ~/.buildenv echo "CXX=clang++" >> ~/.buildenv conan --version conan profile detect --force || true # Ensure default profile uses clang and libstdc++11 conan profile update settings.compiler=clang default || true conan profile update settings.compiler.libcxx=libstdc++11 default || true # Keep C++20 sed -i 's/^settings\.compiler\.cppstd=.*/settings.compiler.cppstd=20/' ~/.conan2/profiles/default || true echo "Conan profile configured (clang):" conan profile show -pr default || conan profile show || true - yams_semver_guard: | set -e if [ -d yams ] && [ -f yams/CMakeLists.txt ]; then REPO_DIR="yams" else REPO_DIR="." fi cd "${REPO_DIR}" echo "Running YAMS semver guard..." python3 scripts/ci/check_yams_semver.py - build: | set -e export PATH="${HOME}/.local/bin:/opt/conan/bin:${PATH}" if ! command -v conan >/dev/null 2>&1; then echo "conan not found in PATH; aborting build" >&2 exit 1 fi if [ -d yams ] && [ -f yams/CMakeLists.txt ]; then REPO_DIR="yams" else REPO_DIR="." fi cd "${REPO_DIR}" export YAMS_DISABLE_MODEL_PRELOAD=1 CLEAN_VERSION_CMAKE="${YAMS_VERSION_CMAKE}" echo "Starting build (CMake version ${CLEAN_VERSION_CMAKE})" # Fetch dependencies and generate CMake toolchain/deps. # Use clang toolchain to avoid GCC 15 onnxruntime 1.18 build issues. conan install . \ -of "${BUILD_DIR}" \ -pr:h=./conan/profiles/host-linux-clang \ -s build_type=Release \ -c tools.build:jobs="${CONAN_CPU_COUNT}" \ --build=missing # Configure with CMake (uses preset toolchain path under ${BUILD_DIR}). cmake --preset yams-release \ -DYAMS_VERSION="${CLEAN_VERSION_CMAKE}" \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCURSES_NEED_NCURSES=ON \ -DCURSES_NEED_WIDE=ON # Build the project. cmake --build --preset yams-release # Install the built artifacts into the staging directory. mkdir -p "${STAGE_DIR}" cmake --install "${BUILD_DIR}" --config Release --prefix "${STAGE_DIR}" # Show ccache stats after build (if available) if command -v ccache >/dev/null 2>&1; then ccache -s || true fi - package: | # Package on tag builds or when explicitly channelized as nightly/weekly # Auto-channelize main branch builds as nightly when not tagged if [[ -z "${RELEASE_CHANNEL:-}" && "${GIT_REF:-}" == "refs/heads/main" ]]; then export RELEASE_CHANNEL=nightly fi if [[ "${GIT_REF:-}" != refs/tags/* && "${RELEASE_CHANNEL:-}" != "nightly" && "${RELEASE_CHANNEL:-}" != "weekly" ]]; then echo "Skipping packaging (not a tag build and no release channel): GIT_REF=${GIT_REF:-n/a} RELEASE_CHANNEL=${RELEASE_CHANNEL:-n/a}" exit 0 fi if [ -d yams ] && [ -f yams/CMakeLists.txt ]; then REPO_DIR="yams" else REPO_DIR="." fi cd "${REPO_DIR}" CLEAN_VERSION="${YAMS_VERSION}" echo "Packaging the release..." cd "${STAGE_DIR}" tar -czf "../yams-${CLEAN_VERSION}-linux-x86_64.tar.gz" . echo "Created asset: yams-${CLEAN_VERSION}-linux-x86_64.tar.gz" # Also publish a raw stage archive for debugging/inspection tar -czf "../yams-${CLEAN_VERSION}-stage.tar.gz" . if command -v zip >/dev/null 2>&1; then zip -qry "../yams-${CLEAN_VERSION}-stage.zip" . fi - package_cpack: | # Package on tag builds or when explicitly channelized as nightly/weekly # Auto-channelize main branch builds as nightly when not tagged if [[ -z "${RELEASE_CHANNEL:-}" && "${GIT_REF:-}" == "refs/heads/main" ]]; then export RELEASE_CHANNEL=nightly fi if [[ "${GIT_REF:-}" != refs/tags/* && "${RELEASE_CHANNEL:-}" != "nightly" && "${RELEASE_CHANNEL:-}" != "weekly" ]]; then echo "Skipping CPack packaging (not a tag build and no release channel): GIT_REF=${GIT_REF:-n/a} RELEASE_CHANNEL=${RELEASE_CHANNEL:-n/a}" exit 0 fi if [ -d yams ] && [ -f yams/CMakeLists.txt ]; then REPO_DIR="yams" else REPO_DIR="." fi cd "${REPO_DIR}" CLEAN_VERSION="${YAMS_VERSION_CMAKE}" echo "Packaging with CPack..." cd "${BUILD_DIR}" # Generate DEB package cpack -G DEB \ -D CPACK_PACKAGE_VERSION="${CLEAN_VERSION}" \ -D CPACK_PACKAGE_CONTACT="Trevon " \ -D CPACK_DEBIAN_PACKAGE_MAINTAINER="Trevon " # Generate RPM package cpack -G RPM -D CPACK_PACKAGE_VERSION="${CLEAN_VERSION}" artifacts: # Files available for download after a successful build. Support both repo layouts. - "yams-*.tar.gz" - "yams-*-stage.tar.gz" - "yams-*-stage.zip" - "build/yams-release/*.deb" - "build/yams-release/*.rpm" - "yams/yams-*.tar.gz" - "yams/yams-*-stage.tar.gz" - "yams/yams-*-stage.zip" - "yams/build/yams-release/*.deb" - "yams/build/yams-release/*.rpm"