253 lines
7.3 KiB
Python
253 lines
7.3 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
自动化部署脚本
|
||
功能:更新mkdocs.yml -> Git提交推送 -> 服务器拉取并重启
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
import json
|
||
import subprocess
|
||
import argparse
|
||
from pathlib import Path
|
||
|
||
# 颜色输出
|
||
class Colors:
|
||
RED = '\033[91m'
|
||
GREEN = '\033[92m'
|
||
YELLOW = '\033[93m'
|
||
CYAN = '\033[96m'
|
||
RESET = '\033[0m'
|
||
|
||
def print_info(msg):
|
||
print(f"{Colors.CYAN}{msg}{Colors.RESET}")
|
||
|
||
def print_success(msg):
|
||
print(f"{Colors.GREEN}✓ {msg}{Colors.RESET}")
|
||
|
||
def print_error(msg):
|
||
print(f"{Colors.RED}✗ {msg}{Colors.RESET}")
|
||
|
||
def print_warning(msg):
|
||
print(f"{Colors.YELLOW}⚠ {msg}{Colors.RESET}")
|
||
|
||
def run_command(cmd, check=True, shell=False):
|
||
"""执行命令"""
|
||
try:
|
||
if isinstance(cmd, str):
|
||
cmd = cmd.split()
|
||
result = subprocess.run(
|
||
cmd,
|
||
check=check,
|
||
shell=shell,
|
||
capture_output=True,
|
||
text=True,
|
||
encoding='utf-8'
|
||
)
|
||
return result.returncode == 0, result.stdout, result.stderr
|
||
except subprocess.CalledProcessError as e:
|
||
return False, e.stdout, e.stderr
|
||
except Exception as e:
|
||
return False, "", str(e)
|
||
|
||
def load_config():
|
||
"""加载配置文件"""
|
||
config_file = Path("deploy_config.json")
|
||
if config_file.exists():
|
||
try:
|
||
with open(config_file, 'r', encoding='utf-8') as f:
|
||
return json.load(f)
|
||
except Exception as e:
|
||
print_warning(f"加载配置文件失败: {e}")
|
||
return {}
|
||
|
||
def step1_update_mkdocs(script_path="add_docs_to_mkdocs.py"):
|
||
"""步骤1: 更新mkdocs.yml"""
|
||
print_info("=" * 50)
|
||
print_info("步骤1: 更新mkdocs.yml")
|
||
print_info("=" * 50)
|
||
|
||
if not Path(script_path).exists():
|
||
print_error(f"找不到脚本: {script_path}")
|
||
return False
|
||
|
||
success, stdout, stderr = run_command([sys.executable, script_path])
|
||
if success:
|
||
print_success("mkdocs.yml更新成功")
|
||
if stdout:
|
||
print(stdout)
|
||
return True
|
||
else:
|
||
print_error("更新mkdocs.yml失败")
|
||
if stderr:
|
||
print_error(stderr)
|
||
return False
|
||
|
||
def step2_git_operations(commit_message, branch="master", remote="origin"):
|
||
"""步骤2: Git操作"""
|
||
print_info("")
|
||
print_info("=" * 50)
|
||
print_info("步骤2: Git提交和推送")
|
||
print_info("=" * 50)
|
||
|
||
# 检查是否有变更
|
||
print_info("检查Git状态...")
|
||
success, stdout, _ = run_command(["git", "status", "--porcelain"])
|
||
if not stdout.strip():
|
||
print_info("没有文件变更,跳过Git操作")
|
||
return True
|
||
|
||
print_info("发现以下变更:")
|
||
success, stdout, _ = run_command(["git", "status", "--short"])
|
||
print(stdout)
|
||
|
||
# 添加文件
|
||
print_info("添加文件到Git...")
|
||
success, _, stderr = run_command(["git", "add", "."])
|
||
if not success:
|
||
print_error("Git add 失败")
|
||
if stderr:
|
||
print_error(stderr)
|
||
return False
|
||
print_success("文件已添加到暂存区")
|
||
|
||
# 提交
|
||
print_info("提交变更...")
|
||
success, _, stderr = run_command(["git", "commit", "-m", commit_message])
|
||
if not success:
|
||
print_error("Git commit 失败")
|
||
if stderr:
|
||
print_error(stderr)
|
||
return False
|
||
print_success("变更已提交")
|
||
|
||
# 推送
|
||
print_info("推送到远程仓库...")
|
||
success, _, stderr = run_command(["git", "push", remote, branch])
|
||
if not success:
|
||
print_error("Git push 失败")
|
||
if stderr:
|
||
print_error(stderr)
|
||
return False
|
||
print_success("代码已推送到远程仓库")
|
||
|
||
return True
|
||
|
||
def step3_server_operations(server_user, server_host, server_path):
|
||
"""步骤3: 服务器操作"""
|
||
print_info("")
|
||
print_info("=" * 50)
|
||
print_info("步骤3: 服务器拉取代码并重启服务")
|
||
print_info("=" * 50)
|
||
|
||
if not server_user or not server_host:
|
||
print_info("未配置服务器信息,跳过服务器操作")
|
||
print_info("")
|
||
print_info("使用方法:")
|
||
print_info(" python deploy.py --server-user <用户> --server-host <地址>")
|
||
print_info("")
|
||
print_info("或手动执行:")
|
||
print_info(f" ssh user@host 'cd {server_path} && git pull origin master && docker-compose restart'")
|
||
return True
|
||
|
||
print_info(f"连接到服务器: {server_user}@{server_host}")
|
||
print_info(f"执行命令: cd {server_path} && git pull origin master && docker-compose restart")
|
||
|
||
remote_cmd = f"cd {server_path} && git pull origin master && docker-compose restart"
|
||
ssh_cmd = ["ssh", f"{server_user}@{server_host}", remote_cmd]
|
||
|
||
success, stdout, stderr = run_command(ssh_cmd)
|
||
if success:
|
||
print_success("服务器代码已更新,服务已重启")
|
||
if stdout:
|
||
print(stdout)
|
||
return True
|
||
else:
|
||
print_error("服务器操作失败")
|
||
if stderr:
|
||
print_error(stderr)
|
||
print_warning("提示: 请确保已配置SSH密钥,或手动执行服务器命令")
|
||
return False
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(description="自动化部署脚本")
|
||
parser.add_argument(
|
||
"-m", "--message",
|
||
default="更新文档",
|
||
help="Git提交信息(默认: 更新文档)"
|
||
)
|
||
parser.add_argument(
|
||
"--server-user",
|
||
help="服务器用户名"
|
||
)
|
||
parser.add_argument(
|
||
"--server-host",
|
||
help="服务器地址"
|
||
)
|
||
parser.add_argument(
|
||
"--server-path",
|
||
default="~/devops/mkdocs",
|
||
help="服务器路径(默认: ~/devops/mkdocs)"
|
||
)
|
||
parser.add_argument(
|
||
"--skip-mkdocs",
|
||
action="store_true",
|
||
help="跳过mkdocs.yml更新"
|
||
)
|
||
parser.add_argument(
|
||
"--skip-git",
|
||
action="store_true",
|
||
help="跳过Git操作"
|
||
)
|
||
parser.add_argument(
|
||
"--skip-server",
|
||
action="store_true",
|
||
help="跳过服务器操作"
|
||
)
|
||
|
||
args = parser.parse_args()
|
||
|
||
# 加载配置
|
||
config = load_config()
|
||
server_config = config.get("server", {})
|
||
git_config = config.get("git", {})
|
||
|
||
# 使用配置或参数
|
||
server_user = args.server_user or server_config.get("user", "")
|
||
server_host = args.server_host or server_config.get("host", "")
|
||
server_path = args.server_path or server_config.get("path", "~/devops/mkdocs")
|
||
branch = git_config.get("branch", "master")
|
||
remote = git_config.get("remote", "origin")
|
||
|
||
try:
|
||
# 步骤1: 更新mkdocs.yml
|
||
if not args.skip_mkdocs:
|
||
if not step1_update_mkdocs():
|
||
sys.exit(1)
|
||
|
||
# 步骤2: Git操作
|
||
if not args.skip_git:
|
||
if not step2_git_operations(args.message, branch, remote):
|
||
sys.exit(1)
|
||
|
||
# 步骤3: 服务器操作
|
||
if not args.skip_server:
|
||
if not step3_server_operations(server_user, server_host, server_path):
|
||
sys.exit(1)
|
||
|
||
print_info("")
|
||
print_info("=" * 50)
|
||
print_success("部署完成!")
|
||
print_info("=" * 50)
|
||
|
||
except KeyboardInterrupt:
|
||
print_error("\n操作已取消")
|
||
sys.exit(1)
|
||
except Exception as e:
|
||
print_error(f"发生错误: {e}")
|
||
sys.exit(1)
|
||
|
||
if __name__ == "__main__":
|
||
main()
|