#!/usr/bin/env bash set -euo pipefail # --- Config & utilities ------------------------------------------------------- # Resolve repo root (script may be called from anywhere) SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)" cd "${REPO_ROOT}" # Load env if present (non-fatal) if [[ -f ".env-rc" ]]; then # shellcheck disable=SC1091 source ".env-rc" fi # Registry URL (override via env if desired) REGISTRY_URL="${REGISTRY_URL:-opencode.it4i.eu:5050/openwebsearcheu-public/owi-cli}" REGISTRY_HOST="${REGISTRY_URL%%/*}" # e.g. "opencode.it4i.eu:5050" # Docker command (use sudo if needed) DOCKER="${DOCKER:-docker}" if ! command -v "${DOCKER}" >/dev/null 2>&1; then echo "❌ Docker binary not found in PATH." exit 1 fi # If docker needs root and user didn't run with sudo, try to elevate: if ! "${DOCKER}" info >/dev/null 2>&1; then if command -v sudo >/dev/null 2>&1; then DOCKER="sudo ${DOCKER}" fi fi # --- Version discovery --------------------------------------------------------- get_version() { local v="" # 1) uv version (if uv exists and returns a value) if command -v uv >/dev/null 2>&1; then if v="$(uv version 2>/dev/null)"; then if [[ -n "${v}" ]]; then echo "${v}" return 0 fi fi fi # 2) Parse pyproject.toml [project].version via Python tomllib/tomli if command -v python3 >/dev/null 2>&1; then if v="$(python3 - <<'PY' 2>/dev/null import sys from pathlib import Path pp = Path("pyproject.toml") if not pp.exists(): sys.exit(1) data = pp.read_bytes() try: import tomllib as toml # Python 3.11+ except Exception: try: import tomli as toml # fallback except Exception: sys.exit(2) cfg = toml.loads(data) print(cfg.get("project", {}).get("version", "")) PY )"; then if [[ -n "${v}" ]]; then echo "${v}" return 0 fi fi fi # 3) Minimal awk parser: version = "x.y.z" under [project] if [[ -f "pyproject.toml" ]]; then v="$(awk ' /^\[project\]/ { in_proj=1; next } /^\[/ { in_proj=0 } in_proj && $0 ~ /^[[:space:]]*version[[:space:]]*=/ { match($0, /"[^\"]+"/); if (RSTART) { print substr($0, RSTART+1, RLENGTH-2); exit } }' pyproject.toml )" if [[ -n "${v}" ]]; then echo "${v}" return 0 fi fi # 4) git describe fallback if command -v git >/dev/null 2>&1; then if v="$(git describe --tags --always 2>/dev/null)"; then if [[ -n "${v}" ]]; then echo "${v}" return 0 fi fi fi # 5) Last resort: datestamp date +'%Y.%m.%d-%H%M%S' } VERSION="$(get_version)" # Sanitize version for Docker tag rules (letters, digits, underscores, dots, dashes) if [[ -z "${VERSION}" ]]; then echo "❌ Could not determine a version tag." exit 1 fi SANITIZED_VERSION="$(echo -n "${VERSION}" | tr ' ' '-' | sed 's/[^A-Za-z0-9_.-]/-/g')" if [[ "${SANITIZED_VERSION}" != "${VERSION}" ]]; then echo "⚠️ Version '${VERSION}' contained unsupported characters; using sanitized tag '${SANITIZED_VERSION}'." fi # Enforce max length 128 for tag if (( ${#SANITIZED_VERSION} > 128 )); then echo "⚠️ Tag too long; truncating to 128 chars." SANITIZED_VERSION="${SANITIZED_VERSION:0:128}" fi IMAGE_NAME="${REGISTRY_URL}:${SANITIZED_VERSION}" IMAGE_LATEST="${REGISTRY_URL}:latest" # --- Credentials --------------------------------------------------------------- : "${GITLAB_TOKEN_NAME:?❌ GITLAB_TOKEN_NAME env var is required}" : "${GITLAB_TOKEN_SECRET:?❌ GITLAB_TOKEN_SECRET env var is required}" # --- Build, login, push -------------------------------------------------------- echo "🔨 Building Docker image:" echo " - ${IMAGE_NAME}" echo " - ${IMAGE_LATEST}" ${DOCKER} build -t "${IMAGE_NAME}" -t "${IMAGE_LATEST}" . echo "🔑 Logging in to ${REGISTRY_HOST}" # Use --password-stdin so secret isn't exposed to process list if ! printf '%s' "${GITLAB_TOKEN_SECRET}" | ${DOCKER} login "${REGISTRY_HOST}" -u "${GITLAB_TOKEN_NAME}" --password-stdin; then echo "❌ Docker login failed for ${REGISTRY_HOST}" exit 1 fi echo "🚀 Pushing images to ${REGISTRY_HOST}" ${DOCKER} push "${IMAGE_NAME}" ${DOCKER} push "${IMAGE_LATEST}" echo "✅ Done. Pushed:" echo " - ${IMAGE_NAME}" echo " - ${IMAGE_LATEST}"