feat: establish Quant OS production-80 architecture
This commit is contained in:
Executable
+109
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "$#" -lt 1 || "$#" -gt 2 ]]; then
|
||||
echo "usage: $0 <40-char-git-sha> [web-root]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
release_sha="$1"
|
||||
web_root="${2:-/srv/www/quant-os}"
|
||||
|
||||
if [[ ! "${release_sha}" =~ ^[0-9a-f]{40}$ ]]; then
|
||||
echo "release SHA must be a 40-character lowercase Git SHA" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ "${web_root}" != /* || "${web_root}" == "/" ]]; then
|
||||
echo "web root must be an explicit absolute non-root path" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ ! -d "${web_root}" ]]; then
|
||||
echo "web root does not exist: ${web_root}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
lock_dir="${web_root}/.status-deploy.lock"
|
||||
lock_acquired=false
|
||||
next_link=""
|
||||
next_link_created=false
|
||||
|
||||
cleanup() {
|
||||
exit_status="$?"
|
||||
if [[ "${next_link_created}" == "true" && -L "${next_link}" ]]; then
|
||||
rm -f "${next_link}"
|
||||
fi
|
||||
if [[ "${lock_acquired}" == "true" ]]; then
|
||||
rmdir "${lock_dir}" 2>/dev/null || true
|
||||
fi
|
||||
exit "${exit_status}"
|
||||
}
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
if [[ "${QUANT_OS_STATUS_DEPLOY_LOCK_HELD:-0}" == "1" ]]; then
|
||||
if [[ ! -d "${lock_dir}" || -L "${lock_dir}" ]]; then
|
||||
echo "caller asserted a deployment lock that is not held" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
if ! mkdir "${lock_dir}" 2>/dev/null; then
|
||||
echo "another status deployment or activation holds ${lock_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
lock_acquired=true
|
||||
fi
|
||||
|
||||
release_dir="${web_root}/releases/${release_sha}"
|
||||
if [[ ! -d "${release_dir}" || -L "${release_dir}" ]]; then
|
||||
echo "release must be a regular directory: ${release_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
release_entries=()
|
||||
while IFS= read -r -d '' entry; do
|
||||
release_entries+=("${entry}")
|
||||
done < <(find "${release_dir}" -mindepth 1 -maxdepth 1 -print0 2>/dev/null)
|
||||
if [[ "${#release_entries[@]}" != "2" ]]; then
|
||||
echo "release must contain exactly index.html and status-data.js" >&2
|
||||
exit 1
|
||||
fi
|
||||
for required in index.html status-data.js; do
|
||||
if [[ ! -f "${release_dir}/${required}" || -L "${release_dir}/${required}" ]]; then
|
||||
echo "release must contain a regular non-symlink ${required}" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
for entry in "${release_entries[@]}"; do
|
||||
case "$(basename "${entry}")" in
|
||||
index.html|status-data.js)
|
||||
;;
|
||||
*)
|
||||
echo "unexpected release entry: $(basename "${entry}")" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
next_link="${web_root}/.status-next-${release_sha}"
|
||||
if [[ -e "${next_link}" || -L "${next_link}" ]]; then
|
||||
echo "temporary activation link already exists: ${next_link}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ln -s "releases/${release_sha}" "${next_link}"
|
||||
next_link_created=true
|
||||
if [[ -e "${web_root}/status" && ! -L "${web_root}/status" ]]; then
|
||||
echo "active status path exists and is not a symlink" >&2
|
||||
exit 1
|
||||
fi
|
||||
if mv --version >/dev/null 2>&1; then
|
||||
mv -Tf "${next_link}" "${web_root}/status"
|
||||
else
|
||||
mv -fh "${next_link}" "${web_root}/status"
|
||||
fi
|
||||
next_link_created=false
|
||||
|
||||
active_target="$(readlink "${web_root}/status")"
|
||||
if [[ "${active_target}" != "releases/${release_sha}" ]]; then
|
||||
echo "active release verification failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "activated ${release_sha}"
|
||||
Reference in New Issue
Block a user