#!/usr/bin/env bash # # 打包 deployment/ 为可上传的 tar.gz 发布包 # 用法: cd deployment && bash package_release.sh # set -euo pipefail export COPYFILE_DISABLE=1 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" VERSION="${DATAOPS_RELEASE_VERSION:-$(date +%Y%m%d)}" ARCHIVE_NAME="dataops-platform-release-${VERSION}.tar.gz" OUTPUT_DIR="${DATAOPS_RELEASE_OUTPUT_DIR:-${ROOT_DIR}/dist}" required=( "${SCRIPT_DIR}/app" "${SCRIPT_DIR}/database" "${SCRIPT_DIR}/migrations" "${SCRIPT_DIR}/alembic.ini" "${SCRIPT_DIR}/requirements.txt" "${SCRIPT_DIR}/wsgi.py" "${SCRIPT_DIR}/gunicorn_config.py" "${SCRIPT_DIR}/deploy_dataops.sh" "${SCRIPT_DIR}/scripts/run_dataops.sh" "${ROOT_DIR}/scripts/edge_gateway_admin.py" "${ROOT_DIR}/deploy/edge/docker-compose.edge.yml" "${SCRIPT_DIR}/scripts/scan_release_secrets.py" "${ROOT_DIR}/docs/runbooks/EDGE_GATEWAY_OPERATIONS.md" "${ROOT_DIR}/docs/phase3/P3_WP04_EDGE_GATEWAY.md" "${ROOT_DIR}/docs/validation/P3_WP04_EDGE_GATEWAY_EVIDENCE.md" "${ROOT_DIR}/docs/validation/P3_WP04_FAILURE_INJECTION.json" "${ROOT_DIR}/docs/architecture/OPENAPI.yaml" "${SCRIPT_DIR}/dataops.env" ) for path in "${required[@]}"; do if [[ ! -e "${path}" ]]; then echo "缺少发布文件: ${path}" >&2 echo "请先执行: bash deployment/sync_release.sh" >&2 exit 1 fi done mkdir -p "${OUTPUT_DIR}" TMP_DIR="$(mktemp -d)" trap 'rm -rf "${TMP_DIR}"' EXIT RELEASE_ROOT="${TMP_DIR}/dataops-platform" mkdir -p "${RELEASE_ROOT}" copy_into_release() { local src="$1" local rel="$2" if [[ -e "${src}" ]]; then mkdir -p "$(dirname "${RELEASE_ROOT}/${rel}")" cp -a "${src}" "${RELEASE_ROOT}/${rel}" fi } copy_into_release "${SCRIPT_DIR}/app" "app" copy_into_release "${SCRIPT_DIR}/database" "database" copy_into_release "${SCRIPT_DIR}/migrations" "migrations" copy_into_release "${SCRIPT_DIR}/config" "config" copy_into_release "${SCRIPT_DIR}/scripts" "scripts" copy_into_release "${ROOT_DIR}/scripts/edge_gateway_admin.py" "scripts/edge_gateway_admin.py" copy_into_release "${ROOT_DIR}/deploy/edge" "deploy/edge" copy_into_release "${ROOT_DIR}/docs/runbooks/EDGE_GATEWAY_OPERATIONS.md" "docs/runbooks/EDGE_GATEWAY_OPERATIONS.md" copy_into_release "${ROOT_DIR}/docs/phase3/P3_WP04_EDGE_GATEWAY.md" "docs/phase3/P3_WP04_EDGE_GATEWAY.md" copy_into_release "${ROOT_DIR}/docs/validation/P3_WP04_EDGE_GATEWAY_EVIDENCE.md" "docs/validation/P3_WP04_EDGE_GATEWAY_EVIDENCE.md" copy_into_release "${ROOT_DIR}/docs/validation/P3_WP04_FAILURE_INJECTION.json" "docs/validation/P3_WP04_FAILURE_INJECTION.json" copy_into_release "${ROOT_DIR}/docs/architecture/OPENAPI.yaml" "docs/architecture/OPENAPI.yaml" copy_into_release "${SCRIPT_DIR}/requirements.txt" "requirements.txt" copy_into_release "${SCRIPT_DIR}/alembic.ini" "alembic.ini" copy_into_release "${SCRIPT_DIR}/wsgi.py" "wsgi.py" copy_into_release "${SCRIPT_DIR}/gunicorn_config.py" "gunicorn_config.py" copy_into_release "${SCRIPT_DIR}/__init__.py" "__init__.py" copy_into_release "${SCRIPT_DIR}/deploy_dataops.sh" "deploy_dataops.sh" copy_into_release "${SCRIPT_DIR}/dataops.env" "dataops.env" copy_into_release "${SCRIPT_DIR}/.env.production.example" ".env.production.example" copy_into_release "${SCRIPT_DIR}/README.md" "README.md" copy_into_release "${SCRIPT_DIR}/DEPLOYMENT_GUIDE.md" "DEPLOYMENT_GUIDE.md" copy_into_release "${SCRIPT_DIR}/CHECKLIST.md" "CHECKLIST.md" copy_into_release "${SCRIPT_DIR}/MANIFEST.md" "MANIFEST.md" # Runtime bytecode and AppleDouble metadata are never release inputs. find "${RELEASE_ROOT}" -type f \( -name '*.pyc' -o -name '*.pyo' -o -name '._*' \) -delete find "${RELEASE_ROOT}" -type d -name '__pycache__' -empty -delete # Scan every remaining regular file as UTF-8 text. This rejects encrypted or # unencrypted private-key blocks, binary/PKCS#12 stores, API-secret shapes and # literal credentials while permitting explicit replacement templates. "${PYTHON_BIN:-python3}" "${SCRIPT_DIR}/scripts/scan_release_secrets.py" "${RELEASE_ROOT}" ( cd "${RELEASE_ROOT}" find . -type f ! -name SHA256SUMS -print | LC_ALL=C sort | while IFS= read -r item; do shasum -a 256 "${item}" done ) > "${RELEASE_ROOT}/SHA256SUMS" tar -czf "${OUTPUT_DIR}/${ARCHIVE_NAME}" -C "${TMP_DIR}" dataops-platform echo "发布包已生成: ${OUTPUT_DIR}/${ARCHIVE_NAME}" echo "上传后在服务器执行:" echo " tar -xzf ${ARCHIVE_NAME}" echo " cd dataops-platform" echo " sudo bash deploy_dataops.sh"