This commit is contained in:
Executable
+114
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
deploy_user="labyricorn-deploy"
|
||||
deploy_home="/srv/labyricorn"
|
||||
|
||||
if [[ "$(id -u)" -eq 0 ]]; then
|
||||
exec sudo -u "$deploy_user" env \
|
||||
HOME="$deploy_home" \
|
||||
PATH="$deploy_home/.local/bin:/usr/local/bin:/usr/bin:/bin" \
|
||||
"$0" "$@"
|
||||
fi
|
||||
|
||||
if [[ "$(id -un)" != "$deploy_user" ]]; then
|
||||
printf 'deploy-labyricorn must run as root or %s\n' "$deploy_user" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
repo="$deploy_home/repo"
|
||||
releases="$deploy_home/releases"
|
||||
current="$deploy_home/current"
|
||||
logs="$deploy_home/logs"
|
||||
project_cache="$deploy_home/project-cache"
|
||||
lektor="$deploy_home/.local/bin/lektor"
|
||||
lektor_python="$deploy_home/.local/pipx/venvs/lektor/bin/python"
|
||||
lock_file="$logs/deploy.lock"
|
||||
log_file="$logs/deploy.log"
|
||||
release_dir=""
|
||||
|
||||
log() {
|
||||
printf '%s %s\n' "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" "$*" | tee -a "$log_file"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
status=$?
|
||||
if [[ "$status" -ne 0 && -n "$release_dir" && -d "$release_dir" ]]; then
|
||||
rm -rf -- "$release_dir"
|
||||
fi
|
||||
if [[ "$status" -ne 0 ]]; then
|
||||
log "deployment failed status=$status"
|
||||
fi
|
||||
exit "$status"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
mkdir -p "$releases" "$logs" "$project_cache"
|
||||
exec 9>"$lock_file"
|
||||
if ! flock -n 9; then
|
||||
log "deployment skipped reason=lock-held"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ -n "$(git -C "$repo" status --porcelain)" ]]; then
|
||||
log "deployment refused reason=dirty-working-tree"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "deployment started"
|
||||
git -C "$repo" fetch --prune origin
|
||||
git -C "$repo" rev-parse --verify --quiet refs/remotes/origin/main >/dev/null
|
||||
git -C "$repo" switch main
|
||||
git -C "$repo" reset --hard origin/main
|
||||
|
||||
site_commit="$(git -C "$repo" rev-parse HEAD)"
|
||||
release_name="$(date -u +'%Y%m%dT%H%M%SZ')-${site_commit:0:12}"
|
||||
release_dir="$releases/$release_name"
|
||||
|
||||
if [[ ! -x "$lektor" || ! -x "$lektor_python" ]]; then
|
||||
log "deployment refused reason=missing-lektor-runtime"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$lektor_python" "$repo/scripts/build_with_projects.py" \
|
||||
--site-root "$repo" \
|
||||
--cache-path "$project_cache" \
|
||||
--output-path "$release_dir" \
|
||||
--lektor "$lektor"
|
||||
|
||||
test -f "$release_dir/index.html"
|
||||
test -f "$release_dir/.labyricorn-projects.json"
|
||||
printf '%s\n' "$site_commit" >"$release_dir/.labyricorn-commit"
|
||||
|
||||
manifest_signature() {
|
||||
"$lektor_python" -c 'import json,sys; d=json.load(open(sys.argv[1], encoding="utf-8")); p={k:{"commit":v["commit"],"metadata_digest":v["metadata_digest"]} for k,v in d.get("projects",{}).items()}; print(json.dumps({"site_commit":d.get("site_commit"),"projects":p},sort_keys=True,separators=(",",":")))' "$1"
|
||||
}
|
||||
|
||||
if [[ -f "$current/.labyricorn-projects.json" ]]; then
|
||||
new_signature="$(manifest_signature "$release_dir/.labyricorn-projects.json")"
|
||||
current_signature="$(manifest_signature "$current/.labyricorn-projects.json")"
|
||||
if [[ "$new_signature" == "$current_signature" ]]; then
|
||||
rm -rf -- "$release_dir"
|
||||
release_dir=""
|
||||
log "deployment unchanged commit=$site_commit"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
chmod -R u=rwX,go=rX "$release_dir"
|
||||
ln -sfn "releases/$release_name" "$deploy_home/current.next"
|
||||
mv -Tf "$deploy_home/current.next" "$current"
|
||||
release_dir=""
|
||||
|
||||
mapfile -t old_releases < <(
|
||||
find "$releases" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %p\n' \
|
||||
| sort -nr \
|
||||
| awk 'NR > 5 {sub(/^[^ ]+ /, ""); print}'
|
||||
)
|
||||
for old_release in "${old_releases[@]}"; do
|
||||
if [[ "$(readlink -f "$old_release")" != "$(readlink -f "$current")" ]]; then
|
||||
rm -rf -- "$old_release"
|
||||
fi
|
||||
done
|
||||
|
||||
log "deployment succeeded release=$release_name commit=$site_commit"
|
||||
Reference in New Issue
Block a user