#!/usr/bin/env python3
# -*- coding:utf-8 -*-
from libs.inc import CliTool
import sys, os, datetime, re, json, requests
from threadpool import makeRequests, ThreadPool
from tools.pdd_publish_client import PddPublishClient

def buildPddWebV2(pddWebGitPath, buildCmd = 'build'):
    res = os.popen("cd " + pddWebGitPath + " && git branch -a | grep '*' | awk '{print $2}'")
    branch = res.read().strip("\n")
#     if pubEnv == 'pre' and branch.startswith('pub-') is False:
#         print(("打包失败，仓库 %s 的分支不是预发布分支，请检查" % pddWebGitPath))
#         exit()
    if pubEnv == 'pub' and not any(keyword in branch for keyword in ['master', 'real', 'revert']):
        CliTool.log(("请检查分支: {} 是否为正式发布分支?， 正式发布分支名称需包含 real、master、revert等关键词".format(pddWebGitPath)))
        exit()

    cmd = 'cd %s  && yarn && yarn %s' % (pddWebGitPath, buildCmd)
    CliTool.log("start process run build command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    distDir = pddWebGitPath + 'dist'
    if os.path.isfile(distDir + '/index.html') is False:
        CliTool.log(distDir + ' 编译文件不存在!')
        exit()
def buildPddZipV2(pubEnv, pddGitPath, apiDirName, pddWebGitPath, webDirName, dcZipBaseDir, zipDirName, zipFileName, htaccessName):
    res = os.popen("cd " + pddGitPath + " && git branch -a | grep '*' | awk '{print $2}'")
    branch = res.read().strip("\n")
#     if pubEnv == 'pre' and branch.startswith('pub-') is False:
#         print(("打包失败，仓库 %s 的分支不是预发布分支，请检查" % pddGitPath))
#         exit()
    if pubEnv == 'pub' and not any(keyword in branch for keyword in ['master', 'real', 'revert']):
        CliTool.log(("请检查分支: {} 是否为正式发布分支?， 正式发布分支名称需包含 real、master、revert等关键词".format(pddGitPath)))
        exit()

    pddWebDistDir = pddWebGitPath + 'dist'
    pubZipDir = dcZipBaseDir + zipDirName + '/'
    tmpZipDir = dcZipBaseDir + 'tmp/' + zipDirName + '/' + zipFileName + '/'

    checkPhpScriptSyntaxErrors(pubEnv, pddGitPath, tmpZipDir + apiDirName)
    cmd = "mkdir -p %s && mkdir -p %s && cd %s && rsync -cvzrDp --del --exclude=.git.* --exclude=/.git/* --exclude=/composer.* --exclude=/.qoder/* --exclude=/.trae/* --exclude=/.codebuddy/* %s %s%s" % (pubZipDir, tmpZipDir, tmpZipDir, pddGitPath, tmpZipDir, apiDirName)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    checkPhpSubModuleDirIsEmpty(tmpZipDir + apiDirName)

    if os.path.isfile(tmpZipDir + apiDirName + '/' + htaccessName) is False:
        CliTool.log("%s 未找到,拼多多打包失败" % (htaccessName))
        exit()

    # 覆盖容器内默认index.php
    cmd = "cd %s && echo \'<?php \' > index.php" % (tmpZipDir)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)

    zipFileNameSuffix = datetime.datetime.now().strftime("%Y%m%d-%H%M")
    zipFilePath = pubZipDir + '%s_%s_%s.zip' % (zipFileName, pubEnv, zipFileNameSuffix)
    cmd = "cd %s && mkdir -p %s && rm -rf %s/dist && cp -r %s ./%s/ && rm -rf .htaccess && cp %s/%s ./.htaccess" % (tmpZipDir, webDirName, webDirName, pddWebDistDir, webDirName, apiDirName, htaccessName)
    cmd += " && rm -rf %s%s_* && zip -r %s ./ -x \'*.git*\' \'*.zip\' " % (pubZipDir, zipFileName, zipFilePath)
    CliTool.log("start process command: " + cmd + "\n")
    outputStr = CliTool.execCommand(cmd)
    CliTool.log(outputStr)
    CliTool.log("end process command: " + cmd + "\n")
    return zipFilePath

def buildPddZipErp(pubEnv, pddGitPath, apiDirName, pddWebGitPath, webDirName, dcZipBaseDir, zipDirName, zipFileName, htaccessName):
    for gitPath in [pddGitPath, pddWebGitPath]:
        res = os.popen("cd " + gitPath + " && git branch -a | grep '*' | awk '{print $2}'")
        branch = res.read().strip("\n")
#         if pubEnv == 'pre' and branch.startswith('pub-') is False:
#             print(("打包失败，仓库 %s 的分支不是预发布分支，请检查" % gitPath))
#             exit()
        if pubEnv == 'pub' and not any(keyword in branch for keyword in ['master', 'real', 'revert']):
            CliTool.log(("请检查分支: {} 是否为正式发布分支?， 正式发布分支名称需包含 real、master、revert等关键词".format(gitPath)))
            exit()

    pddWebDistDir = pddWebGitPath + 'dist'
    pubZipDir = dcZipBaseDir + zipDirName + '/'
    tmpZipDir = dcZipBaseDir + 'tmp/' + zipDirName + '/' + zipFileName + '/'

    checkPhpScriptSyntaxErrors(pubEnv, pddGitPath, tmpZipDir + apiDirName)
    cmd = "mkdir -p %s && mkdir -p %s && cd %s && rsync -cvzrDp --del --exclude=.git.* --exclude=/.git/* --exclude=/composer.* --exclude=/.qoder/* --exclude=/.trae/* --exclude=/.codebuddy/* %s %s%s" % (pubZipDir, tmpZipDir, tmpZipDir, pddGitPath, tmpZipDir, apiDirName)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    checkPhpSubModuleDirIsEmpty(tmpZipDir + apiDirName)

    if os.path.isfile(tmpZipDir + apiDirName + '/' + htaccessName) is False:
        CliTool.log("%s 未找到,拼多多打包失败" % (htaccessName))
        exit()

    checkPhpScriptSyntaxErrors(pubEnv, pddWebGitPath, tmpZipDir + webDirName)
    cmd = "mkdir -p %s && mkdir -p %s && cd %s && rsync -cvzrDp --del --exclude=.git.* --exclude=/.git/* --exclude=/composer.* --exclude=/.qoder/* --exclude=/.trae/* --exclude=/.codebuddy/* %s %s%s" % (pubZipDir, tmpZipDir, tmpZipDir, pddWebGitPath, tmpZipDir, webDirName)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    checkPhpSubModuleDirIsEmpty(tmpZipDir + webDirName)

    # 覆盖容器内默认index.php
    cmd = "cd %s && echo \'<?php \' > index.php" % (tmpZipDir)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)

    zipFileNameSuffix = datetime.datetime.now().strftime("%Y%m%d-%H%M")
    zipFilePath = pubZipDir + '%s_%s_%s.zip' % (zipFileName, pubEnv, zipFileNameSuffix)
    # 1、定位到待压缩目录 2、移动htaccess到根目录 3、压缩文件
    cmd = "cd %s && rm -rf .htaccess && cp %s/%s ./.htaccess && rm -rf %s%s_* && zip -r %s ./ -x \'*.git*\' \'*.zip\' " % (tmpZipDir, apiDirName, htaccessName, pubZipDir, zipFileName, zipFilePath)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    CliTool.log("end process command: " + cmd + "\n")
    return zipFilePath

def buildPddOdMobile(pubEnv, pddGitPath, apiDirName, pddWebGitPath, webDirName, dcZipBaseDir, zipDirName, zipFileName, htaccessName):
    pddSpGitPath = CliTool.workspace() + 'pdd.git/'
    for gitPath in [pddGitPath, pddWebGitPath, pddSpGitPath]:
        res = os.popen("cd " + gitPath + " && git branch -a | grep '*' | awk '{print $2}'")
        branch = res.read().strip("\n")
#         if pubEnv == 'pre' and branch.startswith('pub-') is False:
#             print(("打包失败，仓库 %s 的分支不是预发布分支，请检查" % gitPath))
#             exit()
        if pubEnv == 'pub' and not any(keyword in branch for keyword in ['master', 'real', 'revert']):
            CliTool.log(("请检查分支: {} 是否为正式发布分支?， 正式发布分支名称需包含 real、master、revert等关键词".format(gitPath)))
            exit()

    pddWebDistDir = pddWebGitPath + 'dist'
    pubZipDir = dcZipBaseDir + zipDirName + '/'
    tmpZipDir = dcZipBaseDir + 'tmp/' + zipDirName + '/' + zipFileName + '/'

    checkPhpScriptSyntaxErrors(pubEnv, pddGitPath, tmpZipDir + apiDirName)
    cmd = "mkdir -p %s && mkdir -p %s && cd %s && rsync -cvzrDp --del --exclude=.git.* --exclude=/.git/* --exclude=/composer.* --exclude=/.qoder/* --exclude=/.trae/* --exclude=/.codebuddy/* %s %s%s" % (pubZipDir, tmpZipDir, tmpZipDir, pddGitPath, tmpZipDir, apiDirName)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    checkPhpSubModuleDirIsEmpty(tmpZipDir + apiDirName)

    if os.path.isfile(tmpZipDir + apiDirName + '/' + htaccessName) is False:
        CliTool.log("%s 未找到,拼多多打包失败" % (htaccessName))
        exit()

    checkPhpScriptSyntaxErrors(pubEnv, pddSpGitPath, tmpZipDir + 'spapi')
    cmd = "mkdir -p %s && mkdir -p %s && cd %s && rsync -cvzrDp --del --exclude=.git.* --exclude=/.git/* --exclude=/composer.* --exclude=/.qoder/* --exclude=/.trae/* --exclude=/.codebuddy/* %s %s%s" % (pubZipDir, tmpZipDir, tmpZipDir, pddSpGitPath, tmpZipDir, 'spapi')
    CliTool.log("start process spapi command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    checkPhpSubModuleDirIsEmpty(tmpZipDir + 'spapi')

    cmd = "mkdir -p %s && mkdir -p %s && cd %s && rsync -cvzrDp --del --exclude=.git.* --exclude=/.git/* --exclude=/composer.* --exclude=/.qoder/* --exclude=/.trae/* --exclude=/.codebuddy/* %s %s%s" % (pubZipDir, tmpZipDir, tmpZipDir, pddWebGitPath, tmpZipDir, webDirName)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)

    # 覆盖容器内默认index.php
    cmd = "cd %s && echo \'<?php \' > index.php" % (tmpZipDir)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)

    zipFileNameSuffix = datetime.datetime.now().strftime("%Y%m%d-%H%M")
    zipFilePath = pubZipDir + '%s_%s_%s.zip' % (zipFileName, pubEnv, zipFileNameSuffix)
    cmd = "cd %s && rm -rf .htaccess && cp %s/%s ./.htaccess && rm -rf %s%s_* && zip -r %s ./ -x \'*.git*\' \'*.zip\' " % (tmpZipDir, apiDirName, htaccessName, pubZipDir, zipFileName, zipFilePath)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    CliTool.log("end process command: " + cmd + "\n")
    return zipFilePath

def buildPddZipCommon(pubEnv, pddGitPath, dcZipBaseDir, zipDirName, zipFileName, htaccessName=None):
    res = os.popen("cd " + pddGitPath + " && git branch -a | grep '*' | awk '{print $2}'")
    branch = res.read().strip("\n")
#     if pubEnv == 'pre' and branch.startswith('pub-') is False:
#         print(("打包失败，仓库 %s 的分支不是预发布分支，请检查" % pddGitPath))
#         exit()
    if pubEnv == 'pub' and not any(keyword in branch for keyword in ['master', 'real', 'revert']):
        CliTool.log(("请检查分支: {} 是否为正式发布分支?， 正式发布分支名称需包含 real、master、revert等关键词".format(pddGitPath)))
        exit()

    pubZipDir = dcZipBaseDir + zipDirName + '/'
    tmpZipDir = dcZipBaseDir + 'tmp/' + zipDirName + '/'

    checkPhpScriptSyntaxErrors(pubEnv, pddGitPath, tmpZipDir)
    cmd = "mkdir -p %s && mkdir -p %s && cd %s && rsync -cvzrDp --del --exclude=.git.* --exclude=/.git/* --exclude=/composer.* --exclude=/.qoder/* --exclude=/.trae/* --exclude=/.codebuddy/* %s %s" % (pubZipDir, tmpZipDir, tmpZipDir, pddGitPath, tmpZipDir)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    checkPhpSubModuleDirIsEmpty(tmpZipDir)

    if htaccessName:
        if os.path.isfile(tmpZipDir + htaccessName) is False:
            CliTool.log("%s 未找到,拼多多打包失败" % (htaccessName))
            exit()

    zipFileNameSuffix = datetime.datetime.now().strftime("%Y%m%d-%H%M")
    zipFilePath = pubZipDir + '%s_%s_%s.zip' % (zipFileName, pubEnv, zipFileNameSuffix)
    if htaccessName:
        cmd = "cd %s && rm -rf .htaccess && cp %s ./.htaccess && rm -rf %s%s_* && zip -r %s ./ -x \'*.git*\' \'*.zip\' " % (tmpZipDir, htaccessName, pubZipDir, zipFileName, zipFilePath)
    else:
        cmd = "cd %s && rm -rf %s%s_* && zip -r %s ./ -x \'*.git*\' \'*.zip\' " % (tmpZipDir, pubZipDir, zipFileName, zipFilePath)
    CliTool.log("start process command: " + cmd + "\n")
    CliTool.processCmd2(cmd)
    CliTool.log("end process command: " + cmd + "\n")
    return zipFilePath

def checkPhpSubModuleDirIsEmpty(tmpZipDir):
    checkDirs = [
        os.path.join(tmpZipDir, 'app/libs/vendor/'),
    ]
    for checkDir in checkDirs:
        if not os.path.isdir(checkDir):
            CliTool.log("错误: " + checkDir + "不是有效目录")
            exit()

         # 查找空目录
        for item in os.listdir(checkDir):
            itemPath = os.path.join(checkDir, item)
            if not os.path.isdir(itemPath):
                continue

            subItems = [subItem for subItem in os.listdir(itemPath) if not subItem.startswith('.')]
            if len(subItems) == 0:
                CliTool.log(itemPath + "目录为空，请检查后重新发布")
                exit()


def checkPhpScriptSyntaxErrors(pubEnv, pddGitPath, tmpZipDir):
#     if pubEnv != 'pub':
#         return False

    global passPhpSyntaxAppNames

    # 解析rsync输出，获取php的文件列表
    local_script_dir = pddGitPath

    pddGitPathSplitList = pddGitPath.rstrip("/").split('/')
    if pddGitPathSplitList[-1] == 'api':
        appName = pddGitPathSplitList[-2]
    else:
        appName = pddGitPathSplitList[-1]
    if appName.endswith('.git'):
        appName = appName[:-4]

    if appName in passPhpSyntaxAppNames:
        CliTool.log("[%s] has pass check php syntax, skip......" % (appName))
        return False

    rsyncCmd = "rsync -cvzrDpn --del --exclude=.git.* --exclude=/.git/* --exclude=/composer.* %s %s" % (pddGitPath, tmpZipDir)
    rsync_result = CliTool.execCommand(rsyncCmd)
    # 解析rsync输出，获取已删除的文件列表
    php_files = re.findall(r'^(?!deleting)(.+\.php)$', rsync_result, re.MULTILINE)
    if len(php_files) == 0:
        passPhpSyntaxAppNames.append(appName)
        CliTool.log("未检出到php文件， 继续发布")
        return False

    # 遍历PHP文件并检查语法错误
    error_mgs = ''
    for php_file in php_files:
        if php_file.startswith('api/vendor/') or php_file.startswith('vendor/'):
            continue

        php_script_path = os.path.join(local_script_dir, php_file)
        CliTool.log("check php syntax: %s" % php_script_path)

        cmd = 'php -l {}'.format(php_script_path)
        result = CliTool.execCommand(cmd)
        if 'No syntax errors' in result:
            continue

        result = result.replace(local_script_dir, "")
        error_mgs += result + '\n'

    if error_mgs == '':
        passPhpSyntaxAppNames.append(appName)
        return False

    sendErrorInfoByTingTalkRobots(appName, error_mgs)
    CliTool.log("---------发布异常，检查PHP是否存在语法错误，详见Ops群通知，联系开发---------")
    exit()
    return True

def sendErrorInfoByTingTalkRobots(appName, errorMsg):
    robots_url = 'http://jflow.jiancent.com/open/ding_talk/sendTextMsgToGroup'
    form_data = {
        'sign': '562830de9f752e8bff88685ab92351ed604f4077',
        'groupId': 'cidRi6GD08s2emMouu0SP2HTA==',
        'msg' : "项目[{}]发布时PHP语法错误： \n\n {} ".format(appName, errorMsg),
    }

    response = requests.post(robots_url, data=form_data)
    if response.status_code == 200:
        return True
    else:
        return False

def singlePublish(publishInfo):
    global successAppNames
    appName = publishInfo['appName']
    client = PddPublishClient(publishInfo['appType'])
    isSuccess = client.publishSingle(appName, publishInfo['pubEnv'], publishInfo['zipFilePath'])
    if isSuccess is True:
        successAppNames.append(appName)

def multiPublish(publishInfoList, pubEnv):
    homeDir = os.path.expanduser('~')
    outputStr = os.system('rm -rf %s/Documents/ddc_zip_v2/tmp/access-token/*_lock' % homeDir)
    CliTool.log(outputStr)

    global successAppNames
    pool = ThreadPool(50)
    requests = makeRequests(singlePublish, publishInfoList)
    begin = datetime.datetime.now()
    [pool.putRequest(req) for req in requests]
    pool.wait()
    end = datetime.datetime.now()

    CliTool.log("-------------------------- " + mode + " Publish summary start ------------------------------")
    for successAppName in successAppNames:
        CliTool.log("%s\t%s\tsuccess" % (successAppName, pubEnv))
    for publishInfo in publishInfoList:
        if publishInfo['appName'] not in successAppNames:
            CliTool.log("%s\t%s\tfail" % (publishInfo['appName'], pubEnv))

    useTime = end - begin
    CliTool.log("\n\t\t\t\t publish use time: %s" % useTime)
    CliTool.log("-------------------------- " + mode + " Publish summary end ------------------------------")

successAppNames = []
passPhpSyntaxAppNames = []

app = sys.argv[1]
APP_PDD_V2 = 'pdd-v2'
APP_PDD_ORDER_V2 = 'pdd-order-v2'
APP_PDD_ORDER_MOBILE = 'pdd-order-mobile'
APP_PDD_SP = 'pdd-sp'
APP_PDD_ERP = 'pdd-erp'
APP_GOODS = 'app-goods'
APP_ORDER = 'app-order'
isPddV2 = (app == APP_PDD_V2)
isPddOrderV2 = (app == APP_PDD_ORDER_V2)
isPddOrderMobile = (app == APP_PDD_ORDER_MOBILE)
isPddSp = (app == APP_PDD_SP)
isPddErp = (app == APP_PDD_ERP)
isAppGoods = (app == APP_GOODS)
isAppOrder = (app == APP_ORDER)

if app not in [APP_PDD_V2, APP_PDD_ORDER_V2, APP_PDD_ORDER_MOBILE, APP_PDD_SP, APP_PDD_ERP, APP_GOODS, APP_ORDER]:
    CliTool.log('%s 错误，请联系运维', app)
    exit()

isIntra = (sys.argv[2] == 'intra')
onlyPubAppName = sys.argv[3]
if onlyPubAppName in ['mspdd-v2', 'mspddsp-v2', 'mspddodsh-v2', 'pddbksh-v2', 'pddry-v2', 'mspddod-v2', 'mspddop-v2', 'pddry-opv2', 'pddbkod-v2', 'pddryop-v2', 'mspddod-mobile', 'mspddsp', 'mspddod', 'pddry', 'mspdd', 'pddbksh', 'mspddop', 'mspddopdzmd', 'pddryop', 'pddbkod']:
    pubEnv = sys.argv[4]
    mode = sys.argv[5]
    isAutoPub = (len(sys.argv) > 6 and sys.argv[6] == 'auto')
else:
    onlyPubAppName = ''
    pubEnv = sys.argv[3]
    mode = sys.argv[4]
    isAutoPub = (len(sys.argv) > 5 and sys.argv[5] == 'auto')

if pubEnv not in ['pre', 'pub']:
    CliTool.log('发布环境错误，只支持pre、pub')
    exit()

localPwdFile = os.path.expanduser('~') + '/Documents/publish/tjds1.passwd'
localAppsPath  = CliTool.workspace()
apiGitPath = {
    APP_PDD_V2: 'pdd.git/',
    APP_PDD_ORDER_V2: 'pdd-order-api.git/',
    APP_PDD_ORDER_MOBILE: 'pdd-order-mobile.git/api/',
    APP_PDD_SP: 'pdd.git/',
    APP_PDD_ERP: 'pdd.git/',
    APP_GOODS: 'pdd.git/',
    APP_ORDER: 'pdd-order.git/',
}.get(app, 'pdd.git/')
apiGitPath = localAppsPath + apiGitPath
webGitPath = {
    APP_PDD_V2: 'pdd-web.git/',
    APP_PDD_ORDER_V2: 'pdd-order-web.git/',
    APP_PDD_ORDER_MOBILE: 'pdd-order-mobile.git/web/',
    APP_PDD_SP: 'pdd-mobile-web.git/',
    APP_PDD_ERP: 'pdd-order.git/',
}.get(app, 'pdd-web.git/')
webGitPath = localAppsPath + webGitPath
apiDirName = {
    APP_PDD_SP: 'pdd',
    APP_PDD_ERP: 'pdd',
}.get(app, 'api')
webDirName = {
    APP_PDD_SP: 'pdd-mobile-web',
    APP_PDD_ERP: 'pdd-order'
}.get(app, 'web')

publishInfoList = []
if isIntra is False and mode == 'real':
    dcZipBaseDir = os.path.expanduser('~') + '/Documents/ddc_zip_v2/'
    if os.path.isdir(dcZipBaseDir) is False:
        os.makedirs(dcZipBaseDir)

    if isPddV2 is True:
        appTypeAndAppNameAndAppInfoMap = {
            'ms': {
                'mspdd-v2': {"zipDirName": "v2", "zipFileName": "pdd-v2", 'htaccessName': 'htaccess_pdd_v2'},
                'mspddsp-v2': {"zipDirName": "v2", "zipFileName": "pdd-sp-v2", 'htaccessName': 'htaccess_pddsp_v2'},
                'mspddodsh-v2': {"zipDirName": "v2", "zipFileName": "pdd-odsh-v2", 'htaccessName': 'htaccess_pddodsh_v2'},
            },
            'tbk': {
                'pddbksh-v2': {"zipDirName": "v2", "zipFileName": "pddbk-sh-v2", 'htaccessName': 'htaccess_pddbksh_v2'},
            },
            'jb': {
                'pddry-v2': {"zipDirName": "v2", "zipFileName": "pddry-v2", 'htaccessName': 'htaccess_pddry_v2'},
            },
        }

        for appType, appNameAndInfoMap in appTypeAndAppNameAndAppInfoMap.items():
            if onlyPubAppName and onlyPubAppName not in appTypeAndAppNameAndAppInfoMap[appType]:
                continue

            buildCmd = {
                'tbk': 'build:tbk',
                'jb': 'build:ry',
            }.get(appType, 'build')
            buildPddWebV2(webGitPath, buildCmd)
            for appName, appInfo in appNameAndInfoMap.items():
                if onlyPubAppName and onlyPubAppName != appName:
                    continue

                zipFilePath = buildPddZipV2(pubEnv, apiGitPath, apiDirName, webGitPath, webDirName, dcZipBaseDir, appInfo['zipDirName'], appInfo['zipFileName'], appInfo['htaccessName'])
                if isAutoPub and zipFilePath:
                    publishInfo = {
                        'appType': appType,
                        'appName': appName,
                        'pubEnv': pubEnv,
                        'zipFilePath': zipFilePath,
                    }
                    publishInfoList.append(publishInfo)

    if isPddOrderV2 is True:
        appTypeAndAppNameAndAppInfoMap = {
            'ms': {
                'mspddod-v2': {"zipDirName": "v2", "zipFileName": "pdd-od-v2", 'htaccessName': 'htaccess_pddod_v2'},
                'mspddop-v2': {"zipDirName": "v2", "zipFileName": "pdd-op-v2", 'htaccessName': 'htaccess_pddop_v2'},
            },
            'tbk': {
                'pddbkod-v2': {"zipDirName": "v2", "zipFileName": "pddbk-od-v2", 'htaccessName': 'htaccess_pddbkod_v2'},
            },
            'jb': {
                'pddry-opv2': {"zipDirName": "v2", "zipFileName": "pddry-opv2", 'htaccessName': 'htaccess_pddry_v2'},
                'pddryop-v2': {"zipDirName": "v2", "zipFileName": "pddry-op-v2", 'htaccessName': 'htaccess_pddryop_v2'},
            }
        }
        for appType, appNameAndInfoMap in appTypeAndAppNameAndAppInfoMap.items():
            if onlyPubAppName and onlyPubAppName not in appTypeAndAppNameAndAppInfoMap[appType]:
                continue

            buildCmd = {
                'tbk': 'build:tbk',
                'jb': 'build:ry',
            }.get(appType, 'build')
            buildPddWebV2(webGitPath, buildCmd)
            for appName, appInfo in appNameAndInfoMap.items():
                if onlyPubAppName and onlyPubAppName != appName:
                    continue

                zipFilePath = buildPddZipV2(pubEnv, apiGitPath, apiDirName, webGitPath, webDirName, dcZipBaseDir, appInfo['zipDirName'], appInfo['zipFileName'], appInfo['htaccessName'])
                if isAutoPub and zipFilePath:
                    publishInfo = {
                        'appType': appType,
                        'appName': appName,
                        'pubEnv': pubEnv,
                        'zipFilePath': zipFilePath,
                    }
                    publishInfoList.append(publishInfo)

    if isPddOrderMobile is True:
        appTypeAndAppNameAndAppInfoMap = {
            'ms': {
                'mspddod-mobile': {"zipDirName": "mobile", "zipFileName": "pdd-od-mobile", 'htaccessName': 'root.htaccess'},
            },
        }
        for appType, appNameAndInfoMap in appTypeAndAppNameAndAppInfoMap.items():
            if onlyPubAppName and onlyPubAppName not in appTypeAndAppNameAndAppInfoMap[appType]:
                continue

            buildCmd = {
                'dz': 'build:dz',
            }.get(appType, 'build')
            buildPddWebV2(webGitPath, buildCmd)
            for appName, appInfo in appNameAndInfoMap.items():
                if onlyPubAppName and onlyPubAppName != appName:
                    continue

                zipFilePath = buildPddOdMobile(pubEnv, apiGitPath, apiDirName, webGitPath, webDirName, dcZipBaseDir, appInfo['zipDirName'], appInfo['zipFileName'], appInfo['htaccessName'])
                if isAutoPub and zipFilePath:
                    publishInfo = {
                        'appType': appType,
                        'appName': appName,
                        'pubEnv': pubEnv,
                        'zipFilePath': zipFilePath,
                    }
                    publishInfoList.append(publishInfo)

    if isPddSp is True:
        appTypeAndAppNameAndAppInfoMap = {
            'ms': {
                'mspddsp': {"zipDirName": "pdd-sp", "zipFileName": "pdd-sp", 'htaccessName': 'htaccess_pddsp'},
            },
        }
        for appType, appNameAndInfoMap in appTypeAndAppNameAndAppInfoMap.items():
            if onlyPubAppName and onlyPubAppName not in appTypeAndAppNameAndAppInfoMap[appType]:
                continue

            buildCmd = {
                'dz': 'build:dz',
            }.get(appType, 'build')
            buildPddWebV2(webGitPath, buildCmd)
            for appName, appInfo in appNameAndInfoMap.items():
                if onlyPubAppName and onlyPubAppName != appName:
                    continue

                zipFilePath = buildPddZipV2(pubEnv, apiGitPath, apiDirName, webGitPath, webDirName, dcZipBaseDir, appInfo['zipDirName'], appInfo['zipFileName'], appInfo['htaccessName'])
                if isAutoPub and zipFilePath:
                    publishInfo = {
                        'appType': appType,
                        'appName': appName,
                        'pubEnv': pubEnv,
                        'zipFilePath': zipFilePath,
                    }
                    publishInfoList.append(publishInfo)

    if isPddErp is True:
        appTypeAndAppNameAndAppInfoMap = {
            'ms': {
                'mspddod': {"zipDirName": "pdd-od", "zipFileName": "pdd-od", 'htaccessName': 'htaccess_pddod'},
            },
            'jb': {
                'pddry': {"zipDirName": "pddry", "zipFileName": "pddry", 'htaccessName': 'htaccess_pddry'},
            },
        }
        for appType, appNameAndInfoMap in appTypeAndAppNameAndAppInfoMap.items():
            if onlyPubAppName and onlyPubAppName not in appTypeAndAppNameAndAppInfoMap[appType]:
                continue

            for appName, appInfo in appNameAndInfoMap.items():
                if onlyPubAppName and onlyPubAppName != appName:
                    continue

                zipFilePath = buildPddZipErp(pubEnv, apiGitPath, apiDirName, webGitPath, webDirName, dcZipBaseDir, appInfo['zipDirName'], appInfo['zipFileName'], appInfo['htaccessName'])
                if isAutoPub and zipFilePath:
                    publishInfo = {
                        'appType': appType,
                        'appName': appName,
                        'pubEnv': pubEnv,
                        'zipFilePath': zipFilePath,
                    }
                    publishInfoList.append(publishInfo)

    if isAppGoods is True:
        appTypeAndAppNamesMap = {
            'ms': ['mspdd'],
            'tbk': ['pddbksh'],
        }
        zipFilePath = buildPddZipCommon(pubEnv, apiGitPath, dcZipBaseDir, 'pdd-goods', 'pdd-goods')
        if isAutoPub and zipFilePath:
            for appType, appNames in appTypeAndAppNamesMap.items():
                for appName in appNames:
                    if onlyPubAppName and onlyPubAppName != appName:
                        continue

                    publishInfo = {
                        'appType': appType,
                        'appName': appName,
                        'pubEnv': pubEnv,
                        'zipFilePath': zipFilePath,
                    }
                    publishInfoList.append(publishInfo)

    if isAppOrder is True:
        appTypeAndAppNameAndAppInfoMap = {
            'ms': {
                'mspddop': {"zipDirName": "pdd-order", "zipFileName": "pdd-order", 'htaccessName': ''},
                'mspddopdzmd': {"zipDirName": "pdd-order", "zipFileName": "pdd-order", 'htaccessName': ''},
            },
            'jb': {
                'pddryop': {"zipDirName": "pdd-order", "zipFileName": "pdd-order", 'htaccessName': ''},
            },
            'tbk': {
                'pddbkod': {"zipDirName": "pdd-order-bkod", "zipFileName": "pdd-order-bkod", 'htaccessName': 'htaccess_pddbkod'},
            },
        }
        zipFilePathCache = {}
        for appType, appNameAndInfoMap in appTypeAndAppNameAndAppInfoMap.items():
            if onlyPubAppName and onlyPubAppName not in appTypeAndAppNameAndAppInfoMap[appType]:
                continue

            for appName, appInfo in appNameAndInfoMap.items():
                if onlyPubAppName and onlyPubAppName != appName:
                    continue

                cacheKey = appInfo['zipDirName'] + '/' + appInfo['zipFileName'] + '/' + appInfo['htaccessName']
                if cacheKey not in zipFilePathCache:
                    htaccessName = appInfo['htaccessName'] if appInfo['htaccessName'] else None
                    zipFilePathCache[cacheKey] = buildPddZipCommon(pubEnv, apiGitPath, dcZipBaseDir, appInfo['zipDirName'], appInfo['zipFileName'], htaccessName)
                zipFilePath = zipFilePathCache[cacheKey]
                if isAutoPub and zipFilePath:
                    publishInfo = {
                        'appType': appType,
                        'appName': appName,
                        'pubEnv': pubEnv,
                        'zipFilePath': zipFilePath,
                    }
                    publishInfoList.append(publishInfo)

    cmd = ('find %s -type f -name "*.zip" -mtime +3 -type f -delete && tree -L 2 %s' % (dcZipBaseDir, dcZipBaseDir))
    outputStr = CliTool.execCommand(cmd)
    CliTool.log('process cmd ' + cmd)
    CliTool.log(outputStr)
    if not publishInfoList:
        CliTool.log('当前模式无需自动发布')
        exit()
    multiPublish(publishInfoList, pubEnv)
    