jenkins-scripts

编译

编译
#!/bin/bash

###################
# jenkins 编译使用 #
###################

# node 版本
# node_version=${node_version:-"node-v14.17.1-linux-x64"}
node_version=${node_version:-"node-v16.20.0-linux-x64"}

# 定义环境变量
export JAVA_HOME=/usr/lib/jvm/java
export PATH=/data/app/node/${node_version}/bin:$PATH
# export PATH=/data/app/node/node-v16.20.0-linux-x64/bin:$PATH

# web 编译的环境(部分web编译需要按环境编译)
ENV=${ENV:-""}
# 排除文件夹
EXCLUDE_DIRS=${EXCLUDE_DIRS:-""}
# nacos 配置地址
nacos_url="https://xxx"
nacos_user=""
nacos_password=""
properties_tenant=${properties_tenant:-"namespace-config-dev"}
# 版本覆盖oss
overwrite=${overwrite:-true}
# 小程序工具位置
miniprogram_ci_path=/data/app/node/${node_version}/lib/node_modules/miniprogram-ci/bin/miniprogram-ci.js
# 小程序编译参数
miniprogram_args="--enable-es6 false --enable-minify true"
# npm命令位置
npm_cmd=/data/app/node/${node_version}/bin/npm
# npm 仓库
npm_repo="https://registry.npmmirror.com"
# npm 参数
npm_args="--registry ${npm_repo} --sass_binary_site=${npm_repo}/mirrors/node-sass/"
# hbuild 编译工具下载地址
hbuild_tools_url=${hbuild_tools_url:-"http://xxx/hbuildx-tools-mall4uni.zip"}

# 是否 java 编译
java_comp=${java_comp:-true}
# java 包格式
mode=${mode:-"jar"}
# 是否 web 编译
web_comp=${web_comp:-true}
# 是否 uni 编译
uni_comp=${uni_comp:-true}
# 是否 h5 平台编译发布
uni_h5=${uni_h5:-true}
# 是否 app 平台编译发布
uni_app_plus=${uni_app_plus:-true}
# 是否小程序编译发布
uni_mini=${uni_mini:-true}
# 微信小程序的 appid
minikey_appids=${minikey_appids:-""}
# 微信小程序 key 下载地址
minikey_url=http://xxx/minikey
# jar 打包目录
java_upload_dir=upload_java
# web 静态文件打包目录
web_upload_dir=upload_web
# app 打包目录
app_upload_dir=upload_app
# 微信小程序打包目录
mini_upload_dir=upload_mini
# nuxt 打包目录
nuxt_upload_dir=upload_nuxt
# python 打包目录
python_upload_dir=upload_python
# 指定需要编译的目录
DIRS=${DIRS:-"$(ls ${WORKSPACE})"}
############################################################################################################
# web 项目合并,需要把 web 资源打包在 java 根目录的,项目合并数组 “web_app1:java_app1:dist web_app2:java_app2:dist”
# web项目web_app1编译生成的文件需要放在java项目java_app1的目录下,目录名称为dist
# properties需要添加 spring.resources.static-locations=file:${user.dir}/web/dist/
merge_app_array=${merge_app_array:-""}
############################################################################################################

# 运维版本号
OpsVersion=${Version}_${BUILD_ID}
if [ "$GIT_URL" != "" ];then
    OpsVersion=${Version}_${GIT_COMMIT}
fi
if [ "$SVN_URL" != "" ];then
    OpsVersion=${Version}_${SVN_REVISION}
fi
echo "运维版本号: ${OpsVersion}"
# wgt版本号,app内文件需要使用该版本号纯数字的,例如:"2.3.1_20230505"
WgtVersion=$(echo ${OpsVersion}|awk -F '_' '{print $2"_"$3}')

# curl 命令 http 请求时的超时时间
timeout=30

cat << "EOF"
# 目录结构1
# .
# ├── upload_web(web 编译后的静态文件存放目录)
# ├── upload_java(java 编译后的文件存放目录)
# ├── upload_app(app 编译后的文件存放目录)
# ├── upload_mini(微信小程序编译后的文件存放目录)
# ├── ${目录1}(java项目)
# |   ├── pom.xml
# |   ├── target
# |   |   └── out
# |   |       └── ${应用名1}
# |   |           ├── application.properties
# |   |           ├── application-dev.properties
# |   |           └── ${应用名1}.jar(打包生成)
# |   └── ...
# ├── ${目录2}(java项目)
# |   ├── module1
# |   |    ├─ pom.xml
# |   |    └── ...
# |   ├── module2
# |   |    ├─ pom.xml
# |   |    └── ...
# |   ├── module3
# |   |    ├─ pom.xml
# |   |    └── ...
# |   ├── pom.xml
# |   ├── target
# |   |   └── out
# |   |       ├── ${module1/应用名2}
# |   |       |   ├── application.properties
# |   |       |   ├── application-dev.properties
# |   |       |   └── ${module1/应用名2}.jar(打包生成)
# |   |       └── ${module3/应用名3}
# |   |           ├── application.properties
# |   |           ├── application-dev.properties
# |   |           └── ${module3/应用名3}.jar(打包生成)
# |   └── ...
# ├── ${目录3/应用名4}(vue项目)
# |    ├── package.json
# |    └── ...
# ├── ${目录4/应用名5}(hbuilderx-uni项目)
# |    ├── package.json
# |    ├── manifest.json
# |    └── ...
# ├── ${目录5/应用名6}(uni项目)
# |    ├── package.json
# |    ├── src/manifest.json
# |    └── ...
# ├──db
# |    └──数据库产品分类(mysql/clickhouse/postgresql/...)
# |      └──dbname
# |         ├──ddl
# |         |   ├──1_ddl.sql
# |         |   ├──2_ddl.sql
# |         |   └──...
# |         └──data
# |             ├──1_data.sql (数字编号与ddl中的数字编号对应)
# |             ├──2_data.sql
# |             └──...
# └── ...
EOF

function judge_info_func {
    echo "按文件默认判断代码类型"
    if [ -f nuxt.config.js ] && [ -f package.json ];then
        frame=nuxt
        platform_array=(h5)
    elif [ ! -f manifest.json ] && [ ! -f package.json ] && [ -f index.html ] && [ -d js ];then
        frame=static
        platform_array=(html)
    elif [ -f "src/manifest.json" ] && [ -f package.json ];then
        frame=uni
        platform_array=(h5 mp-weixin app-plus)
    elif ([ -f vite.config.js ] && [ -f package.json ]) || ([ ! -f manifest.json ] && [ -f package.json ]);then
        frame=vue
        platform_array=(h5)
    elif [ -f manifest.json ] && [ -f package.json ];then
        frame=hbuilderx-uni
        platform_array=(h5 mp-weixin app-plus)
    elif [ -f pom.xml ];then
        frame=java
        platform_array=(springboot)
    elif [ -f main.py ];then
        frame=python
        platform_array=fastapi
    else
        frame=""
        platform_array=()
        echo "目录:${dir} 是未知项目,跳过" && return 1;
    fi

    ##### 自定义目录 #####
    custom_dir_name=需要自定义的目录名称
    if [ "$(basename $(pwd))"x == "${custom_dir_name}"x ];then
        frame=hbuilderx-uni
        platform_array=(h5)
    fi
    echo "目录:${dir},frame:${frame},platform_array:${platform_array[*]}"

}

# 上传文件到 oss
function upload_oss_func {
    mkdir -p $(dirname $2)
    if [ ! -f $2 ] || [ ${overwrite} == true ];then
        cp -rf $1 $2 || { echo "上传oss失败" && return 1; }
    else
        echo "已经存在文件: $2,如需强制覆盖请使用 overwrite 参数"
    fi
}

# web放置到java项目下
function merge_app_array_func {
    for merge_app in ${merge_app_array[*]};do
        echo "开始合并项目${merge_app}"
        web_app=$(echo ${merge_app}|awk -F ":" '{print $1}')
        java_app=$(echo ${merge_app}|awk -F ":" '{print $2}')
        web_dir_name=$(echo ${merge_app}|awk -F ":" '{print $3}')
        if [ "${web_dir_name}"x == ""x ];then
            web_dir_name=dist
        fi
        workdir=$(pwd)
        if [ -f "${WORKSPACE}/${web_upload_dir}/${web_app}/${web_app}_${OpsVersion}.zip" ] && [ -d ${WORKSPACE}/${java_upload_dir}/${java_app}/ ];then
            mkdir -p ${WORKSPACE}/${java_upload_dir}/${java_app}/web/
            cp -rf ${WORKSPACE}/${web_upload_dir}/${web_app}/${web_app}_${OpsVersion}.zip ${WORKSPACE}/${java_upload_dir}/${java_app}/web/
            cd ${WORKSPACE}/${java_upload_dir}/${java_app}/web/ && unzip ${web_app}_${OpsVersion}.zip && rm -rf ${web_app}_${OpsVersion}.zip && \
            mv ${web_app}_${OpsVersion}/ ${web_dir_name}/ && \
            cd .. && zip -r -u ${java_app}-${OpsVersion}.zip web/
        else
            echo "web项目 ${web_app} 放置java项目 ${java_app} 下失败,web项目或者java项目没有编译或编译失败!!!"
        fi
        cd ${workdir}
    done
}

function upload_template_config_func {
    for config in application-dev.yaml application-dev.yml application-dev.properties setting-default.ini;do
        if [ -f ${config} ];then
            type=`echo "${config}"|awk -F. '{print $NF}'`
            if [ "${type}"x == "yml"x ] || [ "${type}"x == "yaml"x ];then
                type=yaml
            else
                tyep=properties
            fi
            # nacos 上传配置
            echo "上传 ${AppName} 配置文件到 nacos"
            nacos_accessToken=$(curl --connect-timeout ${timeout} -X POST -s "${nacos_url}/nacos/v1/auth/login" -d "username=${nacos_user}&password=${nacos_password}"|awk -F '"' '{print $4}')
            cat << EOF
curl --connect-timeout ${timeout} -X POST "${nacos_url}/nacos/v1/cs/configs?accessToken=${nacos_accessToken}" \
-d "type=${type}&tenant=${properties_tenant}&dataId=${OpsVersion}&group=moon.${AppName}" \
--data-urlencode "content@${config}"
EOF
            curl --connect-timeout ${timeout} -X POST "${nacos_url}/nacos/v1/cs/configs?accessToken=${nacos_accessToken}" \
            -d "type=${type}&tenant=${properties_tenant}&dataId=${OpsVersion}&group=moon.${AppName}" \
            --data-urlencode "content@${config}"
        fi
    done
}

function nuxt_comp_func {
    if [ "${ENV}"x == ""x ];then
      echo "nuxt 项目编译需要指定环境 ENV" && exit 1
    fi
    if [ ! -f env-${ENV}.js ];then
        echo "项目没有evn-${ENV}.js文件,请重新打tag添加" && exit 1
    fi
    mv -f env-${ENV}.js env.js
    if [ -f package-lock.json ];then
        ${npm_cmd} ci ${npm_args} || { echo "安装依赖失败!!!退出" && exit 1; }
    else
        ${npm_cmd} install ${npm_args} || { echo "安装依赖失败!!!退出" && exit 1; }
    fi
    ${npm_cmd} run build || { echo "编译失败!!!退出" && exit 1; }
    mkdir -p nuxt_tmp && \
    mv .nuxt/ nuxt_tmp/ && \
    mv static/ nuxt_tmp/ && \
    mv nuxt.config.js nuxt_tmp/ && \
    mv package.json nuxt_tmp/ && \
    cd nuxt_tmp && zip -r ${AppName}-${OpsVersion}-${ENV}.zip ./ && md5sum ${AppName}-${OpsVersion}-${ENV}.zip > ${AppName}-${OpsVersion}-${ENV}.md5 && \
    mkdir -p ${WORKSPACE}/${nuxt_upload_dir}/${AppName}/ && \
    mv ${AppName}-${OpsVersion}-${ENV}.zip ${WORKSPACE}/${nuxt_upload_dir}/${AppName}/ && \
    mv ${AppName}-${OpsVersion}-${ENV}.md5 ${WORKSPACE}/${nuxt_upload_dir}/${AppName}/ && \
    cd .. && rm -rf nuxt_tmp
}

# java 编译
function java_comp_func {
    java_pwd=$(pwd)
    mvn clean package -DskipTests -Dfile.encoding=UTF-8 || { echo "构建失败!!!退出" && exit 1; }
    cd ${java_pwd}
    if [ -d "target/out" ];then
        for AppName in $(ls target/out/);do
            if [ ! -f target/out/${AppName}/${AppName}.${mode} ];then
                echo "不存在 target/out/${AppName}/${AppName}.${mode} 文件"
            else
                mv target/out/${AppName}/${AppName}.${mode} target/out/${AppName}/${AppName}-${OpsVersion}.jar
            fi
            for confing in application-dev.yaml application-dev.properties;do
                if [ ! -f "target/out/${AppName}/${confing}" ];then
                    if [ -d "${AppName}" ];then
                        src_config=$(find ${AppName}/ -name ${confing}|head -n 1)
                        if [ -f "${src_config}" ];then
                            mv ${src_config} target/out/${AppName}/
                        else
                            echo "找不到配置文件 ${confing}"
                        fi
                    fi

                fi
            done
            cd target/out/${AppName}/ && zip -r ${AppName}-${OpsVersion}.zip * && \
            mkdir -p ${WORKSPACE}/${java_upload_dir}/${AppName}/ && mv ${AppName}-${OpsVersion}.zip ${WORKSPACE}/${java_upload_dir}/${AppName}/ && \
            upload_template_config_func
            cd ${java_pwd}
        done
    else
        echo "请将程序目录放在target/out目录下"
        echo "例如: target/out/AppName/AppName.jar"
        echo "文件未按照规范生成或编译失败,退出!!!"
        exit 1;
    fi
    cd ${java_pwd}
}

# web 编译
function web_comp_func {
    pwd=$(pwd)
    if [ -f "package-lock.json" ];then
        ${npm_cmd} ci ${npm_args} || { echo "安装依赖失败!!!退出" && exit 1; }
    else
        ${npm_cmd} install ${npm_args} || { echo "安装依赖失败!!!退出" && exit 1; }
    fi
    ${npm_cmd} run build || { echo "编译失败!!!退出" && exit 1; }
    if [ -d dist ];then
        # dist 打包
        mkdir -p ${WORKSPACE}/${web_upload_dir}/${AppName}/ && \
        mv dist/ ${AppName}_${OpsVersion}/ && \
        zip -r ${AppName}_${OpsVersion}.zip ${AppName}_${OpsVersion}/ && \
        mv ${AppName}_${OpsVersion}.zip ${WORKSPACE}/${web_upload_dir}/${AppName}/
        # 生成md5文件
        cd ${WORKSPACE}/${web_upload_dir}/${AppName}/ && \
        md5sum  ${AppName}_${OpsVersion}.zip >  ${AppName}_${OpsVersion}.md5
        cd ${pwd}
    fi
    if [ -d build ];then
        mkdir -p ${WORKSPACE}/${web_upload_dir}/${AppName}/ && \
        mv build/ ${AppName}_${OpsVersion}/ && \
        zip -r ${AppName}_${OpsVersion}.zip ${AppName}_${OpsVersion}/ && \
        mv ${AppName}_${OpsVersion}.zip ${WORKSPACE}/${web_upload_dir}/${AppName}/
        # 生成md5文件
        cd ${WORKSPACE}/${web_upload_dir}/${AppName}/ && \
        md5sum  ${AppName}_${OpsVersion}.zip >  ${AppName}_${OpsVersion}.md5
    fi
}

# 一般 uni 项目编译
function normal_uni_comp_func {
    pwd=$(pwd)
    if [ -f package-lock.json ];then
        ${npm_cmd} ci ${npm_args} || { echo "安装依赖失败!!!退出" && exit 1; }
    else
        ${npm_cmd} install ${npm_args} || { echo "安装依赖失败!!!退出" && exit 1; }
    fi
    ${npm_cmd} run build:${platform} || { echo "编译失败!!!退出" && exit 1; }
    if [ -d dist/build/${platform} ];then
        mkdir -p $WORKSPACE/${AppName}/ && mv dist/build/${platform} $WORKSPACE/${AppName}/${platform}
    fi
    cd ${pwd}
}

# uni 项目预处理文件
function uni_pre_deal_func {
    # 小沐商城
    if [ -f pages/aboutMall/aboutMall.vue ];then
        sed -i "s/\#TagVersion\#/${WgtVersion}/g" pages/aboutMall/aboutMall.vue
    fi
    # 打包时的 wgt 版本
    if [ -f manifest.json ];then
        sed -i "s/\#TagVersion\#/${WgtVersion}/g" manifest.json
    fi
    # 替换对应环境配置
    if [ -f vue.${ENV}.config.js ];then
        if [ "${ENV}"x == ""x ];then
            echo "该uni项目编译需要指定环境ENV" && exit 1
        fi
        if [ -f vue.${ENV}.config.js ];then
            rm -rf vue.config.js && mv vue.${ENV}.config.js vue.config.js
        else
            echo "不存在环境文件 vue.${ENV}.config.js,不合规范"
        fi
    fi

}

function uni_comp_func {
    # 下载编译工具
    echo "开始 ${AppName} 项目 uni ${platform} 平台编译"
    if [ ! -f hbuildx-tools.zip ];then
        curl --connect-timeout ${timeout} -o hbuildx-tools.zip "${hbuild_tools_url}" && \
        unzip hbuildx-tools.zip && chmod 755 build.sh
    fi
    # 预处理
    uni_pre_deal_func
    sh -x build.sh ${platform} $(pwd) || { echo "执行 build.sh 失败!!!退出" && exit 1; }
}

function uni_comp_h5_publish_func {
    echo "开始 h5 发布..."
    pwd=$(pwd)
    if [ -d $WORKSPACE/${AppName}/${platform} ];then
        # dist 打包
        mkdir -p ${WORKSPACE}/${web_upload_dir}/${AppName}/ && \
        mv $WORKSPACE/${AppName}/${platform} ${AppName}_${OpsVersion}/ && \
        zip -r ${AppName}_${OpsVersion}.zip ${AppName}_${OpsVersion}/ && \
        mv ${AppName}_${OpsVersion}.zip ${WORKSPACE}/${web_upload_dir}/${AppName}/
        cd ${pwd}
    elif [ -d $WORKSPACE/${platform} ];then
        # dist 打包
        mkdir -p ${WORKSPACE}/${web_upload_dir}/${AppName}/ && \
        mv $WORKSPACE/${platform} ${AppName}_${OpsVersion}/ && \
        zip -r ${AppName}_${OpsVersion}.zip ${AppName}_${OpsVersion}/ && \
        mv ${AppName}_${OpsVersion}.zip ${WORKSPACE}/${web_upload_dir}/${AppName}/
        cd ${pwd}
    fi
}

function uni_comp_app_publish_func {
    echo "开始 uni app 发布..."
    if [ "${ENV}"x == ""x ];then
        echo "该uni项目编译需要指定环境ENV" && exit 1
    fi
    mkdir -p $WORKSPACE/${app_upload_dir}/${AppName}
    if [ -d $WORKSPACE/${AppName}/${platform} ];then
        cd $WORKSPACE/${AppName}/${platform}

        if [ -f $WORKSPACE/${AppName}/androidPrivacy.json ];then
            cp -rf $WORKSPACE/${AppName}/androidPrivacy.json $WORKSPACE/${AppName}/${platform}
        fi
        zip -r ${AppName}_${platform}_${ENV}_${OpsVersion}.wgt * && \
        mv ${AppName}_${platform}_${ENV}_${OpsVersion}.wgt $WORKSPACE/${app_upload_dir}/${AppName}/
    elif [ -d $WORKSPACE/${platform} ];then
        cd $WORKSPACE/${platform}
        if [ -f $WORKSPACE/androidPrivacy.json ];then
            cp -rf $WORKSPACE/androidPrivacy.json $WORKSPACE/${platform}
        fi
        zip -r ${AppName}_${platform}_${ENV}_${OpsVersion}.wgt * && \
        mv ${AppName}_${platform}_${ENV}_${OpsVersion}.wgt $WORKSPACE/${app_upload_dir}/${AppName}/
    else
        echo "目录 ${WORKSPACE}/${AppName}/${platform} 和 ${WORKSPACE}/${platform} 不存在"
        exit 1
    fi
}

function uni_comp_weixin_publish_func {
    pwd=$(pwd)
    cd ${WORKSPACE}
    echo "开始 uni 微信小程序发布..."
    mkdir -p $WORKSPACE/${mini_upload_dir}/${AppName}
    if [ -d $WORKSPACE/${AppName}/${platform} ];then
        cd $WORKSPACE/${AppName}/
    elif [ -d $WORKSPACE/${platform} ];then
        cd $WORKSPACE
    else
        echo "目录 ${WORKSPACE}/${AppName}/${platform} 和 ${WORKSPACE}/${platform} 不存在"
        exit 1
    fi
    zip -r ${AppName}_${platform}_${OpsVersion}.zip ${platform}/ && \
    mv ${AppName}_${platform}_${OpsVersion}.zip $WORKSPACE/${mini_upload_dir}/${AppName}
    # 上传微信
    cd ${WORKSPACE}
    npm install miniprogram-ci -g
    for minikey_appid in ${minikey_appids};do
        # 微信小程序 key 下载地址
        echo "微信小程序appid: ${minikey_appid},minikey_url: ${minikey_url}/private.${minikey_appid}.key"
        curl --connect-timeout ${timeout} -O ${minikey_url}/private.${minikey_appid}.key
        echo "开始上传微信小程序..."
        ${miniprogram_ci_path} upload \
        --pp ./${platform}/ \
        --pkp ./private.${minikey_appid}.key \
        --appid ${minikey_appid} \
        --uv ${OpsVersion} \
        -r 1 \
        ${miniprogram_args} || { echo "微信小程序上传失败!!!" && exit 1; }
    done
    cd ${pwd}
}

function python_comp_func {
    zip -r ${AppName}-${OpsVersion}.zip * && \
    mkdir -p ${WORKSPACE}/${python_upload_dir}/${AppName}/ && \
    mv ${AppName}-${OpsVersion}.zip ${WORKSPACE}/${python_upload_dir}/${AppName}/ && \
    mv setting-default.ini ${WORKSPACE}/${python_upload_dir}/${AppName}/
}

function static_web_comp_func {
    if [ "${dir}"x == "./"x ] && [ "${AppName}"x == ""x ];then
        echo "项目编译目录为 ./ 需要指定 AppName" && exit 1
    else
        AppName=${dir}
    fi
    cd .. && \
    cp -rf ${AppName} ${AppName}_${OpsVersion} && zip -r ${AppName}_${OpsVersion}.zip ${AppName}_${OpsVersion} && rm -rf ${AppName}_${OpsVersion} && \
    md5sum  ${AppName}_${OpsVersion}.zip > ${AppName}_${OpsVersion}.md5 && \
    mkdir -p ${WORKSPACE}/${web_upload_dir}/${AppName}/ && \
    mv ${AppName}_${OpsVersion}.zip ${AppName}_${OpsVersion}.md5 ${WORKSPACE}/${web_upload_dir}/${AppName}/
}


function upload_func {
    echo  "开始上传程序到仓库。。。"
    # 上传 db
    if [ -d ${WORKSPACE}/db/ ];then
        if [ "${Object}"x == ""x ];then
            echo "存在 db 目录需要指定 Object 参数"
            exit 1
        fi
        cd ${WORKSPACE}/db/ && zip -r sql_${Object}_${OpsVersion}.zip *
        local_sql_file=${WORKSPACE}/db/sql_${Object}_${OpsVersion}.zip
        oss_sql_file=/data/oss/moon-download/resources/db/${Object}/sql_${Object}_${OpsVersion}.zip
        echo "正在上传sql中..."
        upload_oss_func ${local_sql_file} ${oss_sql_file} || { echo "sql 上传失败" && exit 1; }
        echo "sql列表地址: http://xxxx/db/${Object}/"
        echo "sql下载地址: https://xxxx/db/${Object}/sql_${Object}_${OpsVersion}.zip"
    fi

    # 上传 java dokcer 镜像, 上传 java 配置模板
    if [ -d ${WORKSPACE}/${java_upload_dir}/ ];then
        for AppName in $(ls ${WORKSPACE}/${java_upload_dir}/);do
            # 上传 java 配置模板
            cd ${WORKSPACE}/${java_upload_dir}/${AppName}/
            local_zip_file=${WORKSPACE}/${java_upload_dir}/${AppName}/${AppName}-${OpsVersion}.zip
            oss_zip_file=/data/oss/moon-download/resources/jar/${AppName}/${AppName}-${OpsVersion}.zip
            echo "服务 ${AppName} 正在上传中..."
            upload_oss_func ${local_zip_file} ${oss_zip_file} || { echo "jar上传失败" && exit 1; }
        done
        for AppName in $(ls ${WORKSPACE}/${java_upload_dir}/);do
            echo "jar包列表地址: http://xxxx/jar/${AppName}/"
            echo "jar包下载地址: https://xxxx/jar/${AppName}/${AppName}-${OpsVersion}.zip"
        done
    fi

    # 上传 nuxt web
    if [ -d ${WORKSPACE}/${nuxt_upload_dir}/ ];then
        # 上传 web 包
        for AppName in $(ls ${WORKSPACE}/${nuxt_upload_dir}/);do
            local_nuxt_file=${WORKSPACE}/${nuxt_upload_dir}/${AppName}/${AppName}-${OpsVersion}-${ENV}.zip
            oss_nuxt_file=/data/oss/moon-download/resources/nuxt/${AppName}/${AppName}-${OpsVersion}-${ENV}.zip
            echo "nuxt ${AppName} 正在上传中..."
            upload_oss_func ${local_nuxt_file} ${oss_nuxt_file} || { echo "nuxt包上传失败" && exit 1; }
        done
        for AppName in $(ls ${WORKSPACE}/${nuxt_upload_dir}/);do
            echo "nuxt包列表地址: http://xxxx/web/${AppName}/"
            echo "nuxt包下载地址: https://xxxx/web/${AppName}/${AppName}_${OpsVersion}.zip"
        done
    fi

    # 上传 web 包
    if [ -d ${WORKSPACE}/${web_upload_dir}/ ];then
        for app_zip_file in $(ls ${WORKSPACE}/${web_upload_dir}/);do
            AppName=$(echo "${app_zip_file}"|awk -F "_${OpsVersion}" '{print $1}')
            local_zip_file=${WORKSPACE}/${web_upload_dir}/${AppName}/${AppName}_${OpsVersion}.zip
            oss_zip_file=/data/oss/moon-download/resources/web/${AppName}/${AppName}_${OpsVersion}.zip
            echo "web ${AppName} 正在上传中..."
            upload_oss_func ${local_zip_file} ${oss_zip_file} || { echo "web上传失败" && exit 1; }
        done
        for AppName in $(ls ${WORKSPACE}/${web_upload_dir}/);do
            echo "web包列表地址: http://xxxx/web/${AppName}/"
            echo "web包下载地址: https://xxxx/web/${AppName}/${AppName}_${OpsVersion}.zip"
        done
    fi


    # 打印 app 包地址
    if [ -d ${WORKSPACE}/${app_upload_dir}/ ];then
        # 上传 web 包
        for AppName in $(ls ${WORKSPACE}/${app_upload_dir}/);do
            local_wgt_file=${WORKSPACE}/${app_upload_dir}/${AppName}/${AppName}_app-plus_${ENV}_${OpsVersion}.wgt
            oss_wgt_file=/data/oss/moon-download/resources/wgt/${AppName}/${AppName}_app-plus_${ENV}_${OpsVersion}.wgt
            echo "wgt ${AppName} 正在上传中..."
            upload_oss_func ${local_wgt_file} ${oss_wgt_file} || { echo "app上传失败" && exit 1; }
        done
        for AppName in $(ls ${WORKSPACE}/${app_upload_dir}/);do
            echo "wgt包列表地址: http://xxxx/wgt/${AppName}"
            echo "wgt包下载地址: https://xxxx/wgt/${AppName}/${AppName}_app-plus_${ENV}_${OpsVersion}.wgt"
        done
    fi

    # 打印小程序包地址
    if [ -d ${WORKSPACE}/${mini_upload_dir}/ ];then
        # 上传 web 包
        for AppName in $(ls ${WORKSPACE}/${mini_upload_dir}/);do
            local_mini_file=${WORKSPACE}/${mini_upload_dir}/${AppName}/${AppName}_mp-weixin_${OpsVersion}.zip
            oss_mini_file=/data/oss/moon-download/resources/mini/${AppName}/${AppName}_mp-weixin_${OpsVersion}.zip
            echo "小程序 ${AppName} 正在上传中..."
            upload_oss_func ${local_mini_file} ${oss_mini_file} || { echo "微信小程序上传失败" && exit 1; }
        done
        for AppName in $(ls ${WORKSPACE}/${mini_upload_dir}/);do
            echo "小程序包列表地址: http://xxxx/mini/${AppName}"
            echo "小程序包下载地址: https://xxxx/mini/${AppName}/${AppName}_mp-weixin_${OpsVersion}.zip"
        done
    fi

    # 打印python包地址
    if [ -d ${WORKSPACE}/${python_upload_dir}/ ];then
        for AppName in $(ls ${WORKSPACE}/${python_upload_dir}/);do
            # 上传 python 配置模板
            cd ${WORKSPACE}/${python_upload_dir}/${AppName}/
            local_zip_file=${WORKSPACE}/${python_upload_dir}/${AppName}/${AppName}-${OpsVersion}.zip
            oss_zip_file=/data/oss/moon-download/resources/python/${AppName}/${AppName}-${OpsVersion}.zip
            echo "python ${AppName} 正在上传中..."
            upload_oss_func ${local_zip_file} ${oss_zip_file} || { echo "python上传失败" && exit 1; }
        done
        for AppName in $(ls ${WORKSPACE}/${python_upload_dir}/);do
            echo "python包列表地址: http://xxxx/python/${AppName}"
            echo "python包下载地址: https://xxxx/python/${AppName}/${AppName}-${OpsVersion}.zip"
        done
    fi

    echo "运维版本号: ${OpsVersion}"
}


# 开始循环目录编译项目,根目录循环目录编译
function loop_comp_v5_func {
    # 编译项目
    for dir in $DIRS;
    do
        cd ${WORKSPACE}
        if [ -d "${dir}" ];then
            cd ${WORKSPACE}/${dir}

            include=false
            for exclude_dir in ${EXCLUDE_DIRS};do
                if [ "${dir}"x == "${exclude_dir}"x ];then
                    include=true
                fi
            done
            if [ "${include}"x == "true"x ];then
                echo "${dir} 该目录是 EXCLUDE_DIRS, 跳过"
                continue
            fi
            if [ "${dir}"x == "./"x ];then  # 判断 AppName
                if [ "${Object}"x == ""x ];then
                    echo "项目编译目录为 ./ 需要指定 Object" && exit 1
                else
                    AppName=${Object}
                fi
            else
                AppName=${dir}
            fi
            judge_info_func || { echo "跳过 ${dir} 目录" && continue; }  # 判断项目类型
            # 开始编译
            if [ "${frame}"x == "nuxt"x ];then # if [ -f nuxt.config.js ] && [ -f package.json ];then
                if [ ${web_comp} == true ];then
                    echo "开始 nuxt 编译 ${dir} 目录..."
                    nuxt_comp_func
                fi
            elif [ "${frame}"x == "vue"x ];then # if [ ! -f manifest.json ] && [ -f package.json ];then
                if [ ${web_comp} == true ];then
                    echo "开始 web 编译 ${dir} 目录..."
                    web_comp_func
                fi
            elif [ "${frame}"x == "python"x ];then
                echo "开始 python 编译 ${dir} 目录..."
                python_comp_func
            elif [ "${frame}"x == "static"x ];then # if [ ! -f manifest.json ] && [ ! -f package.json ] && [ -f index.html ] && [ -d js ];then
                if [ ${static_web} == true ];then
                    echo "开始 static 编译 ${dir} 目录..."
                    static_web_comp_func
                fi
            elif [ "${frame}"x == "java"x ];then # elif [ -f pom.xml ];then
                if [ ${java_comp} == true ];then
                    echo "开始 java 编译 ${dir} 目录..."
                    java_comp_func
                fi
            elif [ "${frame}"x == "uni"x ];then # elif [ -f manifest.json ] && [ -f package.json ];then
                if [ ${uni_comp} == true ];then
                    for platform in ${platform_array[*]};do
                        echo "开始循环项目数组 platform_array: ${platform_array[*]},当前 platform: ${platform}"
                        if [ ${uni_h5} == true ] && [ "${platform}"x == "h5"x ];then
                            normal_uni_comp_func
                            uni_comp_h5_publish_func
                        fi
                        if [ ${uni_mini} == true ] && [ "${platform}"x == "mp-weixin"x ];then
                            normal_uni_comp_func
                            uni_comp_weixin_publish_func
                        fi
                        if [ ${uni_app_plus} == true ] && [ "${platform}"x == "app-plus"x ];then
                            normal_uni_comp_func
                            uni_comp_app_publish_func
                        fi
                    done
                fi
            elif [ "${frame}"x == "hbuilderx-uni"x ];then # elif [ -f manifest.json ] && [ -f package.json ];then
                if [ ${uni_comp} == true ];then
                    for platform in ${platform_array[*]};do
                        echo "开始循环项目数组 platform_array: ${platform_array[*]},当前 platform: ${platform}"
                        if [ ${uni_h5} == true ] && [ "${platform}"x == "h5"x ];then
                            uni_comp_func
                            uni_comp_h5_publish_func
                        fi
                        if [ ${uni_mini} == true ] && [ "${platform}"x == "mp-weixin"x ];then
                            uni_comp_func
                            uni_comp_weixin_publish_func
                        fi
                        if [ ${uni_app_plus} == true ] && [ "${platform}"x == "app-plus"x ];then
                            uni_comp_func
                            uni_comp_app_publish_func
                        fi
                    done
                fi
            else
                echo "判断项目结构错误" && exit 1;
            fi
        fi
    done
    cd ${WORKSPACE}
    # 合成项目(把dist文件夹放到java中)
    merge_app_array_func
    cd ${WORKSPACE}
    echo "编译完成!!!"
}


# 循环目录编译
loop_comp_v5_func || { echo "构建失败!!!退出" && exit 1; }

# 打包上传web包
upload_func || { echo "上传失败!!!退出" && exit 1; }

上线脚本

java

salt脚本

# salt-java-deploy.sls
# 这里应该是Java项目的salt部署配置
# 由于文件不存在,使用示例配置

java_deploy:
  file.managed:
    - name: /opt/java-app/deploy.sh
    - source: salt://java/scripts/deploy.sh
    - mode: 755
  cmd.run:
    - name: /opt/java-app/deploy.sh
    - require:
      - file: java_deploy

shell脚本

deploy-v4.sh
setup-v4.sh
run.sh
#!/bin/bash
echo 'Asia/Shanghai' > /etc/timezone

object=$1
appname=$2
env=$3
version=$4

timeout=10
app_url="https://xxx/resources/jar/${appname}/${appname}-${version}.zip"
workdir=/data/app/${object}/${appname}

# 部署配置文件
function deploy_config() {
  nacos_username=
  nacos_password=
  object="$1"
  appname="$2"
  env="$3"
  version="$4"
  config_file="${workdir}/workdir/${env}/application-${env}.properties"
  nacos_url="https://xxx"
  if [ -d "${workdir}/workdir/${env}/" ];then
    cd ${workdir}/workdir/${env}/ || exit
    nacos_accessToken=$(curl -X POST -s "${nacos_url}/nacos/v1/auth/login" -d "username=${nacos_username}&password=${nacos_password}" | awk -F '"' '{print $4}')
    config_url="${nacos_url}/nacos/v1/cs/configs?accessToken=${nacos_accessToken}&tenant=namespace-config-${env}&dataId=${version}&group=${object}.${appname}"
    config_newest_url="${nacos_url}/nacos/v1/cs/configs?accessToken=${nacos_accessToken}&tenant=namespace-config-${env}&dataId=newest&group=${object}.${appname}"
    config_http_code=$(curl --connect-timeout ${timeout} -s -I "${config_url}" | grep HTTP | awk '{print $2}')
    config_newest_http_code=$(curl --connect-timeout ${timeout} -s -I "${config_newest_url}" | grep HTTP | awk '{print $2}')
    if [ "${config_http_code}"x == "200"x ]; then
      curl --connect-timeout ${timeout} -s -o "${config_file}" "${config_url}"
    elif [ "${config_newest_http_code}"x == "200"x ]; then
      curl --connect-timeout ${timeout} -s -o "${config_file}" "${config_newest_url}"
    else
      echo "没有下载到对应的配置文件"
      exit 1
    fi
  fi
  # 判断是否下载成功
  if [ ! -f application-${env}.properties ]; then
    echo "没有下载到对应的配置文件"
    exit 1
  fi
  cd ${workdir}/ || exit
}

# 部署 app
function deploy_app() {
    mkdir -p ${workdir}/bak ${workdir}/workdir/${env}
    if [ ! -f ${workdir}/bak/${appname}-${version}.zip ] || [ $(ls -al ${workdir}/bak/${appname}-${version}.zip | awk '{print $5}') -ne $(curl -s -I "${app_url}"|grep "Content-Length"|awk '{print $2}'|tr -d '\r') ];then
        curl -o ${workdir}/bak/${appname}-${version}.zip ${app_url}
    fi
    unzip -o -d ${workdir}/workdir/${env} ${workdir}/bak/${appname}-${version}.zip
    if [ $? != 0 ];then
      echo "部署压缩包失败,下载地址: ${app_url}"
      exit 1
    fi
}

# 更新 newest 配置
function update_newest_config() {
  nacos_url="https://xxx"
  nacos_username=
  nacos_password=
  config_file="${workdir}/workdir/${env}/application-${env}.properties"
  nacos_accessToken=$(curl -X POST -s "${nacos_url}/nacos/v1/auth/login" -d "username=${nacos_username}&password=${nacos_password}" | awk -F '"' '{print $4}')
  curl --connect-timeout ${timeout} -X POST "${nacos_url}/nacos/v1/cs/configs?accessToken=${nacos_accessToken}" \
  -d "type=properties&tenant=namespace-config-${env}&dataId=newest&group=${object}.${appname}" --data-urlencode "content@${config_file}"
}

deploy_app || exit 1
deploy_config ${object} ${appname} ${env} ${version} || exit 1
update_newest_config

web

salt脚本

# salt-web-deploy.sls
# Web项目的salt部署配置示例

web_deploy:
  file.managed:
    - name: /opt/web-app/deploy.sh
    - source: salt://web/scripts/deploy.sh
    - mode: 755
  cmd.run:
    - name: /opt/web-app/deploy.sh
    - require:
      - file: web_deploy

shell脚本

  • deploy-v4.sh
#!/bin/bash

# unzip 带中文名文件有问题
export LC_CTYPE=en_US.UTF-8

echo 'Asia/Shanghai' > /etc/timezone

object=$1
appname=$2
env=$3
version=$4

timeout=10
app_url="https://xxx/resources/web/${appname}/${appname}_${version}.zip"
workdir=/data/web/${object}/${appname}

function deploy_app() {
    mkdir -p ${workdir}/bak ${workdir}/workdir/${env}
    if [ ! -f ${workdir}/bak/${appname}-${version}.zip ] || [ $(ls -al ${workdir}/bak/${appname}-${version}.zip | awk '{print $5}') -ne $(curl -s -I ${app_url}|grep "Content-Length"|awk '{print $2}'|tr -d '\r') ];then
        curl -o ${workdir}/bak/${appname}_${version}.zip ${app_url}
    fi
    rm -rf ${workdir}/workdir/${env} && \
    unzip -d ${workdir}/workdir/ ${workdir}/bak/${appname}_${version}.zip && \
    mv ${workdir}/workdir/${appname}_${version} ${workdir}/workdir/${env}
    if [ $? != 0 ];then
      echo "部署压缩包失败,下载地址: ${app_url}"
      exit 1
    fi
}

deploy_app

python

salt脚本

# salt-python-deploy.sls
# Python项目的salt部署配置示例

python_deploy:
  file.managed:
    - name: /opt/python-app/deploy.sh
    - source: salt://python/scripts/deploy.sh
    - mode: 755
  cmd.run:
    - name: /opt/python-app/deploy.sh
    - require:
      - file: python_deploy

shell脚本

deploy-v4.sh
setup-v4.sh
run.sh
#!/bin/bash
echo 'Asia/Shanghai' > /etc/timezone

object=$1
appname=$2
env=$3
version=$4

timeout=10
app_url="https://xxx/resources/python/${appname}/${appname}-${version}.zip"
workdir=/data/app/${object}/${appname}

function deploy_config() {
  nacos_username=
  nacos_password=
  object="$1"
  appname="$2"
  env="$3"
  version="$4"
  config_file="${workdir}/workdir/${env}/setting.ini"
  nacos_url="https://xxx"
  if [ -d "${workdir}/workdir/${env}/" ];then
    cd ${workdir}/workdir/${env}/ || exit
    nacos_accessToken=$(curl -X POST -s "${nacos_url}/nacos/v1/auth/login" -d "username=${nacos_username}&password=${nacos_password}" | awk -F '"' '{print $4}')
    config_url="${nacos_url}/nacos/v1/cs/configs?accessToken=${nacos_accessToken}&tenant=namespace-config-${env}&dataId=${version}&group=${object}.${appname}"
    config_newest_url="${nacos_url}/nacos/v1/cs/configs?accessToken=${nacos_accessToken}&tenant=namespace-config-${env}&dataId=newest&group=${object}.${appname}"
    config_http_code=$(curl --connect-timeout ${timeout} -s -I "${config_url}" | grep HTTP | awk '{print $2}')
    config_newest_http_code=$(curl --connect-timeout ${timeout} -s -I "${config_newest_url}" | grep HTTP | awk '{print $2}')
    if [ "${config_http_code}"x == "200"x ]; then
      curl --connect-timeout ${timeout} -s -o "${config_file}" "${config_url}"
    elif [ "${config_newest_http_code}"x == "200"x ]; then
      curl --connect-timeout ${timeout} -s -o "${config_file}" "${config_newest_url}"
    else
      echo "没有下载到对应的配置文件"
      exit 1
    fi
  fi
  cd ${workdir}/ || exit
}

function deploy_app() {
    mkdir -p ${workdir}/bak ${workdir}/workdir/${env}
    if [ ! -f ${workdir}/bak/${appname}-${version}.zip ] || [ $(ls -al ${workdir}/bak/${appname}-${version}.zip | awk '{print $5}') -ne $(curl -s -I ${app_url}|grep "Content-Length"|awk '{print $2}'|tr -d '\r') ];then
        curl -o ${workdir}/bak/${appname}-${version}.zip ${app_url}
    fi
    unzip -o -d ${workdir}/workdir/${env} ${workdir}/bak/${appname}-${version}.zip
    if [ $? != 0 ];then
      echo "部署压缩包失败,下载地址: ${app_url}"
      exit 1
    fi
}

# 更新 newest 配置
function update_newest_config() {
  nacos_url="https://xxx"
  nacos_username=
  nacos_password=
  config_file="${workdir}/workdir/${env}/setting.ini"
  nacos_accessToken=$(curl -X POST -s "${nacos_url}/nacos/v1/auth/login" -d "username=${nacos_username}&password=${nacos_password}" | awk -F '"' '{print $4}')
  curl --connect-timeout ${timeout} -X POST "${nacos_url}/nacos/v1/cs/configs?accessToken=${nacos_accessToken}" \
  -d "type=properties&tenant=namespace-config-${env}&dataId=newest&group=${object}.${appname}" --data-urlencode "content@${config_file}"
}


deploy_app
deploy_config ${object} ${appname} ${env} ${version}
update_newest_config