| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- #!/usr/bin/env bash
- set -euo pipefail
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
- # shellcheck source=wp13-common.sh
- source "${SCRIPT_DIR}/wp13-common.sh"
- usage() {
- cat <<'EOF'
- Usage: package_offline.sh [options]
- Build a checksum-verifiable DataOps Compose offline archive.
- Options:
- --repo-root PATH Repository root.
- --output-dir PATH Destination directory (default: <repo>/dist).
- --version VALUE Package version (default: UTC timestamp).
- --skip-images Contract-test mode; omit Docker image archive.
- --help Show this help.
- EOF
- }
- REPO_ROOT="$(wp13_default_root)"
- OUTPUT_DIR=""
- VERSION="$(date -u '+%Y%m%dT%H%M%SZ')"
- SKIP_IMAGES=0
- while [[ $# -gt 0 ]]; do
- case "$1" in
- --repo-root) REPO_ROOT="$2"; shift 2 ;;
- --output-dir) OUTPUT_DIR="$2"; shift 2 ;;
- --version) VERSION="$2"; shift 2 ;;
- --skip-images) SKIP_IMAGES=1; shift ;;
- --help|-h) usage; exit 0 ;;
- *) wp13_die "unknown argument: $1" ;;
- esac
- done
- REPO_ROOT="$(cd "${REPO_ROOT}" && pwd)"
- OUTPUT_DIR="${OUTPUT_DIR:-${REPO_ROOT}/dist}"
- mkdir -p "${OUTPUT_DIR}"
- OUTPUT_DIR="$(cd "${OUTPUT_DIR}" && pwd)"
- for required in \
- deploy/docker/docker-compose.yml \
- deploy/docker/.env.example \
- database \
- migrations \
- deployment/compose; do
- [[ -e "${REPO_ROOT}/${required}" ]] \
- || wp13_die "required release input is missing: ${required}"
- done
- if ! diff -qr \
- --exclude='__pycache__' \
- --exclude='*.pyc' \
- "${REPO_ROOT}/app" "${REPO_ROOT}/deployment/app" >/dev/null; then
- wp13_die "deployment/app is not synchronised with app"
- fi
- if ! diff -qr \
- --exclude='__pycache__' \
- --exclude='*.pyc' \
- "${REPO_ROOT}/migrations" "${REPO_ROOT}/deployment/migrations" >/dev/null; then
- wp13_die "deployment/migrations is not synchronised with migrations"
- fi
- PACKAGE_NAME="dataops-platform-offline-${VERSION}"
- TEMP_DIR="$(mktemp -d)"
- trap 'rm -rf "${TEMP_DIR}"' EXIT
- BUNDLE_ROOT="${TEMP_DIR}/${PACKAGE_NAME}"
- mkdir -p \
- "${BUNDLE_ROOT}/deploy" \
- "${BUNDLE_ROOT}/operations" \
- "${BUNDLE_ROOT}/images"
- cp -R "${REPO_ROOT}/deploy/docker" "${BUNDLE_ROOT}/deploy/docker"
- cp -R "${REPO_ROOT}/database" "${BUNDLE_ROOT}/database"
- cp -R "${REPO_ROOT}/migrations" "${BUNDLE_ROOT}/migrations"
- cp -R "${REPO_ROOT}/deployment/compose/." "${BUNDLE_ROOT}/operations/"
- cp "${REPO_ROOT}/deployment/MANIFEST.md" "${BUNDLE_ROOT}/MANIFEST.md"
- find "${BUNDLE_ROOT}" -type d -name __pycache__ -prune -exec rm -rf {} +
- find "${BUNDLE_ROOT}" -type f -name '*.pyc' -delete
- COMPOSE_FILE="${BUNDLE_ROOT}/deploy/docker/docker-compose.yml"
- IMAGE_LIST="${BUNDLE_ROOT}/images/images.txt"
- wp13_require_command docker
- docker compose -f "${REPO_ROOT}/deploy/docker/docker-compose.yml" \
- config --images | LC_ALL=C sort -u >"${IMAGE_LIST}"
- {
- printf 'version=%s\n' "${VERSION}"
- printf 'created_at_utc=%s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
- printf 'source_commit=%s\n' "$(git -C "${REPO_ROOT}" rev-parse HEAD 2>/dev/null || printf unknown)"
- if [[ -n "$(git -C "${REPO_ROOT}" status --porcelain --untracked-files=no 2>/dev/null)" ]]; then
- printf 'source_worktree=dirty\n'
- else
- printf 'source_worktree=clean\n'
- fi
- printf 'compose_sha256=%s\n' "$(wp13_sha256_file "${COMPOSE_FILE}")"
- printf 'images_included=%s\n' "$([[ "${SKIP_IMAGES}" -eq 1 ]] && printf no || printf yes)"
- while IFS= read -r image; do
- [[ -n "${image}" ]] || continue
- image_id="$(docker image inspect -f '{{.Id}}' "${image}" 2>/dev/null || printf missing)"
- printf 'image=%s|%s\n' "${image}" "${image_id}"
- done <"${IMAGE_LIST}"
- } >"${BUNDLE_ROOT}/release-manifest.txt"
- if [[ "${SKIP_IMAGES}" -eq 0 ]]; then
- while IFS= read -r image; do
- [[ -n "${image}" ]] || continue
- docker image inspect "${image}" >/dev/null 2>&1 \
- || wp13_die "cannot package missing image: ${image}"
- done <"${IMAGE_LIST}"
- # shellcheck disable=SC2046
- docker save -o "${BUNDLE_ROOT}/images/dataops-images.tar" $(cat "${IMAGE_LIST}")
- fi
- wp13_write_checksums "${BUNDLE_ROOT}"
- ARCHIVE="${OUTPUT_DIR}/${PACKAGE_NAME}.tar.gz"
- tar -czf "${ARCHIVE}" -C "${TEMP_DIR}" "${PACKAGE_NAME}"
- wp13_log "offline package created: ${ARCHIVE}"
|