#!/usr/bin/env bash # Deploy this app to production with the latest boboko-core tag. # # 1. Refuses to run with uncommitted work (the server deploys what's pushed, # nothing else) — only the core wiring files are allowed to be dirty. # 2. Pulls translation lines added in the Language Lines UI into core's # seeders (boboko:translations:pull) — in local mode; if any are pulled, # stops so you can release core first. In repo mode it only checks. # 3. Switches to repo mode if you're on the local ../boboko-core checkout, # and restarts the stack either way so the lockfiles pick up the newest # tag (bin/core-mode repo). # 4. Commits the lockfile bump, if any, asks for confirmation, pushes. # 5. Runs `envoy run deploy` (see Envoy.blade.php) against .env.envoy's host. # # Leaves you in repo mode — run `bin/core-mode local` to go back. set -euo pipefail cd "$(dirname "$0")/.." fail() { echo "!!! $*" >&2; exit 1; } [ -f .env.envoy ] || fail ".env.envoy not found — copy .env.envoy.example and fill it in." branch=$(grep -m1 '^DEPLOY_BRANCH=' .env.envoy | cut -d= -f2-) host=$(grep -m1 '^DEPLOY_SSH_HOST=' .env.envoy | cut -d= -f2-) branch=${branch:-master} [ "$(git branch --show-current)" = "$branch" ] || fail "You're not on $branch (the branch Envoy deploys)." # Anything tracked and modified other than the four core wiring files would be # silently left out of the deploy — make that a hard stop instead. dirty=$(git status --porcelain --untracked-files=no | grep -vE '^.. (composer\.json|composer\.lock|package\.json|package-lock\.json)$' || true) if [ -n "$dirty" ]; then echo "$dirty" fail "Commit or stash these first — the server only deploys what's pushed." fi echo ">>> Fetching origin..." git fetch origin "$branch" [ "$(git rev-list --count "HEAD..origin/$branch")" -eq 0 ] || fail "origin/$branch has commits you don't — pull first." # Translation lines added through the Language Lines UI only reach other apps # once they're in core's seeders. In local mode, pull them into # ../boboko-core; in repo mode the command can only report them. lines_in() { printf '%s\n' "$1" | sed -n 's/^\([0-9][0-9]*\) line(s).*/\1/p' | tail -1; } if [ "$(bin/core-mode)" = local ]; then echo ">>> Pulling UI-added translations into ../boboko-core's seeders..." out=$(bin/dc-core.sh exec -T app php artisan boboko:translations:pull --no-ansi) || fail "boboko:translations:pull failed — is the stack running (bin/dc-core.sh up -d)?" echo "$out" pulled=$(lines_in "$out") if [ "${pulled:-0}" -gt 0 ]; then fail "Pulled $pulled translation line(s) into ../boboko-core. Review, commit, tag and push core, then rerun bin/deploy." fi else echo ">>> Checking for UI-added translations missing from core's seeders..." if out=$(bin/dc exec -T app php artisan boboko:translations:pull --dry-run --no-ansi 2>&1); then missing=$(lines_in "$out") if [ "${missing:-0}" -gt 0 ]; then echo "$out" fail "These lines are only in this database — run bin/core-mode local and rerun bin/deploy to pull them into core." fi echo " nothing missing" else echo " skipped — the installed boboko/core doesn't have boboko:translations:pull yet" fi fi # Switch to repo mode (or just restart if already there) so both lockfiles # resolve the newest boboko-core tag. bin/core-mode repo git diff --quiet HEAD -- composer.json package.json || fail "composer.json / package.json differ from HEAD in repo mode — they should only differ by the local/repo toggle." if grep -A14 '"name": "boboko/core"' composer.lock | grep -q '"type": "path"'; then fail "composer.lock still points boboko/core at the local path repo." fi if grep -A6 '"node_modules/@boboko/core": {' package-lock.json | grep -q '"link": true'; then fail "package-lock.json still links @boboko/core to the local checkout." fi version=$(grep -A1 '"name": "boboko/core"' composer.lock | grep -o '"version": "[^"]*"' | cut -d'"' -f4) # A tag you created in ../boboko-core but never pushed won't be resolved. if [ -d ../boboko-core ]; then latest=$(git -C ../boboko-core tag --sort=-v:refname | head -1) if [ -n "$latest" ] && [ "$latest" != "v$version" ]; then echo "!!! Warning: resolved boboko/core $version, but ../boboko-core's newest tag is $latest." echo "!!! Did you push it? (git -C ../boboko-core push origin $latest)" fi fi if ! git diff --quiet HEAD -- composer.lock package-lock.json; then echo ">>> Committing lockfiles for boboko/core $version..." git add composer.lock package-lock.json git commit -m "Chore: Bumping boboko/core to $version" fi echo echo ">>> Deploying $branch to $host with boboko/core $version." pending=$(git log --oneline "origin/$branch..HEAD") if [ -n "$pending" ]; then echo ">>> Commits to push:" echo "$pending" else echo ">>> Nothing new to push — this redeploys origin/$branch as-is." fi echo read -r -p "Push and deploy? [y/N] " answer [ "$answer" = y ] || [ "$answer" = Y ] || fail "Aborted." if [ -n "$pending" ]; then git push origin "$branch" fi vendor/bin/envoy run deploy echo echo ">>> Done. You're in repo mode — run bin/core-mode local to go back to your ../boboko-core checkout."