#!/bin/bash
#
# backup_gitlab.sh
#
# 功能：
# 1. 创建 GitLab 备份并保存到本地（含校验）
# 2. （可选）备份 gitlab.rb & gitlab-secrets.json
# 3. 将备份文件 + 上述配置文件 一并 SCP 传输到远程服务器
# 4. 成功或失败都进行飞书告警
# 5. 记录日志到 /var/log/gitlab_backup.log
# 6. 清理本地的 .tar(.gz) 和 gitlab.rb.*、gitlab-secrets.json.* 文件

# 若在 Debian/Ubuntu 出现 EOF 报错，可执行：
#   dos2unix /usr/local/bin/backup_gitlab.sh

# ========== 1. 基础环境、变量设置 ==========

# 避免中文乱码 (确保已安装 zh_CN.UTF-8 或其他 UTF-8 locale)
export LANG=zh_CN.UTF-8
export LC_ALL=zh_CN.UTF-8

# 项目标识，用于飞书消息区分
PROJECT_NAME="【GitLab备份】"

# GitLab 本地备份目录 (需与 gitlab.rb 中相同)
GITLAB_BACKUP_PATH="/data/backups"

# 远程服务器信息
REMOTE_HOST="xx.xx.xx.xx"
REMOTE_USER="root"
REMOTE_DIR="/data/backup"

# 飞书自定义机器人 Webhook
FEISHU_WEBHOOK="https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxxxxxx"

# (可选) 是否备份 gitlab.rb & gitlab-secrets.json
BACKUP_GITLAB_CONFIG=true

# 本地日志文件
LOG_FILE="/var/log/gitlab_backup.log"

# ========== 2. 日志输出到屏幕 & 追加到日志文件 ==========
exec > >(tee -a "${LOG_FILE}") 2>&1

# ========== 3. 飞书通知函数 (HereDoc 避免引号冲突) ==========
send_feishu_message() {
    local message_content="$1"
    curl -s -X POST "${FEISHU_WEBHOOK}" \
         -H "Content-Type: application/json" \
         -d @- <<EOF
{
  "msg_type": "text",
  "content": {
    "text": "$message_content"
  }
}
EOF
}

# ========== 4. 开始执行主逻辑 ==========

echo "=========================================================="
echo "[INFO] $(date '+%F %T') 开始执行 ${PROJECT_NAME}脚本..."

# 4.1 创建 GitLab 备份
echo "[INFO] 正在创建 GitLab 备份..."
gitlab-backup create STRATEGY=copy GZIP_RSYNCABLE=yes
if [ $? -ne 0 ]; then
    echo "[ERROR] GitLab 备份创建失败！"
    send_feishu_message "${PROJECT_NAME}备份创建失败，请立即检查。"
    exit 1
fi

# 4.2 查找最新生成的备份文件
LATEST_BACKUP_FILE=$(ls -t "${GITLAB_BACKUP_PATH}"/*gitlab_backup.tar* 2>/dev/null | head -n 1)
if [ -z "${LATEST_BACKUP_FILE}" ]; then
    echo "[ERROR] 未找到 GitLab 备份文件，请检查。"
    send_feishu_message "${PROJECT_NAME}备份文件丢失，请立即检查。"
    exit 1
fi
echo "[INFO] 找到最新的备份文件：${LATEST_BACKUP_FILE}"

# 4.3 重命名备份文件 (可用 .tar/.tar.gz 后缀)
DATE_STR=$(date +'%Y%m%d%H%M%S')
NEW_BACKUP_NAME="gitlab-backup-${DATE_STR}.tar"

mv "${LATEST_BACKUP_FILE}" "${GITLAB_BACKUP_PATH}/${NEW_BACKUP_NAME}"
if [ $? -ne 0 ]; then
    echo "[ERROR] 重命名备份文件失败！"
    send_feishu_message "${PROJECT_NAME}重命名备份文件失败，请立即检查。"
    exit 1
fi
echo "[INFO] 备份文件已重命名为：${NEW_BACKUP_NAME}"

# 4.4 校验备份文件完整性
echo "[INFO] 正在校验备份文件完整性..."
tar -tf "${GITLAB_BACKUP_PATH}/${NEW_BACKUP_NAME}" >/dev/null 2>&1
if [ $? -ne 0 ]; then
    echo "[ERROR] 备份文件损坏或不完整！"
    send_feishu_message "${PROJECT_NAME}备份文件损坏，请立即检查。"
    exit 1
fi
echo "[INFO] 备份文件校验通过。"

# 4.5 (可选) 备份 gitlab.rb & gitlab-secrets.json
GITLAB_RB_BACKUP=""
GITLAB_SECRETS_BACKUP=""
if [ "${BACKUP_GITLAB_CONFIG}" = true ]; then
    if [ -f /etc/gitlab/gitlab.rb ]; then
        GITLAB_RB_BACKUP="gitlab.rb.${DATE_STR}"
        cp /etc/gitlab/gitlab.rb "${GITLAB_BACKUP_PATH}/${GITLAB_RB_BACKUP}"
        echo "[INFO] 已备份 gitlab.rb 为：${GITLAB_RB_BACKUP}"
    fi
    if [ -f /etc/gitlab/gitlab-secrets.json ]; then
        GITLAB_SECRETS_BACKUP="gitlab-secrets.json.${DATE_STR}"
        cp /etc/gitlab/gitlab-secrets.json "${GITLAB_BACKUP_PATH}/${GITLAB_SECRETS_BACKUP}"
        echo "[INFO] 已备份 gitlab-secrets.json 为：${GITLAB_SECRETS_BACKUP}"
    fi
fi

# 4.6 传输到远程服务器 (tar 文件 + gitlab.rb.* + gitlab-secrets.json.*)
echo "[INFO] 开始将备份文件及配置文件传输到 ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR} ..."

# 先传 tar
scp -o StrictHostKeyChecking=no \
    "${GITLAB_BACKUP_PATH}/${NEW_BACKUP_NAME}" \
    "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/"

# 若 gitlab.rb.* 存在，则传
if [ -n "$GITLAB_RB_BACKUP" ] && [ -f "${GITLAB_BACKUP_PATH}/${GITLAB_RB_BACKUP}" ]; then
    scp -o StrictHostKeyChecking=no \
        "${GITLAB_BACKUP_PATH}/${GITLAB_RB_BACKUP}" \
        "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/"
fi

# 若 gitlab-secrets.json.* 存在，则传
if [ -n "$GITLAB_SECRETS_BACKUP" ] && [ -f "${GITLAB_BACKUP_PATH}/${GITLAB_SECRETS_BACKUP}" ]; then
    scp -o StrictHostKeyChecking=no \
        "${GITLAB_BACKUP_PATH}/${GITLAB_SECRETS_BACKUP}" \
        "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/"
fi

# 检查 SCP 是否成功（这里简单假定只要最后一次 scp 没失败就算成功）
if [ $? -ne 0 ]; then
    echo "[ERROR] SCP 传输失败，请检查网络或 SSH 配置。"
    send_feishu_message "${PROJECT_NAME}传输失败，无法上传至远程服务器，请立即检查。"
    exit 1
fi

echo "[INFO] 成功将备份文件(及配置文件)传输到远程服务器。"

# 4.7 清理本地目录下的 .tar/.tar.gz/gitlab.rb.*/gitlab-secrets.json.* 文件
echo "[INFO] 正在清理本地目录中的备份文件 (.tar, .tar.gz, gitlab.rb.*, gitlab-secrets.json.*)..."
rm -f "${GITLAB_BACKUP_PATH}"/*.tar \
      "${GITLAB_BACKUP_PATH}"/*.tar.gz \
      "${GITLAB_BACKUP_PATH}"/gitlab.rb.* \
      "${GITLAB_BACKUP_PATH}"/gitlab-secrets.json.* 2>/dev/null
echo "[INFO] 清理完成。"

# 4.8 发送成功通知 & 脚本结束
echo "[INFO] $(date '+%F %T') ${PROJECT_NAME}备份与传输全部完成。"
send_feishu_message "${PROJECT_NAME}备份 & 传输成功：${NEW_BACKUP_NAME}"
echo "=========================================================="
exit 0

