aboutsummaryrefslogtreecommitdiffstats
path: root/deploy/post-receive
blob: b6b0b296e45362119ef4e279b567d9bf0f324128 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/bin/sh
# Deploy hook for cs:~/coinosv3-server.git. Install it as hooks/post-receive.
#
# A push to `prod` checks the commit out to $CHECKOUT, installs dependencies,
# restarts the services whose files changed, then mirrors the commit to
# git.coinos.io and gittr. What runs is always a commit: never copy files
# into the checkout by hand.
set -u
CHECKOUT=/home/adam/coinosv3-server
LOG=/home/adam/coinosv3-server-deploy.log
MIRROR=/home/adam/git/coinosv3-server.git
GITTR=[email protected]:npub1w27mc4aa6m0ufe3xs5z3m6qyr52gc0rglept7vqlwx4xeaf72tasnqz70r/coinosv3-server.git
BARE=$(pwd)
SERVICES="names nwcpush blossom"

while read -r oldrev newrev ref; do
  [ "$ref" = refs/heads/prod ] || continue
  {
    echo "== $(date -u +%FT%TZ) deploy $newrev"
    # the checkout is an ordinary clone of this repo, so submodules work
    unset GIT_DIR
    [ -d "$CHECKOUT/.git" ] || git clone -q --no-checkout "$BARE" "$CHECKOUT" || { echo "clone failed"; exit 1; }
    git -C "$CHECKOUT" fetch -q origin || { echo "fetch failed"; exit 1; }
    git -C "$CHECKOUT" checkout -q -f --detach "$newrev" || { echo "checkout failed"; exit 1; }
    # the pinned coinosv3 commit comes from the coinosv3 repo on this host
    git -C "$CHECKOUT" config submodule.coinosv3.url /home/adam/coinosv3.git
    git -C "$CHECKOUT" -c protocol.file.allow=always submodule update --init --force -q \
      || { echo "submodule update failed"; exit 1; }
    cd "$CHECKOUT" || exit 1
    docker run --rm -v "$CHECKOUT":/app -w /app oven/bun:1.3.14 bun install --frozen-lockfile --production \
      || { echo "bun install failed"; exit 1; }

    # which services to restart: their own directory changed, or something
    # they all share did (the pin, dependencies, compose); everything on a
    # first deploy
    if [ "$oldrev" = 0000000000000000000000000000000000000000 ]; then
      restart=$SERVICES
    else
      changed=$(git --git-dir="$BARE" diff --name-only "$oldrev" "$newrev")
      if echo "$changed" | grep -qE '^(coinosv3|package\.json|bun\.lock|compose\.yml)$'; then
        restart=$SERVICES
      else
        restart=""
        for s in $SERVICES; do echo "$changed" | grep -q "^$s/" && restart="$restart $s"; done
        # names imports bridge/ln.js
        echo "$changed" | grep -q '^bridge/ln\.js$' && case "$restart" in *names*) ;; *) restart="$restart names";; esac
      fi
    fi
    if [ -n "$restart" ]; then
      echo "restarting:$restart"
      docker compose -f "$CHECKOUT/compose.yml" --env-file /home/adam/coinosv3-state/.env up -d --force-recreate $restart \
        || echo "compose up failed"
    else
      echo "no service files changed"
    fi

    # mirrors; a failure here never fails the deploy
    git --git-dir="$BARE" push --quiet "$MIRROR" "$newrev:refs/heads/master" "refs/tags/*:refs/tags/*" \
      || echo "mirror push to git.coinos.io failed"
    GIT_SSH_COMMAND="ssh -i /home/adam/.ssh/gittr_ed25519 -o IdentitiesOnly=yes -o BatchMode=yes -o ConnectTimeout=15" \
      timeout 120 git --git-dir="$BARE" push --quiet "$GITTR" "$newrev:refs/heads/master" "refs/tags/*:refs/tags/*" \
      || echo "mirror push to gittr failed"
  } >> "$LOG" 2>&1
done