Python定时任务前端项目本地自动打包远程部署脚本实现

import os
import time
import subprocess
import schedule
from datetime import datetime
import paramiko
from dateutil import parser


def read_last_build_time():
    """
    读取上次打包的时间
    :return: 上次打包的时间(datetime对象),如果文件不存在则返回None
    """
    try:
        with open(LAST_BUILD_TIME_FILE, "r") as f:
            return datetime.fromisoformat(f.read().strip())
    except FileNotFoundError:
        return None


def write_last_build_time(time):
    """
    写入本次打包的时间
    :param time: 当前时间(datetime对象)
    """
    with open(LAST_BUILD_TIME_FILE, "w") as f:
        f.write(time.isoformat())


def git_pull():
    """
    执行git pull命令,拉取最新代码
    """
    subprocess.run(["git", "pull"], cwd=REPO_DIR, check=True, stdout=subprocess.DEVNULL)


def get_last_commit_time():
    """
    获取仓库中最新一次提交的时间
    :return: 最新一次提交的时间(datetime对象)
    """
    result = subprocess.run(["git", "log", "-1", "--format=%cd", "--date=iso"], cwd=REPO_DIR, capture_output=True,
                            text=True, check=True)
    return parser.parse(result.stdout.strip())


def build_project():
    """
    执行打包命令,构建项目
    """
    subprocess.run(["pnpm", "i"], cwd=REPO_DIR, shell=True, check=True, stdout=subprocess.DEVNULL)
    subprocess.run(["pnpm", "run", "build"], cwd=REPO_DIR, shell=True, check=True, stdout=subprocess.DEVNULL)


def rename_remote_dirs(ssh):
    """
    判断远程目录并重命名
    """
    try:
        new_dir = os.path.join(os.path.dirname(REMOTE_DIR), datetime.now().strftime("%Y%m%d%H%M"))
        new_dir = new_dir.replace("\\", "/").replace(r"\\", "/")
        ssh.exec_command(f"mv {REMOTE_DIR} {new_dir}")
    except IOError:
        pass  # 如果目录不存在,继续
    ssh.exec_command(f"mv {REMOTE_DIR_TEMP} {REMOTE_DIR}")


def upload_build():
    """
    上传打包生成的文件夹到远程服务器
    """
    # 连接远程服务器
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(REMOTE_SERVER, port=REMOTE_PORT, username=REMOTE_USER, password=REMOTE_PASSWORD)
    sftp = ssh.open_sftp()
    # 遍历本地build目录,逐个文件上传到远程服务器
    for root, dirs, files in os.walk(BUILD_DIR):
        for file in files:
            local_path = os.path.join(root, file)
            relative_path = os.path.relpath(local_path, BUILD_DIR)
            remote_file = os.path.join(REMOTE_DIR_TEMP, relative_path).replace("\\", "/").replace(r"\\", "/")
            remote_dir = os.path.dirname(remote_file)
            # 创建目标目录
            try:
                sftp.put(local_path, remote_file)
            except FileNotFoundError:
                ssh.exec_command(f"mkdir -p {remote_dir}")
            except IOError:
                pass  # 如果目录已存在,继续
            finally:
                sftp.put(local_path, remote_file)
    rename_remote_dirs(ssh)
    # 关闭连接
    sftp.close()
    ssh.close()


def deploy():
    """
    执行部署任务,包括:
    1. 拉取最新代码
    2. 检查是否有新提交
    3. 如果有新提交,则构建项目并上传到远程服务器
    """
    print(f"检查更新时间 {datetime.now()}")
    git_pull()
    last_build_time = read_last_build_time()
    last_commit_time = get_last_commit_time().replace(tzinfo=None)
    # 如果上次打包时间不存在或有新提交,则构建并上传项目
    if last_build_time is None or last_commit_time > last_build_time:
        print("检测到新提交,正在打包...")
        build_project()
        print("上传打包文件...")
        upload_build()
        write_last_build_time(datetime.now())
        print("部署完成")
    else:
        print("没有检测到提交")


if __name__ == "__main__":
    # 配置参数
    REPO_DIR = "D:/vue_test"  # 仓库目录
    BUILD_DIR = os.path.join(REPO_DIR, "build")  # 打包输出目录
    REMOTE_SERVER = "your.server.ip"  # 远程服务器地址
    REMOTE_PORT = 22  # SSH端口
    REMOTE_USER = "your_user"  # SSH用户名
    REMOTE_PASSWORD = "your_password"  # SSH密码
    REMOTE_DIR = "/web/vue_test"  # 远程服务器目录
    LAST_BUILD_TIME_FILE = "last_build_time.txt"  # 记录上次打包时间的文件

    # 远程临时目录
    REMOTE_DIR_TEMP = os.path.join(os.path.dirname(REMOTE_DIR), 'temp').replace("\\", "/").replace(r"\\", "/")
    # 启动时先运行一次
    deploy()
    # 每小时执行一次部署任务
    schedule.every(1).hours.do(deploy)
    while True:
        schedule.run_pending()
        time.sleep(10)
posted @   槑孒  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示