#!/bin/sh
# Web Apps deploy, run as the account: a fresh release from the staged source, dependencies, the build, then current points at it
set -u
base="$HOME/webapps/$BB_APP"
rel="$base/releases/$BB_DEPLOY"
mkdir -p "$base/logs" "$base/releases" || exit 20
exec >>"$base/logs/$BB_DEPLOY.log" 2>&1
step() { printf '\n==> %s\n' "$*"; }
fail() { printf '\n!! %s\n' "$2"; rm -rf -- "$rel"; exit "$1"; }
export PATH="$BB_RUNTIME_BIN:/usr/local/bin:/usr/bin:/bin" CI=1 COREPACK_ENABLE_DOWNLOAD_PROMPT=0 npm_config_update_notifier=false
printf '==> Deploy %s of %s with Node.js %s\n' "$BB_DEPLOY" "$BB_APP" "$(node --version 2>/dev/null || echo '(missing)')"

src="$base/source"
[ -n "$BB_APPDIR" ] && src="$src/$BB_APPDIR"
[ -d "$src" ] || fail 20 "The staged source isn't there; stage the app again."
step "Copying the source into a new release"
mkdir -p "$rel" && (cd "$src" && tar -cf - --exclude=./.git --exclude=./node_modules .) | (cd "$rel" && tar -xf -) || fail 20 "The source couldn't be copied."
cd "$rel" || fail 20 "The release folder couldn't be opened."

case "$BB_PM" in
    yarn|pnpm)
        # corepack fetches the exact yarn or pnpm the project asks for, into the account's own cache
        shims="$HOME/.cache/bakkbone/corepack-bin"
        mkdir -p "$shims" && corepack enable --install-directory "$shims" yarn pnpm || fail 13 "corepack couldn't set up $BB_PM."
        export PATH="$shims:$PATH"
        ;;
esac
if [ -f package.json ]; then
    step "Installing dependencies with $BB_PM"
    # Build tools are usually devDependencies, so they're installed whatever NODE_ENV the app sets
    case "$BB_PM" in
        npm) if [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then npm ci --include=dev --no-audit --no-fund; else npm install --include=dev --no-audit --no-fund; fi ;;
        yarn) NODE_ENV=development yarn install ;;
        pnpm) if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile --prod=false; else pnpm install --prod=false; fi ;;
        *) fail 13 "$BB_PM isn't available on this server; use npm, yarn or pnpm." ;;
    esac || fail 13 "Installing dependencies failed."
fi

if [ -n "$BB_BUILD" ]; then
    step "Building: $BB_BUILD"
    NODE_ENV="${NODE_ENV:-$BB_MODE}" sh -c "$BB_BUILD" || fail 10 "The build failed."
fi
if [ "$BB_CATEGORY" = static ]; then
    [ -d "${BB_OUTPUT:-.}" ] || fail 11 "The build didn't produce ${BB_OUTPUT:-.}, which the app is served from."
fi

step "Making release $BB_DEPLOY live"
ln -sfn "releases/$BB_DEPLOY" "$base/.current-new" && mv -T "$base/.current-new" "$base/current" || fail 20 "The release couldn't be made live."
# The live release and the two before it are kept, so a bad deploy can be rolled back by hand
ls -1 "$base/releases" | sort | head -n -3 | while read -r old; do
    [ "$old" = "$BB_DEPLOY" ] || rm -rf -- "$base/releases/$old"
done
printf '\n==> Done\n'
