407 lines
16 KiB
YAML
407 lines
16 KiB
YAML
# .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
|
|
|
|
secrets:
|
|
- 46f739e5-4538-45dd-a79f-bf173b7a2ed9
|
|
|
|
sources:
|
|
- https://git.sr.ht/~trevon/yams
|
|
|
|
# Static metadata for search and badges (unrelated to Git tags)
|
|
tags:
|
|
- linux
|
|
- release
|
|
- cmake
|
|
- conan
|
|
- yams
|
|
- nightly
|
|
- weekly
|
|
|
|
environment:
|
|
# Define consistent directories (setup.sh uses build/release for Release builds).
|
|
BUILD_DIR: build/release
|
|
STAGE_DIR: stage # relative to BUILD_DIR (Meson --destdir uses builddir as base)
|
|
# 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
|
|
- meson
|
|
- ninja-build
|
|
- zip
|
|
- ccache
|
|
- dpkg-dev
|
|
- fakeroot
|
|
- rpm
|
|
- lld
|
|
- clang
|
|
- llvm
|
|
- python3
|
|
- python3-pip
|
|
- python3-venv
|
|
- pipx
|
|
- git
|
|
- libncurses-dev
|
|
- libtinfo-dev
|
|
- pkg-config
|
|
- libboost-all-dev
|
|
- 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-gnutls-dev # use gnutls variant; required by libmediainfo-dev (conflicts with openssl variant)
|
|
- libsqlite3-dev
|
|
- libncurses-dev
|
|
- protobuf-compiler
|
|
- libprotobuf-dev
|
|
- libmediainfo-dev # enables MediaInfo-based video metadata extraction
|
|
- mediainfo # MediaInfo CLI tool used at runtime for JSON output
|
|
|
|
tasks:
|
|
# Determine version from the Git ref and persist to ~/.buildenv for later tasks.
|
|
- compute_version: |
|
|
set -e
|
|
# Detect repository root (sr.ht often checks out into ./yams). Support Meson or CMake projects.
|
|
if [ -d yams ] && { [ -f yams/meson.build ] || [ -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/meson.build ] || [ -f yams/CMakeLists.txt ]; }; then
|
|
REPO_DIR="yams"
|
|
else
|
|
REPO_DIR="."
|
|
fi
|
|
cd "${REPO_DIR}"
|
|
|
|
# Configure Conan (use explicit GCC host/build profiles for Debian CI)
|
|
conan --version
|
|
conan profile detect --force || true
|
|
|
|
echo "Conan profile configured (default, overridden by setup.sh):"
|
|
conan profile show -pr default || conan profile show || true
|
|
|
|
- yams_semver_guard: |
|
|
set -e
|
|
if [ -d yams ] && { [ -f yams/meson.build ] || [ -f yams/CMakeLists.txt ]; }; then
|
|
REPO_DIR="yams"
|
|
else
|
|
REPO_DIR="."
|
|
fi
|
|
cd "${REPO_DIR}"
|
|
if [ -f scripts/ci/check_yams_semver.py ]; then
|
|
echo "Running YAMS semver guard..."
|
|
python3 scripts/ci/check_yams_semver.py
|
|
else
|
|
echo "No semver guard script found; skipping."
|
|
fi
|
|
|
|
- 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/meson.build ]; then
|
|
REPO_DIR="yams"
|
|
else
|
|
REPO_DIR="."
|
|
fi
|
|
cd "${REPO_DIR}"
|
|
export YAMS_DISABLE_MODEL_PRELOAD=1
|
|
CLEAN_VERSION_MESON="${YAMS_VERSION}"
|
|
echo "Starting build (Meson version ${CLEAN_VERSION_MESON})"
|
|
|
|
# Use setup.sh with environment variables for consistent build configuration
|
|
export YAMS_COMPILER=gcc
|
|
export YAMS_CPPSTD=20
|
|
export YAMS_CONAN_HOST_PROFILE=./conan/profiles/host-linux-gcc
|
|
export YAMS_CONAN_ARCH=x86_64
|
|
|
|
# Configure FAST_MODE via extra Meson flags
|
|
if [ "${FAST_MODE:-0}" = "1" ]; then
|
|
echo "FAST_MODE=1: build will skip ONNX and tests"
|
|
export YAMS_EXTRA_MESON_FLAGS="-Dyams-version=${CLEAN_VERSION_MESON} -Denable-onnx=disabled -Dplugin-onnx=false -Dbuild-tests=false"
|
|
else
|
|
export YAMS_EXTRA_MESON_FLAGS="-Dyams-version=${CLEAN_VERSION_MESON}"
|
|
fi
|
|
|
|
# Set install prefix to /usr for Linux packages (matches GitHub workflow)
|
|
export YAMS_INSTALL_PREFIX="/usr"
|
|
|
|
# Run setup.sh (Release build) - it now respects all YAMS_* environment variables
|
|
./setup.sh Release
|
|
|
|
# Build the project
|
|
meson compile -C build/release
|
|
|
|
# Install the built artifacts into build-local staging directory (BUILD_DIR/STAGE_DIR).
|
|
meson install -C build/release --destdir "${STAGE_DIR}"
|
|
|
|
# Show ccache stats after build (if available)
|
|
if command -v ccache >/dev/null 2>&1; then
|
|
ccache -s || true
|
|
fi
|
|
|
|
- test: |
|
|
set -e
|
|
# Run test suite; do not fail the build solely due to test failures so we can publish logs
|
|
if [ -d yams ] && [ -f yams/meson.build ]; then
|
|
REPO_DIR="yams"
|
|
else
|
|
REPO_DIR="."
|
|
fi
|
|
cd "${REPO_DIR}"
|
|
mkdir -p artifacts || true
|
|
if [ -d "${BUILD_DIR}" ]; then
|
|
echo "Running meson tests in ${BUILD_DIR}..."
|
|
meson test -C "${BUILD_DIR}" --print-errorlogs || true
|
|
# Collect logs and common debug info
|
|
if [ -d "${BUILD_DIR}/meson-logs" ]; then
|
|
tar -C "${BUILD_DIR}" -czf artifacts/meson-logs.tar.gz meson-logs || true
|
|
cp -vf "${BUILD_DIR}/meson-logs/testlog.txt" artifacts/testlog.txt 2>/dev/null || true
|
|
cp -vf "${BUILD_DIR}/meson-logs/meson-log.txt" artifacts/meson-log.txt 2>/dev/null || true
|
|
fi
|
|
# Export compile_commands if generated
|
|
if [ -f "${BUILD_DIR}/compile_commands.json" ]; then
|
|
cp -vf "${BUILD_DIR}/compile_commands.json" artifacts/compile_commands.json || true
|
|
fi
|
|
else
|
|
echo "BUILD_DIR ${BUILD_DIR} missing; skipping meson tests" | tee artifacts/test-notes.txt
|
|
fi
|
|
|
|
- package: |
|
|
set -e
|
|
# 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/meson.build ] || [ -f yams/CMakeLists.txt ]; }; then
|
|
REPO_DIR="yams"
|
|
else
|
|
REPO_DIR="."
|
|
fi
|
|
cd "${REPO_DIR}"
|
|
CLEAN_VERSION="${YAMS_VERSION}"
|
|
echo "Packaging the release..."
|
|
# Package from the staged install under BUILD_DIR/STAGE_DIR
|
|
if [ ! -d "${BUILD_DIR}/${STAGE_DIR}" ]; then
|
|
echo "ERROR: Stage directory ${BUILD_DIR}/${STAGE_DIR} not found" >&2
|
|
ls -al "${BUILD_DIR}" || true
|
|
exit 1
|
|
fi
|
|
cd "${BUILD_DIR}/${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
|
|
# Only attempt zip if there are regular files to include; otherwise zip exits with "Nothing to do!"
|
|
if find . -type f -print -quit | grep -q .; then
|
|
zip -qry "../yams-${CLEAN_VERSION}-stage.zip" . || echo "zip failed; continuing (tarball already created)"
|
|
else
|
|
echo "Stage contains no regular files; skipping zip archive"
|
|
fi
|
|
fi
|
|
|
|
- package_meson: |
|
|
set -e
|
|
# Package on tag builds or when explicitly channelized as nightly/weekly
|
|
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/meson.build ]; then
|
|
REPO_DIR="yams"
|
|
else
|
|
REPO_DIR="."
|
|
fi
|
|
cd "${REPO_DIR}"
|
|
CLEAN_VERSION="${YAMS_VERSION}"
|
|
echo "Packaging with Meson..."
|
|
if [ -x scripts/build-deb.sh ]; then
|
|
scripts/build-deb.sh "${CLEAN_VERSION}" "${BUILD_DIR}"
|
|
else
|
|
echo "scripts/build-deb.sh not found; skipping distro package step"
|
|
fi
|
|
|
|
- collect_artifacts: |
|
|
set -e
|
|
ART_DIR="artifacts"
|
|
mkdir -p "${ART_DIR}"
|
|
rm -f "${ART_DIR}/yams"*.tar.gz "${ART_DIR}/yams"*.deb "${ART_DIR}/yams"*.rpm 2>/dev/null || true
|
|
# Determine repository root
|
|
if [ -d yams ] && { [ -f yams/meson.build ] || [ -f yams/CMakeLists.txt ]; }; then
|
|
REPO_DIR="yams"
|
|
else
|
|
REPO_DIR="."
|
|
fi
|
|
# Publish a minimal, size-safe artifact set so SourceHut can retain them reliably.
|
|
# Policy:
|
|
# - Tag builds: prefer distro packages (.deb, .rpm) if available; fall back to the tarball.
|
|
# - Nightly/weekly: publish only the primary tarball (avoid duplicates and stage archives).
|
|
shopt -s nullglob || true
|
|
if [[ "${GIT_REF:-}" == refs/tags/* ]]; then
|
|
# Prefer distro packages on tagged releases
|
|
if compgen -G "${REPO_DIR}/${BUILD_DIR}/*.deb" > /dev/null; then
|
|
for f in "${REPO_DIR}/${BUILD_DIR}"/*.deb; do cp -v "$f" "${ART_DIR}/"; done
|
|
fi
|
|
if compgen -G "${REPO_DIR}/${BUILD_DIR}/*.rpm" > /dev/null; then
|
|
for f in "${REPO_DIR}/${BUILD_DIR}"/*.rpm; do cp -v "$f" "${ART_DIR}/"; done
|
|
fi
|
|
# Fallback to tarball when packages are missing
|
|
if ! compgen -G "${ART_DIR}/*" > /dev/null; then
|
|
for f in "${REPO_DIR}/${BUILD_DIR}"/yams-*-linux-x86_64.tar.gz; do cp -v "$f" "${ART_DIR}/"; done
|
|
fi
|
|
else
|
|
# Nightly/weekly: publish only the primary tarball
|
|
for f in "${REPO_DIR}/${BUILD_DIR}"/yams-*-linux-x86_64.tar.gz; do cp -v "$f" "${ART_DIR}/"; done
|
|
fi
|
|
# Provide stable filenames expected by SourceHut (no globbing in artifacts list)
|
|
if compgen -G "${ART_DIR}/*.tar.gz" > /dev/null; then
|
|
TARBALL=$(ls -1 "${ART_DIR}"/*.tar.gz | head -1)
|
|
cp -v "$TARBALL" "${ART_DIR}/yams.tar.gz"
|
|
fi
|
|
if compgen -G "${ART_DIR}/*.deb" > /dev/null; then
|
|
DEB=$(ls -1 "${ART_DIR}"/*.deb | head -1)
|
|
cp -v "$DEB" "${ART_DIR}/yams.deb"
|
|
fi
|
|
if compgen -G "${ART_DIR}/*.rpm" > /dev/null; then
|
|
RPM=$(ls -1 "${ART_DIR}"/*.rpm | head -1)
|
|
cp -v "$RPM" "${ART_DIR}/yams.rpm"
|
|
fi
|
|
echo "Collected artifacts:" && ls -l "${ART_DIR}" || true
|
|
# Fallback for CI branches: if no artifacts were collected (packaging gated),
|
|
# compress the staged install to provide a basic artifact for inspection.
|
|
if [ "$(find "${ART_DIR}" -type f | wc -l | tr -d ' ')" -eq 0 ]; then
|
|
if [ -d "${REPO_DIR}/${BUILD_DIR}/${STAGE_DIR}" ]; then
|
|
echo "No release artifacts; creating CI tarball from ${REPO_DIR}/${BUILD_DIR}/${STAGE_DIR}" >&2
|
|
tar -C "${REPO_DIR}/${BUILD_DIR}/${STAGE_DIR}" -czf "${ART_DIR}/yams.tar.gz" .
|
|
ls -l "${ART_DIR}" || true
|
|
else
|
|
echo "WARNING: Stage dir ${REPO_DIR}/${BUILD_DIR}/${STAGE_DIR} missing; no artifacts to publish" >&2
|
|
fi
|
|
fi
|
|
|
|
echo "collect_artifacts completed successfully"
|
|
exit 0
|
|
|
|
artifacts:
|
|
# SourceHut interprets artifact names literally (no shell globs). Provide
|
|
# stable filenames in collect_artifacts.
|
|
- "artifacts/yams.tar.gz"
|
|
- "artifacts/yams.deb"
|
|
- "artifacts/yams.rpm"
|
|
- "artifacts/meson-logs.tar.gz"
|
|
- "artifacts/testlog.txt"
|
|
- "artifacts/meson-log.txt"
|
|
- "artifacts/compile_commands.json"
|