build Add push-to-deploy pipeline scripts

Bare-repo post-receive hook plus root setup, layout-fix, and reset scripts. The hook builds and tests a timestamped release on a shared opam switch, flips a current symlink, restarts via scoped sudo, health-checks the app, rolls back on failure, and records deploy metadata.

Commit
7a7981b2a1e40cd48a4a87c01bccb0c49542f60b
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
deploy/fix-layout-root.sh
index 00000000..bd07f486 000000..100755
@@ -0,0 +1,119 @@
1 Added: #!/usr/bin/env bash
2 Added: # Corrective root script for the hito deploy layout.
3 Added: #
4 Added: # A manual seed nested shared/ and releases/ INSIDE the live release, so the
5 Added: # unit's /srv/hito/shared/hito.sqlite path vanished and SQLite could not open
6 Added: # the DB. This restores the intended sibling layout:
7 Added: #
8 Added: # /srv/hito/shared/{hito.sqlite,_opam} (never inside a release)
9 Added: # /srv/hito/releases/<ts>/ (the app tree)
10 Added: # /srv/hito/current -> releases/<ts>
11 Added: #
12 Added: # Run as root: sudo bash fix-layout-root.sh
13 Added: # Idempotent and conservative: it moves, never deletes, the database.
14 Added: set -euo pipefail
15 Added:
16 Added: SRV=/srv/hito
17 Added: DEPLOY_USER=mpeter
18 Added: DEPLOY_GROUP=git
19 Added:
20 Added: # The release that is currently live (resolve the symlink, strip trailing /).
21 Added: LIVE=$(readlink -f "$SRV/current")
22 Added: echo "live release: $LIVE"
23 Added: [ -d "$LIVE" ] || { echo "current does not resolve to a directory"; exit 1; }
24 Added:
25 Added: echo "== 1. restore top-level shared/ =="
26 Added: mkdir -p "$SRV/shared"
27 Added: # Move the DB back to the top-level shared dir if it drifted into the release.
28 Added: if [ -f "$LIVE/shared/hito.sqlite" ] && [ ! -e "$SRV/shared/hito.sqlite" ]; then
29 Added: mv "$LIVE/shared/hito.sqlite" "$SRV/shared/hito.sqlite"
30 Added: echo " moved DB -> $SRV/shared/hito.sqlite"
31 Added: fi
32 Added: # Move the shared opam switch back up if it drifted into the release.
33 Added: if [ -d "$LIVE/shared/_opam" ] && [ ! -e "$SRV/shared/_opam" ]; then
34 Added: mv "$LIVE/shared/_opam" "$SRV/shared/_opam"
35 Added: echo " moved shared switch -> $SRV/shared/_opam"
36 Added: fi
37 Added:
38 Added: echo "== 2. relocate the live release under releases/ =="
39 Added: mkdir -p "$SRV/releases"
40 Added: # Drop the nested shared/ and releases/ that the manual seed pulled in.
41 Added: rm -rf "$LIVE/shared" "$LIVE/releases"
42 Added: base=$(basename "$LIVE")
43 Added: if [ "$(dirname "$LIVE")" != "$SRV/releases" ]; then
44 Added: mv "$LIVE" "$SRV/releases/$base"
45 Added: LIVE="$SRV/releases/$base"
46 Added: echo " moved release -> $LIVE"
47 Added: fi
48 Added:
49 Added: echo "== 3. ownership and current symlink =="
50 Added: chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$SRV/shared" "$SRV/releases"
51 Added: ln -sfn "$LIVE" "$SRV/current.tmp"
52 Added: mv -T "$SRV/current.tmp" "$SRV/current"
53 Added: chown -h "$DEPLOY_USER:$DEPLOY_GROUP" "$SRV/current"
54 Added: echo " current -> $LIVE"
55 Added:
56 Added: echo "== 4. wire DB into the release and reinstall the corrected hook =="
57 Added: ln -sfn "$SRV/shared/hito.sqlite" "$LIVE/hito.sqlite"
58 Added: install -o "$DEPLOY_USER" -g "$DEPLOY_GROUP" -m 0755 \
59 Added: "$(dirname "$0")/post-receive" /srv/git/hito.git/hooks/post-receive
60 Added:
61 Added: echo "== 5. remove the obsolete top-level working clone =="
62 Added: # /srv/hito must contain only shared/, releases/, and current. A pre-pipeline
63 Added: # in-place clone still lives at the top level and makes dune see the hito
64 Added: # package twice (top-level dune-project AND current/dune-project). Its content
65 Added: # is fully preserved in the bare repo and in every release, and the only unique
66 Added: # runtime state (the DB) is already in shared/. Remove ONLY known clone
67 Added: # entries; never touch shared/, releases/, or current.
68 Added: for entry in ARCHITECTURE.org RAIL.org REQUESTS.org bin lib test site \
69 Added: dune dune-project hito.opam hito.sqlite LICENSE \
70 Added: _build .git .gitignore .ocamlformat .envrc .cache .kiro; do
71 Added: target="$SRV/$entry"
72 Added: if [ -e "$target" ] || [ -L "$target" ]; then
73 Added: rm -rf "$target"
74 Added: echo " removed $target"
75 Added: fi
76 Added: done
77 Added: # Guard: the three managed entries must survive.
78 Added: for keep in shared releases current; do
79 Added: [ -e "$SRV/$keep" ] || { echo "FATAL: $SRV/$keep missing after cleanup"; exit 1; }
80 Added: done
81 Added:
82 Added: echo "== 6. deploy master as a fresh release, built on the shared switch =="
83 Added: # Build in a staging dir OUTSIDE /srv/hito so dune's upward project-root search
84 Added: # never sees the current symlink or any sibling release (which would make the
85 Added: # hito package appear twice). Move the built tree into releases/ only after a
86 Added: # clean build, then flip current.
87 Added: NEW_TS=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
88 Added: NEW_REL="$SRV/releases/$NEW_TS"
89 Added: STAGE=$(sudo -u "$DEPLOY_USER" mktemp -d "/tmp/hito-stage.XXXXXX")
90 Added: sha=$(git --git-dir=/srv/git/hito.git rev-parse refs/heads/master)
91 Added: git --git-dir=/srv/git/hito.git archive "$sha" | tar -x -C "$STAGE"
92 Added: chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$STAGE"
93 Added: sudo -u "$DEPLOY_USER" -H bash -lc "
94 Added: set -euo pipefail
95 Added: export OPAMROOT=/home/$DEPLOY_USER/.opam
96 Added: cd '$STAGE'
97 Added: eval \"\$(opam env --switch='$SRV/shared' --set-switch)\"
98 Added: opam install . --deps-only --with-test -y
99 Added: dune build @check
100 Added: dune runtest
101 Added: dune build
102 Added: "
103 Added: # Publish the built tree as the new release.
104 Added: mkdir -p "$SRV/releases"
105 Added: mv "$STAGE" "$NEW_REL"
106 Added: ln -sfn "$SRV/shared/hito.sqlite" "$NEW_REL/hito.sqlite"
107 Added: chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$NEW_REL"
108 Added: ln -sfn "$NEW_REL" "$SRV/current.tmp"
109 Added: mv -T "$SRV/current.tmp" "$SRV/current"
110 Added: chown -h "$DEPLOY_USER:$DEPLOY_GROUP" "$SRV/current"
111 Added: echo " current -> $NEW_REL (master ${sha:0:12})"
112 Added:
113 Added: echo "== 7. restart =="
114 Added: systemctl restart hito
115 Added: sleep 1
116 Added: systemctl is-active hito && echo "hito is active" || {
117 Added: echo "still failing; recent journal:"; journalctl -u hito -n 15 --no-pager; exit 1;
118 Added: }
119 Added: echo "Done. /srv/hito holds shared/, releases/, current; live release is master."
deploy/post-receive
index 00000000..ab781dc8 000000..100755
@@ -0,0 +1,133 @@
1 Added: #!/usr/bin/env bash
2 Added: # hito post-receive hook. Runs on the VPS after every push.
3 Added: #
4 Added: # For a push to master: check out the pushed revision into a fresh timestamped
5 Added: # release, build and test it against the shared opam switch, flip
6 Added: # /srv/hito/current, restart the service, and confirm it answers HTTP. Any
7 Added: # build/test failure leaves the live release untouched and fails the push. A
8 Added: # failed health check rolls current back to the previous release and restarts.
9 Added: set -euo pipefail
10 Added:
11 Added: DEPLOY_BRANCH=master
12 Added: SRV=/srv/hito
13 Added: BARE=/srv/git/hito.git
14 Added: SHARED="$SRV/shared"
15 Added: RELEASES="$SRV/releases"
16 Added: KEEP=5
17 Added: HEALTH_URL="http://127.0.0.1:8080/login"
18 Added: HEALTH_TRIES=10
19 Added: HEALTH_DELAY=1
20 Added: export OPAMROOT=/home/mpeter/.opam
21 Added: export OPAMSWITCH="$SHARED"
22 Added:
23 Added: log() { printf ' hito-deploy: %s\n' "$*" >&2; }
24 Added: fail() { log "FAILED: $*"; exit 1; }
25 Added:
26 Added: # Poll the app until it answers, or report failure after HEALTH_TRIES.
27 Added: health_ok() {
28 Added: local i
29 Added: for i in $(seq 1 "$HEALTH_TRIES"); do
30 Added: if curl -sf -o /dev/null --max-time 3 "$HEALTH_URL"; then
31 Added: return 0
32 Added: fi
33 Added: sleep "$HEALTH_DELAY"
34 Added: done
35 Added: return 1
36 Added: }
37 Added:
38 Added: while read -r _old new ref; do
39 Added: if [ "$ref" != "refs/heads/$DEPLOY_BRANCH" ]; then
40 Added: log "skipping $ref (only $DEPLOY_BRANCH deploys)"
41 Added: continue
42 Added: fi
43 Added:
44 Added: start=$SECONDS
45 Added: ts=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
46 Added: rel="$RELEASES/$ts"
47 Added: buildlog="$rel/deploy.log"
48 Added: prev=$(readlink -f "$SRV/current" 2>/dev/null || true)
49 Added: log "deploying ${new:0:12} to $rel"
50 Added: mkdir -p "$rel"
51 Added:
52 Added: # Materialize the pushed revision from the bare repo. Use git archive so the
53 Added: # release contains exactly the tracked tree and never a stray shared/ or
54 Added: # releases/ directory. shared/ and releases/ are strict siblings of a release
55 Added: # and must never appear inside one.
56 Added: if ! git --git-dir="$BARE" archive "$new" | tar -x -C "$rel"; then
57 Added: rm -rf "$rel"; fail "checkout"
58 Added: fi
59 Added:
60 Added: # Build and test against the shared switch. The full build log is kept inside
61 Added: # the release ($buildlog) so a successful deploy leaves a record, not only a
62 Added: # failed one. Install missing deps only when hito.opam changed.
63 Added: eval "$(opam env --switch="$SHARED" --set-switch)"
64 Added: cd "$rel"
65 Added:
66 Added: log "syncing dependencies"
67 Added: opam install . --deps-only --with-test -y >"$buildlog" 2>&1 \
68 Added: || { tail -30 "$buildlog" >&2; rm -rf "$rel"; fail "opam deps"; }
69 Added:
70 Added: log "dune build @check"
71 Added: dune build @check >>"$buildlog" 2>&1 \
72 Added: || { tail -40 "$buildlog" >&2; rm -rf "$rel"; fail "@check"; }
73 Added:
74 Added: log "dune runtest"
75 Added: dune runtest >>"$buildlog" 2>&1 \
76 Added: || { tail -40 "$buildlog" >&2; rm -rf "$rel"; fail "tests"; }
77 Added:
78 Added: log "dune build (release)"
79 Added: dune build >>"$buildlog" 2>&1 \
80 Added: || { tail -40 "$buildlog" >&2; rm -rf "$rel"; fail "build"; }
81 Added:
82 Added: build_secs=$((SECONDS - start))
83 Added:
84 Added: # Wire the shared database into this release.
85 Added: ln -sfn "$SHARED/hito.sqlite" "$rel/hito.sqlite"
86 Added:
87 Added: # Record deploy metadata: in the release for provenance, and appended to a
88 Added: # durable log under shared/ so the deploy history outlives pruned releases.
89 Added: subject=$(git --git-dir="$BARE" log -1 --format=%s "$new")
90 Added: cat >"$rel/deploy-info.json" <<JSON
91 Added: {
92 Added: "commit": "$new",
93 Added: "subject": $(printf '%s' "$subject" | sed 's/\\/\\\\/g; s/"/\\"/g; s/.*/"&"/'),
94 Added: "branch": "$DEPLOY_BRANCH",
95 Added: "deployed_at": "$ts",
96 Added: "build_seconds": $build_secs,
97 Added: "release": "$rel"
98 Added: }
99 Added: JSON
100 Added: printf '%s\t%s\t%ss\t%s\t%s\n' \
101 Added: "$ts" "${new:0:12}" "$build_secs" "$DEPLOY_BRANCH" "$subject" \
102 Added: >>"$SHARED/deploy-history.tsv"
103 Added:
104 Added: # Atomic flip: swap the symlink in one rename so no request sees a half state.
105 Added: ln -sfn "$rel" "$SRV/current.tmp"
106 Added: mv -T "$SRV/current.tmp" "$SRV/current"
107 Added: log "current -> $rel"
108 Added:
109 Added: # Restart via the single scoped sudoers rule.
110 Added: sudo -n systemctl restart hito || fail "restart"
111 Added:
112 Added: # Health check. systemd reports active as soon as the process starts, so poll
113 Added: # the app itself. On failure, roll current back to the previous release and
114 Added: # restart, so a broken build never stays live.
115 Added: if health_ok; then
116 Added: log "healthy: $HEALTH_URL"
117 Added: elif [ -n "$prev" ] && [ -d "$prev" ]; then
118 Added: log "health check failed; rolling back to $prev"
119 Added: ln -sfn "$prev" "$SRV/current.tmp"
120 Added: mv -T "$SRV/current.tmp" "$SRV/current"
121 Added: sudo -n systemctl restart hito || true
122 Added: fail "health check (rolled back to previous release)"
123 Added: else
124 Added: fail "health check (no previous release to roll back to)"
125 Added: fi
126 Added:
127 Added: log "deployed ${new:0:12} in ${build_secs}s"
128 Added:
129 Added: # Prune all but the most recent $KEEP releases.
130 Added: ls -1dt "$RELEASES"/*/ 2>/dev/null | tail -n +$((KEEP + 1)) \
131 Added: | xargs -r rm -rf
132 Added: log "done"
133 Added: done
deploy/reset-srv-hito-root.sh
index 00000000..95065c44 000000..100755
@@ -0,0 +1,114 @@
1 Added: #!/usr/bin/env bash
2 Added: # Full reset of /srv/hito to the clean release layout.
3 Added: #
4 Added: # Wipes everything under /srv/hito EXCEPT the database and the shared opam
5 Added: # switch, which are preserved (the DB is the only unique runtime state; the
6 Added: # switch is expensive to rebuild). Result:
7 Added: #
8 Added: # /srv/hito/shared/{hito.sqlite,_opam}
9 Added: # /srv/hito/releases/<ts>/ (master, freshly built)
10 Added: # /srv/hito/current -> releases/<ts>
11 Added: #
12 Added: # Run as root: sudo bash reset-srv-hito-root.sh
13 Added: set -euo pipefail
14 Added:
15 Added: SRV=/srv/hito
16 Added: DEPLOY_USER=mpeter
17 Added: DEPLOY_GROUP=git
18 Added: BARE=/srv/git/hito.git
19 Added: DB="$SRV/shared/hito.sqlite"
20 Added: SWITCH="$SRV/shared/_opam"
21 Added:
22 Added: [ -f "$DB" ] || { echo "FATAL: database not found at $DB; aborting before any wipe"; exit 1; }
23 Added:
24 Added: echo "== 1. stop the service =="
25 Added: systemctl stop hito || true
26 Added:
27 Added: echo "== 2. back up and set aside the database and shared switch =="
28 Added: STASH=$(mktemp -d /root/hito-reset-stash.XXXXXX)
29 Added: cp -a "$DB" "$STASH/hito.sqlite" # safety copy
30 Added: echo " DB backed up to $STASH/hito.sqlite"
31 Added: mv "$DB" "$STASH/hito.sqlite.live"
32 Added: [ -d "$SWITCH" ] && mv "$SWITCH" "$STASH/_opam" && echo " switch set aside"
33 Added:
34 Added: echo "== 3. wipe everything under /srv/hito (contents only, keep the dir) =="
35 Added: # Remove all entries, including dotfiles, without following into the stash.
36 Added: find "$SRV" -mindepth 1 -maxdepth 1 -exec rm -rf {} +
37 Added: echo " /srv/hito emptied"
38 Added:
39 Added: echo "== 4. rebuild the clean skeleton =="
40 Added: mkdir -p "$SRV/shared" "$SRV/releases"
41 Added: mv "$STASH/hito.sqlite.live" "$DB"
42 Added: [ -d "$STASH/_opam" ] && mv "$STASH/_opam" "$SWITCH"
43 Added: chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$SRV/shared" "$SRV/releases"
44 Added: echo " restored shared/ (DB + switch) and empty releases/"
45 Added:
46 Added: echo "== 5. deploy master as the first clean release =="
47 Added: # Build in a staging dir OUTSIDE /srv/hito so dune's project-root search never
48 Added: # sees current or a sibling release. Publish only after a clean build.
49 Added: start=$SECONDS
50 Added: TS=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
51 Added: REL="$SRV/releases/$TS"
52 Added: STAGE=$(sudo -u "$DEPLOY_USER" mktemp -d /tmp/hito-stage.XXXXXX)
53 Added: sha=$(git --git-dir="$BARE" rev-parse refs/heads/master)
54 Added: git --git-dir="$BARE" archive "$sha" | tar -x -C "$STAGE"
55 Added: chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$STAGE"
56 Added: sudo -u "$DEPLOY_USER" -H bash -lc "
57 Added: set -euo pipefail
58 Added: export OPAMROOT=/home/$DEPLOY_USER/.opam
59 Added: cd '$STAGE'
60 Added: eval \"\$(opam env --switch='$SRV/shared' --set-switch)\"
61 Added: opam install . --deps-only --with-test -y 2>&1 | tee deploy.log
62 Added: dune build @check 2>&1 | tee -a deploy.log
63 Added: dune runtest 2>&1 | tee -a deploy.log
64 Added: dune build 2>&1 | tee -a deploy.log
65 Added: "
66 Added: build_secs=$((SECONDS - start))
67 Added: mv "$STAGE" "$REL"
68 Added: ln -sfn "$SRV/shared/hito.sqlite" "$REL/hito.sqlite"
69 Added:
70 Added: # Deploy metadata, matching the hook: provenance in the release and a durable
71 Added: # history line under shared/.
72 Added: subject=$(git --git-dir="$BARE" log -1 --format=%s "$sha")
73 Added: cat >"$REL/deploy-info.json" <<JSON
74 Added: {
75 Added: "commit": "$sha",
76 Added: "subject": $(printf '%s' "$subject" | sed 's/\\/\\\\/g; s/"/\\"/g; s/.*/"&"/'),
77 Added: "branch": "master",
78 Added: "deployed_at": "$TS",
79 Added: "build_seconds": $build_secs,
80 Added: "release": "$REL"
81 Added: }
82 Added: JSON
83 Added: printf '%s\t%s\t%ss\t%s\t%s\n' \
84 Added: "$TS" "${sha:0:12}" "$build_secs" "master" "$subject" \
85 Added: >>"$SRV/shared/deploy-history.tsv"
86 Added:
87 Added: chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$REL"
88 Added: chown "$DEPLOY_USER:$DEPLOY_GROUP" "$SRV/shared/deploy-history.tsv"
89 Added: ln -sfn "$REL" "$SRV/current.tmp"
90 Added: mv -T "$SRV/current.tmp" "$SRV/current"
91 Added: chown -h "$DEPLOY_USER:$DEPLOY_GROUP" "$SRV/current"
92 Added: echo " current -> $REL (master ${sha:0:12}, built in ${build_secs}s)"
93 Added:
94 Added: echo "== 6. start the service and health-check =="
95 Added: systemctl start hito
96 Added: HEALTH_URL="http://127.0.0.1:8080/login"
97 Added: healthy=false
98 Added: for _ in $(seq 1 10); do
99 Added: if curl -sf -o /dev/null --max-time 3 "$HEALTH_URL"; then healthy=true; break; fi
100 Added: sleep 1
101 Added: done
102 Added: if $healthy; then
103 Added: echo " hito is healthy at $HEALTH_URL"
104 Added: else
105 Added: echo " FAILED health check; recent journal:"
106 Added: journalctl -u hito -n 15 --no-pager
107 Added: exit 1
108 Added: fi
109 Added:
110 Added: echo
111 Added: echo "Done. /srv/hito now holds only shared/, releases/, current."
112 Added: echo "Safety backup of the DB remains at $STASH/hito.sqlite"
113 Added: echo "Remove it once you have confirmed the app works: rm -rf $STASH"
114 Added: ls -la "$SRV"
deploy/setup-root.sh
index 00000000..594f6b9d 000000..100755
@@ -0,0 +1,69 @@
1 Added: #!/usr/bin/env bash
2 Added: # One-time root setup for the hito push-to-deploy pipeline on the VPS.
3 Added: # Run as root: sudo bash setup-root.sh
4 Added: #
5 Added: # Idempotent: safe to re-run. It does not touch the live release or the
6 Added: # database beyond moving the DB once into the shared directory.
7 Added: set -euo pipefail
8 Added:
9 Added: DEPLOY_USER=mpeter
10 Added: DEPLOY_GROUP=git
11 Added: SRV=/srv/hito
12 Added: BARE=/srv/git/hito.git
13 Added: UNIT=/etc/systemd/system/hito.service
14 Added: SUDOERS=/etc/sudoers.d/hito-deploy
15 Added: SHARED="$SRV/shared"
16 Added: RELEASES="$SRV/releases"
17 Added:
18 Added: echo "== 1. release and shared directories =="
19 Added: mkdir -p "$RELEASES" "$SHARED"
20 Added: # Move the live database under shared/ exactly once. The unit is edited below
21 Added: # to read it from there, so a new release never orphans the data.
22 Added: if [ -f "$SRV/hito.sqlite" ] && [ ! -e "$SHARED/hito.sqlite" ]; then
23 Added: mv "$SRV/hito.sqlite" "$SHARED/hito.sqlite"
24 Added: echo " moved hito.sqlite -> $SHARED/hito.sqlite"
25 Added: fi
26 Added: chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$RELEASES" "$SHARED"
27 Added:
28 Added: echo "== 2. shared opam switch (matches existing 5.5.0) =="
29 Added: # Built once as the deploy user, reused by every release unless hito.opam
30 Added: # changes. Kept outside releases so pruning a release never deletes it.
31 Added: if [ ! -d "$SHARED/_opam" ]; then
32 Added: sudo -u "$DEPLOY_USER" -H bash -lc "
33 Added: export OPAMROOT=/home/$DEPLOY_USER/.opam
34 Added: opam switch create '$SHARED' ocaml-base-compiler.5.5.0 --no-install -y
35 Added: "
36 Added: echo " created shared switch at $SHARED/_opam"
37 Added: else
38 Added: echo " shared switch already present"
39 Added: fi
40 Added:
41 Added: echo "== 3. post-receive hook =="
42 Added: install -o "$DEPLOY_USER" -g "$DEPLOY_GROUP" -m 0755 \
43 Added: "$(dirname "$0")/post-receive" "$BARE/hooks/post-receive"
44 Added: echo " installed $BARE/hooks/post-receive"
45 Added:
46 Added: echo "== 4. scoped sudoers for restart =="
47 Added: cat > "$SUDOERS" <<SUDO
48 Added: $DEPLOY_USER ALL=(root) NOPASSWD: /usr/bin/systemctl restart hito
49 Added: SUDO
50 Added: chmod 0440 "$SUDOERS"
51 Added: visudo -c -f "$SUDOERS"
52 Added:
53 Added: echo "== 5. systemd unit -> current/ =="
54 Added: # Point ExecStart and WorkingDirectory at the current symlink, read the DB
55 Added: # from shared/, and keep the existing hardening (ReadWritePaths already /srv/hito).
56 Added: cp -a "$UNIT" "$UNIT.bak.$(date +%s)"
57 Added: sed -i \
58 Added: -e 's#^ExecStart=.*#ExecStart=/srv/hito/current/_build/default/bin/main.exe#' \
59 Added: -e 's#^WorkingDirectory=.*#WorkingDirectory=/srv/hito/current#' \
60 Added: -e 's#^Environment=HITO_DB=.*#Environment=HITO_DB=sqlite3:/srv/hito/shared/hito.sqlite#' \
61 Added: "$UNIT"
62 Added: systemctl daemon-reload
63 Added: echo " unit updated (backup kept alongside)."
64 Added:
65 Added: echo
66 Added: echo "Done. The service still runs the old in-place build until the first"
67 Added: echo "successful push flips /srv/hito/current. To go live now without a push:"
68 Added: echo " 1) su - $DEPLOY_USER and run deploy/first-release.sh (creates current/)"
69 Added: echo " 2) sudo systemctl restart hito"