wp13-common.sh 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #!/usr/bin/env bash
  2. set -euo pipefail
  3. WP13_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  4. export COMPOSE_PROGRESS="${COMPOSE_PROGRESS:-plain}"
  5. wp13_log() {
  6. printf '[WP13] %s\n' "$*"
  7. }
  8. wp13_die() {
  9. printf '[WP13] ERROR: %s\n' "$*" >&2
  10. exit 1
  11. }
  12. wp13_require_command() {
  13. command -v "$1" >/dev/null 2>&1 || wp13_die "required command not found: $1"
  14. }
  15. wp13_default_root() {
  16. if [[ -f "${WP13_SCRIPT_DIR}/../../deploy/docker/docker-compose.yml" ]]; then
  17. (cd "${WP13_SCRIPT_DIR}/../.." && pwd)
  18. return
  19. fi
  20. if [[ -f "${WP13_SCRIPT_DIR}/../deploy/docker/docker-compose.yml" ]]; then
  21. (cd "${WP13_SCRIPT_DIR}/.." && pwd)
  22. return
  23. fi
  24. (cd "${WP13_SCRIPT_DIR}/.." && pwd)
  25. }
  26. wp13_sha256_file() {
  27. local file="$1"
  28. if command -v sha256sum >/dev/null 2>&1; then
  29. sha256sum "${file}" | awk '{print $1}'
  30. else
  31. shasum -a 256 "${file}" | awk '{print $1}'
  32. fi
  33. }
  34. wp13_write_checksums() {
  35. local root="$1"
  36. local output="${root}/checksums.sha256"
  37. : >"${output}"
  38. while IFS= read -r relative; do
  39. printf '%s %s\n' \
  40. "$(wp13_sha256_file "${root}/${relative}")" \
  41. "${relative}" >>"${output}"
  42. done < <(
  43. cd "${root}"
  44. find . -type f \
  45. ! -name checksums.sha256 \
  46. ! -path '*/__pycache__/*' \
  47. ! -name '*.pyc' \
  48. -print \
  49. | sed 's#^\./##' \
  50. | LC_ALL=C sort
  51. )
  52. }
  53. wp13_verify_checksums() {
  54. local root="$1"
  55. [[ -f "${root}/checksums.sha256" ]] \
  56. || wp13_die "checksum manifest not found: ${root}/checksums.sha256"
  57. if command -v sha256sum >/dev/null 2>&1; then
  58. (cd "${root}" && sha256sum -c checksums.sha256 >/dev/null) \
  59. || wp13_die "checksum verification failed"
  60. else
  61. (cd "${root}" && shasum -a 256 -c checksums.sha256 >/dev/null) \
  62. || wp13_die "checksum verification failed"
  63. fi
  64. wp13_log "checksum verification passed"
  65. }
  66. wp13_compose() {
  67. local compose_file="$1"
  68. local project_name="$2"
  69. local env_file="$3"
  70. shift 3
  71. if [[ -n "${env_file}" ]]; then
  72. docker compose \
  73. --env-file "${env_file}" \
  74. -p "${project_name}" \
  75. -f "${compose_file}" \
  76. "$@"
  77. else
  78. docker compose \
  79. -p "${project_name}" \
  80. -f "${compose_file}" \
  81. "$@"
  82. fi
  83. }
  84. wp13_project_container_ids() {
  85. local project_name="$1"
  86. docker ps -aq \
  87. --filter "label=com.docker.compose.project=${project_name}"
  88. }
  89. wp13_project_running_ids() {
  90. local project_name="$1"
  91. docker ps -q \
  92. --filter "label=com.docker.compose.project=${project_name}"
  93. }
  94. wp13_assert_no_project_containers() {
  95. local project_name="$1"
  96. if [[ -n "$(wp13_project_container_ids "${project_name}")" ]]; then
  97. wp13_die "destination project already exists: ${project_name}"
  98. fi
  99. }
  100. wp13_wait_for_project() {
  101. local project_name="$1"
  102. local timeout_seconds="${2:-300}"
  103. local started_at
  104. started_at="$(date +%s)"
  105. while :; do
  106. local ids
  107. ids="$(wp13_project_container_ids "${project_name}")"
  108. [[ -n "${ids}" ]] || wp13_die "project has no containers: ${project_name}"
  109. local pending=0
  110. local failed=0
  111. local container_id
  112. for container_id in ${ids}; do
  113. local state health exit_code
  114. state="$(docker inspect -f '{{.State.Status}}' "${container_id}")"
  115. health="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "${container_id}")"
  116. exit_code="$(docker inspect -f '{{.State.ExitCode}}' "${container_id}")"
  117. if [[ "${state}" == "exited" && "${exit_code}" == "0" ]]; then
  118. continue
  119. fi
  120. if [[ "${state}" == "exited" || "${state}" == "dead" ]]; then
  121. failed=1
  122. break
  123. fi
  124. if [[ "${state}" != "running" ]]; then
  125. pending=1
  126. continue
  127. fi
  128. if [[ "${health}" != "none" && "${health}" != "healthy" ]]; then
  129. pending=1
  130. fi
  131. done
  132. [[ "${failed}" -eq 0 ]] || wp13_die "project contains a failed container: ${project_name}"
  133. if [[ "${pending}" -eq 0 ]]; then
  134. wp13_log "project is healthy: ${project_name}"
  135. return 0
  136. fi
  137. if (( $(date +%s) - started_at >= timeout_seconds )); then
  138. wp13_die "project health timeout after ${timeout_seconds}s: ${project_name}"
  139. fi
  140. sleep 5
  141. done
  142. }
  143. wp13_safe_archive_name() {
  144. printf '%s' "$1" | tr -c 'A-Za-z0-9._-' '_'
  145. }