#!/usr/bin/env bash # Host wrapper: build CI image + run pipeline with log capture. # # Usage: # ./scripts/docker-build-runner.sh --build-id 42 --workdir /path/to/repo # # Env: see ci-build-and-publish-ota.sh # When invoked from PHP (BUILD_LOG_STDOUT_ONLY=1), log via stdout only — parent redirects to build.log. # # Parallel builds: set BUILD_ISOLATE_SOURCE=1 (default from builder) to shallow-clone into # $OUT_DIR/src instead of mutating the shared deploy checkout. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" IMAGE="${ANDROIDCAST_CI_IMAGE:-androidcast-ci:latest}" CI_VERSION="${ANDROIDCAST_CI_VERSION:-00.01.00.1000}" BUILD_ID="${BUILD_ID:-local}" LOG_FILE="${BUILD_LOG_FILE:-${ROOT}/out/builds/${BUILD_ID}/build.log}" WORK_DIR="${BUILD_WORK_DIR:-${ROOT}}" OUT_DIR="${BUILD_OUT_DIR:-${WORK_DIR}/out/builds/${BUILD_ID}}" LOG_STDOUT_ONLY="${BUILD_LOG_STDOUT_ONLY:-0}" ISOLATE_SOURCE="${BUILD_ISOLATE_SOURCE:-1}" CLONE_DEPTH="${BUILD_GIT_DEPTH:-1}" SOURCE_DIR="${OUT_DIR}/src" DOCKER_WORKSPACE="${WORK_DIR}" mkdir -p "$(dirname "$LOG_FILE")" "$OUT_DIR" log() { if [[ "$LOG_STDOUT_ONLY" == "1" ]]; then echo "$@" else echo "$@" | tee -a "$LOG_FILE" fi } run_logged() { if [[ "$LOG_STDOUT_ONLY" == "1" ]]; then "$@" else "$@" 2>&1 | tee -a "$LOG_FILE" fi } # Git 2.35+ refuses repos owned by another uid (PHP-FPM nginx vs deploy user). git_safe() { git -c safe.directory="${WORK_DIR}" "$@" } resolve_git_remote() { if [[ -n "${GIT_REMOTE:-}" ]]; then echo "$GIT_REMOTE" return fi if [[ -d "${WORK_DIR}/.git" ]]; then git_safe -C "${WORK_DIR}" remote get-url origin 2>/dev/null || true fi } prepare_isolated_source() { local ref="${GIT_REF:-}" local remote sha remote="$(resolve_git_remote)" if [[ -z "$ref" || -z "$remote" ]]; then log "[runner] isolate: skip (need GIT_REF and origin remote)" return 0 fi rm -rf "${SOURCE_DIR}" mkdir -p "${SOURCE_DIR}" log "[runner] isolate: shallow clone depth=${CLONE_DEPTH} ref=${ref} -> ${SOURCE_DIR}" if git clone --depth "${CLONE_DEPTH}" --recurse-submodules --shallow-submodules \ --single-branch --branch "${ref}" "${remote}" "${SOURCE_DIR}" 2>/dev/null; then : else log "[runner] isolate: branch clone failed; clone default branch then checkout ${ref}" run_logged git clone --depth "${CLONE_DEPTH}" --recurse-submodules --shallow-submodules \ "${remote}" "${SOURCE_DIR}" run_logged git -c safe.directory="${SOURCE_DIR}" -C "${SOURCE_DIR}" fetch --depth "${CLONE_DEPTH}" origin "${ref}" run_logged git -c safe.directory="${SOURCE_DIR}" -C "${SOURCE_DIR}" checkout "${ref}" fi if [[ -n "${GIT_SHA:-}" ]]; then log "[runner] isolate: checkout pin GIT_SHA=${GIT_SHA}" run_logged git -c safe.directory="${SOURCE_DIR}" -C "${SOURCE_DIR}" checkout "${GIT_SHA}" fi run_logged git -c safe.directory="${SOURCE_DIR}" -C "${SOURCE_DIR}" rev-parse HEAD DOCKER_WORKSPACE="${SOURCE_DIR}" } sync_shared_checkout() { if [[ -z "${GIT_REF:-}" ]] || [[ ! -d "${WORK_DIR}/.git" ]]; then return 0 fi log "[runner] syncing shared checkout ref=${GIT_REF}" run_logged git_safe -C "${WORK_DIR}" fetch origin --prune || true run_logged git_safe -C "${WORK_DIR}" checkout "${GIT_REF}" run_logged git_safe -C "${WORK_DIR}" pull --rebase origin "${GIT_REF}" || true if [[ -n "${GIT_SHA:-}" ]]; then run_logged git_safe -C "${WORK_DIR}" checkout "${GIT_SHA}" fi run_logged git_safe -C "${WORK_DIR}" rev-parse HEAD } log "[runner] image=${IMAGE} ci_version=${CI_VERSION} build_id=${BUILD_ID}" log "[runner] workdir=${WORK_DIR} out=${OUT_DIR} isolate=${ISOLATE_SOURCE}" if [[ "$ISOLATE_SOURCE" == "1" ]]; then prepare_isolated_source else sync_shared_checkout fi log "[runner] docker workspace=${DOCKER_WORKSPACE}" run_logged docker build \ --build-arg ANDROIDCAST_CI_VERSION="${CI_VERSION}" \ -t "$IMAGE" \ -f "${ROOT}/Dockerfile" \ "${ROOT}" run_logged docker run --rm \ -v "${DOCKER_WORKSPACE}:/workspace" \ -v "${ROOT}/out:/workspace/out" \ -w /workspace \ -e BUILD_ID="${BUILD_ID}" \ -e OUT_DIR="/workspace/out/builds/${BUILD_ID}" \ -e OTA_BASE_URL="${OTA_BASE_URL:-}" \ -e OTA_CHANNEL="${OTA_CHANNEL:-staging}" \ -e GRADLE_TASK="${GRADLE_TASK:-assembleDebug}" \ -e RUN_UNIT_TESTS="${RUN_UNIT_TESTS:-1}" \ -e RUN_NATIVE="${RUN_NATIVE:-1}" \ -e AUTO_OTA="${AUTO_OTA:-0}" \ -e GIT_REF="${GIT_REF:-}" \ -e GIT_SHA="${GIT_SHA:-}" \ -e RELEASE_NOTES="${RELEASE_NOTES:-}" \ "$IMAGE" \ ./scripts/ci-build-and-publish-ota.sh log "[runner] finished build_id=${BUILD_ID}"