#!/bin/bash -e
#
# Author:: Lance Albertson <lance@osuosl.org>
# Copyright:: Copyright 2024-2026, Cinc Project
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# macOS build entry point.
#
# Strategy: combine RVM-bootstrap (for ruby/bundler) with rename-aside
# of the live install (for runner-state preservation).
#
#   1. mv /opt/omnibus-toolchain -> /opt/omnibus-toolchain.bootstrap
#      so the runner's working toolchain is safely out of the way.
#   2. Install ruby-3.4 via RVM into ${TOP_DIR}/rvm. RVM ruby is not
#      affected by writes to /opt/omnibus-toolchain — and crucially it
#      does not depend on /opt/omnibus-toolchain at all, so the
#      shebang problem that breaks "use the renamed toolchain's
#      binaries" never applies.
#   3. Build runs against a fresh empty /opt/omnibus-toolchain.
#   4. trap on EXIT restores the original install whether the build
#      succeeds or fails — runner ends every job in the same state it
#      started. Operator-driven upgrades pick up the new pkg manually,
#      see CINC_MAINTENANCE_PLAN.md §3.2.

TOP_DIR="$(pwd)"
export CI_PROJECT_DIR=${CI_PROJECT_DIR:-${TOP_DIR}}
export FORCE_UNSAFE_CONFIGURE=1
export rvm_path="${TOP_DIR}/rvm"

# Put Bundler's user-level cache + config inside the workspace
# instead of $HOME/.bundle, which is not always writable on
# self-hosted runners.
export BUNDLE_USER_HOME="${TOP_DIR}/.bundle-user"
mkdir -p "${BUNDLE_USER_HOME}"

INSTALL_DIR="/opt/omnibus-toolchain"
BOOTSTRAP_DIR="/opt/omnibus-toolchain.bootstrap"

# Defuse stale TLS/CA settings that point at the install_dir we are
# about to rename aside. Two sources to neutralize:
#   1. Env vars (GIT_SSL_CAINFO etc.) — unset them.
#   2. The runner's ~/.gitconfig http.sslcainfo entry — we cannot
#      unset it without modifying operator state (other projects on
#      this runner rely on it pointing at the live install), so use
#      GIT_CONFIG_COUNT to inject a per-process override that points
#      at the bootstrap copy of the cacert bundle. The bootstrap copy
#      exists from the moment we rename through the trap-restore on
#      exit, so the override path is always valid during the build.
unset GIT_SSL_CAINFO SSL_CERT_FILE SSL_CERT_DIR CURL_CA_BUNDLE
export GIT_CONFIG_NOSYSTEM=1
export GIT_CONFIG_COUNT=1
export GIT_CONFIG_KEY_0="http.sslcainfo"
export GIT_CONFIG_VALUE_0="${BOOTSTRAP_DIR}/embedded/ssl/certs/cacert.pem"

# Recover from a previous build that crashed before its trap could run.
if [ -d "${BOOTSTRAP_DIR}" ]; then
  if [ -x "${INSTALL_DIR}/embedded/bin/ruby" ]; then
    # Live install looks healthy; bootstrap is leftover noise.
    sudo rm -rf "${BOOTSTRAP_DIR}"
  else
    # Live install is missing or half-built; restore from bootstrap.
    sudo rm -rf "${INSTALL_DIR}"
    sudo mv "${BOOTSTRAP_DIR}" "${INSTALL_DIR}"
  fi
fi

if [ ! -x "${INSTALL_DIR}/embedded/bin/ruby" ]; then
  echo "ERROR: no working toolchain at ${INSTALL_DIR}; cannot guarantee a clean rollback" >&2
  echo "Install a seed omnibus-toolchain on this runner first; see CINC_MAINTENANCE_PLAN.md" >&2
  exit 1
fi

# Move the live install aside so the build has a clean slate AND so
# we can roll back to the original toolchain regardless of how the
# build exits.
sudo mv "${INSTALL_DIR}" "${BOOTSTRAP_DIR}"
trap 'sudo rm -rf "${INSTALL_DIR}"; sudo mv "${BOOTSTRAP_DIR}" "${INSTALL_DIR}"' EXIT

# Pre-create the empty install dir with current-user ownership.
# /opt itself is owned by root with normal perms, so the unprivileged
# omnibus build cannot recreate INSTALL_DIR on its own (the rename
# above left /opt without our install_dir). The build runs as the
# runner user without sudo on macOS, so it needs to own INSTALL_DIR
# to write into it.
sudo mkdir -p "${INSTALL_DIR}"
sudo chown "$(id -un):$(id -gn)" "${INSTALL_DIR}"

set -e
mkdir -p ${TOP_DIR}/cache/git_cache

GIT_CACHE="${TOP_DIR}/cache/git_cache/opt/omnibus-toolchain"
if [ -d "${GIT_CACHE}" ] && ! git --git-dir="${GIT_CACHE}" rev-parse --git-dir > /dev/null 2>&1; then
  echo "Git cache is corrupted, removing..."
  rm -rf "${GIT_CACHE}"
fi

grep -q '^cache_dir' omnibus.rb || {
  echo "cache_dir '${TOP_DIR}/cache'" >> omnibus.rb
  echo "git_cache_dir '${TOP_DIR}/cache/git_cache'" >> omnibus.rb
  # omnibus defaults source_dir/build_dir/package_dir/package_tmp to
  # /var/cache/omnibus/*, which is not writable on macOS without
  # sudo. Point them all into the workspace so the unprivileged
  # build can mkdir as needed. Do NOT point package_dir at
  # ${TOP_DIR}/pkg — omnibus's package_me step copies the built
  # package from package_dir to <project_root>/pkg (project.rb:1159)
  # and if those two are equal FileUtils.cp raises "same file" after
  # packaging completes.
  echo "source_dir '${TOP_DIR}/omnibus-src'" >> omnibus.rb
  echo "build_dir '${TOP_DIR}/omnibus-build'" >> omnibus.rb
  echo "package_dir '${TOP_DIR}/omnibus-pkg'" >> omnibus.rb
  echo "package_tmp '${TOP_DIR}/pkg-tmp'" >> omnibus.rb
  # Same reason as the other dir overrides: the default
  # base_dir/cache/ccache lives under /var/cache/omnibus which is
  # not writable by the unprivileged runner user on macOS, so
  # ccache's mkdir -p fails and the compile invocation aborts with
  # "cannot compute suffix of object files: cannot compile" during
  # libtool's configure.
  echo "ccache_dir '${TOP_DIR}/cache/ccache'" >> omnibus.rb
  echo "use_git_caching true" >> omnibus.rb
}

# Bootstrap Ruby via RVM (we cannot use the renamed toolchain's ruby
# because its shebangs still hardcode /opt/omnibus-toolchain, which
# the rename made nonexistent).
#
# Disable RVM's autolibs: by default `rvm install` tries to `brew
# update` on macOS to satisfy build deps, which is fragile on
# self-hosted runners with operator-managed Homebrew. The runner is
# already provisioned with Xcode CLT + brew autoconf/automake/libtool;
# RVM has no business touching brew here.
curl -sSL https://get.rvm.io | bash
source "${TOP_DIR}/rvm/scripts/rvm"
rvm autolibs disable
rvm install ruby-3.4

gem sources --remove https://rubygems.org/ || true
gem sources --add https://rubygems.cinc.sh
gem sources --add https://rubygems.org

bundle config set --local path "${TOP_DIR}/vendor/bundle"
bundle config set --local without 'development'
bundle install

if [ -n "${AWS_ACCESS_KEY_ID:-}" ] ; then
  bundle exec omnibus cache populate
fi

bundle exec omnibus build omnibus-toolchain \
  -l ${OMNIBUS_LOG_LEVEL:-info} \
  --override append_timestamp:false

mkdir -p ${CI_PROJECT_DIR}/data
mv -v pkg/omnibus-toolchain* ${CI_PROJECT_DIR}/data/
