|
|
@@ -0,0 +1,355 @@
|
|
|
+properties([
|
|
|
+ parameters([
|
|
|
+ [$class: 'ChoiceParameter',
|
|
|
+ choiceType: 'PT_SINGLE_SELECT',
|
|
|
+ description: '选择要部署 API or UI',
|
|
|
+ name: 'modulePrefix',
|
|
|
+ randomName: 'choice-parameter-5631314439613978',
|
|
|
+ script: [
|
|
|
+ $class: 'GroovyScript',
|
|
|
+ fallbackScript: [
|
|
|
+ classpath: [],
|
|
|
+ sandbox: true,
|
|
|
+ script:
|
|
|
+ 'return[\'Could not get Env\']'
|
|
|
+ ],
|
|
|
+ script: [
|
|
|
+ classpath: [],
|
|
|
+ sandbox: true,
|
|
|
+ script:
|
|
|
+ 'return["java","ui"]'
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ],
|
|
|
+ [$class: 'CascadeChoiceParameter',
|
|
|
+ choiceType: 'PT_SINGLE_SELECT',
|
|
|
+ description: '选择要部署的项目',
|
|
|
+ name: 'module',
|
|
|
+ randomName: 'choice-parameter-5631314456178619',
|
|
|
+ referencedParameters: 'modulePrefix',
|
|
|
+ script: [
|
|
|
+ $class: 'GroovyScript',
|
|
|
+ fallbackScript: [
|
|
|
+ classpath: [],
|
|
|
+ sandbox: true,
|
|
|
+ script:
|
|
|
+ 'return[\'Could not get Environment from Env Param\']'
|
|
|
+ ],
|
|
|
+ script: [
|
|
|
+ classpath: [],
|
|
|
+ sandbox: true,
|
|
|
+ script:
|
|
|
+ ''' if (modulePrefix.equals("java")){
|
|
|
+ return["storlead-centre-api"]
|
|
|
+ }
|
|
|
+ else if(modulePrefix.equals("ui")){
|
|
|
+ return["sp-user-center"]
|
|
|
+ }
|
|
|
+ '''
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+ ]
|
|
|
+
|
|
|
+
|
|
|
+ ])
|
|
|
+])
|
|
|
+
|
|
|
+pipeline {
|
|
|
+ options {
|
|
|
+ timestamps()
|
|
|
+ }
|
|
|
+ environment {
|
|
|
+ GROUPID = readMavenPom().getGroupId()//com.storlead
|
|
|
+ ARTIFACTID = readMavenPom().getArtifactId()//sp-project
|
|
|
+ VERSION = readMavenPom().getVersion()//1.0
|
|
|
+ }
|
|
|
+ // 参数
|
|
|
+ parameters {
|
|
|
+ choice(
|
|
|
+ name: 'profile',
|
|
|
+ choices: ['test', 'prod','uat'],
|
|
|
+ description: '选择要部署的配置文件'
|
|
|
+ )
|
|
|
+ }
|
|
|
+ agent any
|
|
|
+ stages {
|
|
|
+ stage('处理参数') {
|
|
|
+ steps {
|
|
|
+ script {
|
|
|
+ echo "处理参数"
|
|
|
+ script {
|
|
|
+ //服务器配置
|
|
|
+ MODULE_PREFIX = "${params.modulePrefix}"
|
|
|
+ SERVER_SSH_PORT = 53023
|
|
|
+ SERVER_HOST = "node1.storlead.com"
|
|
|
+ SWARM_INIT_REPLICAS_NUM = 1
|
|
|
+
|
|
|
+ //服务配置
|
|
|
+ API_PORT = 9200
|
|
|
+ API_REMOTE_DEBUG_PORT = 9201
|
|
|
+ API_NAMESPACE_RESTFUL = "${params.module}"
|
|
|
+
|
|
|
+ //DOCKER配置
|
|
|
+ DOCKER_REGISTRY = "reg-aliyun"
|
|
|
+ DOCKER_HOST = "registry.cn-shenzhen.aliyuncs.com"
|
|
|
+ //Docker私服登陆url https://registry-vpc.cn-shenzhen.aliyuncs.com
|
|
|
+ DOCKER_LOGIN_REGISTRY = "https://${DOCKER_HOST}"
|
|
|
+
|
|
|
+ BUILD_PREFIX = "storlead-huawei"
|
|
|
+ //镜像完整名称 registry-vpc.cn-shenzhen.aliyuncs.com/storlead/sp-project-management-prod:1.0
|
|
|
+ DOCKER_IMG_NAME = "${DOCKER_HOST}/${BUILD_PREFIX}/${ARTIFACTID}-${params.module}-${params.profile}:${VERSION}"
|
|
|
+ //镜像名 storlead/sp-project-management-prod:1.0
|
|
|
+ IMG_NAME = "${BUILD_PREFIX}/${ARTIFACTID}-${params.module}-${params.profile}:${VERSION}"
|
|
|
+
|
|
|
+ PUSH_DOCK_IMG = true
|
|
|
+ SERVER_HOST_NAME = "test1"
|
|
|
+ echo "为指定 module 设定对应 服务器及端口"
|
|
|
+ echo "处理 ${params.module} 项目"
|
|
|
+ if (params.modulePrefix == "java") {
|
|
|
+ echo "---- storelad-centre-api"
|
|
|
+ script {
|
|
|
+ if (params.profile == "test") {
|
|
|
+ SWARM_INIT_REPLICAS_NUM = 1
|
|
|
+ SERVER_HOST = "test1.storlead.com"
|
|
|
+ API_PORT = 10020
|
|
|
+ API_REMOTE_DEBUG_PORT = 10021
|
|
|
+ SERVER_HOST_NAME = "test1"
|
|
|
+ } else if (params.profile == "prod") {
|
|
|
+ SERVER_HOST = "110.41.82.21"
|
|
|
+ API_PORT = 10020
|
|
|
+ API_REMOTE_DEBUG_PORT = 10020
|
|
|
+ SERVER_HOST_NAME = "node1"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (params.modulePrefix == "ui") {
|
|
|
+ script {
|
|
|
+ if (params.profile == "test") {
|
|
|
+ SERVER_HOST = "test1.storlead.com"
|
|
|
+ } else if (params.profile == "prod") {
|
|
|
+ SERVER_HOST = "110.41.82.21"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ echo "处理MODULE_NAMESPACE_RESTFUL"
|
|
|
+ //把 module 名 从 sp-xxx 变成 xxx 也就是 项目 的 namespace
|
|
|
+ if (API_NAMESPACE_RESTFUL == "sp-sales-api") {
|
|
|
+ API_NAMESPACE_RESTFUL = "sales"
|
|
|
+ }
|
|
|
+ echo "处理镜像推送"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ stage('Node 编译') {
|
|
|
+
|
|
|
+ when {
|
|
|
+ environment name: 'modulePrefix', value: 'ui'
|
|
|
+ }
|
|
|
+ agent {
|
|
|
+ docker {
|
|
|
+// image "registry-vpc.cn-shenzhen.aliyuncs.com/storlead/node:19-alpine"
|
|
|
+ image "node:20-alpine"
|
|
|
+ args '-v /app:/app/:z -v /etc/localtime:/etc/localtime:ro -u root'
|
|
|
+ reuseNode true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ steps {
|
|
|
+ withCredentials([
|
|
|
+ usernamePassword(credentialsId: 'storleadHW', usernameVariable: 'usernameHW', passwordVariable: 'passwordHW'),
|
|
|
+ usernamePassword(credentialsId: 'storlead', usernameVariable: 'username', passwordVariable: 'password')
|
|
|
+ ]) {
|
|
|
+ script {
|
|
|
+ echo "发布 UI 代码"
|
|
|
+
|
|
|
+ def remote = [:]
|
|
|
+ remote.allowAnyHosts = true
|
|
|
+ remote.name = "${SERVER_HOST}"
|
|
|
+ remote.host = "${SERVER_HOST}"
|
|
|
+ remote.port = 53023
|
|
|
+ remote.user = username
|
|
|
+ remote.password = password
|
|
|
+
|
|
|
+ if (params.profile == "prod") {
|
|
|
+ remote.port = 22
|
|
|
+ remote.user = "root"
|
|
|
+ remote.user = usernameHW
|
|
|
+ remote.password = passwordHW
|
|
|
+ }
|
|
|
+ if(params.module == 'sp-user-mobile-center') {
|
|
|
+ sh """cd ${params.modulePrefix}/${params.module} && npm install && npm run build:${params.profile}"""
|
|
|
+ } else {
|
|
|
+ sh """cd ${params.modulePrefix}/${params.module} && npm install && npm run ${params.profile}"""
|
|
|
+ }
|
|
|
+
|
|
|
+// sh """cd ${params.modulePrefix}/${params.module} && npm run ${params.profile}"""
|
|
|
+
|
|
|
+ sshCommand remote: remote, command: "mkdir -p /app/sp/ui/app-centre/${params.profile}/${params.module}"
|
|
|
+
|
|
|
+ sshCommand remote: remote, command: "rm -rf /app/sp/ui/app-centre/${params.profile}/${params.module}/dist/*"
|
|
|
+
|
|
|
+
|
|
|
+ echo "/app/sp/ui/sales/${params.profile}/${params.module}/*"
|
|
|
+
|
|
|
+ sshPut remote: remote, from: "${params.modulePrefix}/${params.module}/dist/", into: "/app/sp/ui/app-centre/${params.profile}/${params.module}/"
|
|
|
+
|
|
|
+ echo "${params.modulePrefix}/${params.module}/dist/,/app/sp/ui/app-centre/${params.profile}/${params.module}/"
|
|
|
+
|
|
|
+ sshCommand remote: remote, command: "cp -rf /app/sp/ui/app-centre/${params.profile}/${params.module}/dist/* /app/sp/ui/app-centre/${params.profile}/${params.module}/"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ stage('Maven 编译') {
|
|
|
+ when {
|
|
|
+ environment name: 'modulePrefix', value: 'java'
|
|
|
+ }
|
|
|
+ agent {
|
|
|
+ docker {
|
|
|
+ image 'maven:3-amazoncorretto-11'
|
|
|
+ //让docker 使用 host 宿主机的 m2仓库 使用root用户来运行 以让指定的~/.m2/config/setting.xml 阿里加速下载maven 依赖生效
|
|
|
+ args '-v /app:/app:z -v $HOME/.m2:/root/.m2:z -u root'
|
|
|
+ reuseNode true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ steps {
|
|
|
+ echo "编译 API 代码"
|
|
|
+ sh "mvn clean package -U -am -pl ${modulePrefix}/${params.module} -P${params.profile} -Dmaven.test.skip=true"
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 项目打包到镜像并推送到镜像仓库
|
|
|
+ stage('构建Docker镜像') {
|
|
|
+ when {
|
|
|
+ environment name: 'modulePrefix', value: 'java'
|
|
|
+ }
|
|
|
+ steps {
|
|
|
+ echo "构建Dcoker镜像-------------------"
|
|
|
+ script {
|
|
|
+ docker.withRegistry(DOCKER_LOGIN_REGISTRY, DOCKER_REGISTRY) {
|
|
|
+
|
|
|
+ BASE_IMAGE = 'registry.cn-shenzhen.aliyuncs.com/storlead/openjdk:11'
|
|
|
+ sh "docker pull ${BASE_IMAGE}"
|
|
|
+
|
|
|
+ sh """
|
|
|
+ echo '
|
|
|
+ FROM ${BASE_IMAGE}
|
|
|
+
|
|
|
+ COPY ${modulePrefix}/${params.module}/target/${params.module}.jar app.jar
|
|
|
+ EXPOSE ${API_PORT}
|
|
|
+ EXPOSE ${API_REMOTE_DEBUG_PORT}
|
|
|
+ HEALTHCHECK --interval=1m --timeout=10s CMD curl -f http://localhost:${API_PORT}/${API_NAMESPACE_RESTFUL}/actuator
|
|
|
+ ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "-Djava.awt.headless=true","-Dspring.profiles.active=${params.profile}", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:${API_REMOTE_DEBUG_PORT}","-jar","/app.jar"]' > Dockerfile
|
|
|
+ docker build -t ${DOCKER_IMG_NAME} .
|
|
|
+ """
|
|
|
+ sh "docker push ${DOCKER_IMG_NAME}"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ stage('启动服务') {
|
|
|
+ when {
|
|
|
+ environment name: 'modulePrefix', value: 'java'
|
|
|
+ }
|
|
|
+ steps {
|
|
|
+ withCredentials([
|
|
|
+ usernamePassword(credentialsId: 'storleadHW', usernameVariable: 'usernameHW', passwordVariable: 'passwordHW'),
|
|
|
+ usernamePassword(credentialsId: 'storlead', usernameVariable: 'username', passwordVariable: 'password'),
|
|
|
+ usernamePassword(credentialsId: 'reg-aliyun', usernameVariable: 'aliUsername', passwordVariable: 'aliPassword')
|
|
|
+ ]) {
|
|
|
+ script {
|
|
|
+
|
|
|
+ echo "启动服务"
|
|
|
+ echo "${aliPassword}"
|
|
|
+ echo "docker login -u ${aliUsername} -p ${aliPassword} ${DOCKER_LOGIN_REGISTRY}"
|
|
|
+
|
|
|
+ def remote = [:]
|
|
|
+ remote.name = "${SERVER_HOST}"
|
|
|
+ remote.host = "${SERVER_HOST}"
|
|
|
+ remote.port = 53023
|
|
|
+ remote.user = username
|
|
|
+ remote.password = password
|
|
|
+ remote.allowAnyHosts = true
|
|
|
+
|
|
|
+ //因为使用 docker swarm 发布 只能在 manage node 执行部署
|
|
|
+ if (params.profile == "prod") {
|
|
|
+ remote.port = 22
|
|
|
+ remote.user = "root"
|
|
|
+ remote.user = usernameHW
|
|
|
+ remote.password = passwordHW
|
|
|
+ }
|
|
|
+ if (PUSH_DOCK_IMG) {
|
|
|
+ //docker 认证
|
|
|
+ sshCommand remote: remote, command: "docker login -u ${aliUsername} -p ${aliPassword} ${DOCKER_LOGIN_REGISTRY}"
|
|
|
+ //如果选择推送才使用远程的版本 如果不选择推送到远程则直接运行本机刚打包的镜像版本即可
|
|
|
+ sshCommand remote: remote, command: "docker pull ${DOCKER_IMG_NAME}"
|
|
|
+ }
|
|
|
+ sh """
|
|
|
+ echo '
|
|
|
+ version: "3.7"
|
|
|
+ services:
|
|
|
+ ${ARTIFACTID}-${params.module}-${params.profile}:
|
|
|
+ image: ${DOCKER_IMG_NAME}
|
|
|
+ deploy:
|
|
|
+ replicas: ${SWARM_INIT_REPLICAS_NUM}
|
|
|
+ placement:
|
|
|
+ constraints:
|
|
|
+ - 'node.hostname == ${SERVER_HOST_NAME}'
|
|
|
+ update_config:
|
|
|
+ parallelism: 1
|
|
|
+ delay: 1m
|
|
|
+ restart_policy:
|
|
|
+ condition: on-failure
|
|
|
+ # 最多连续重试3次如果仍然失败则放弃重试
|
|
|
+ max_attempts: 3
|
|
|
+ healthcheck:
|
|
|
+ test: ["CMD", "curl", "-f", "http://localhost:${API_PORT}/${API_NAMESPACE_RESTFUL}/actuator"]
|
|
|
+ interval: 1m
|
|
|
+ timeout: 5s
|
|
|
+ retries: 3
|
|
|
+ start_period: 30s
|
|
|
+ environment:
|
|
|
+ - "TZ=Asia/Shanghai"
|
|
|
+ - "SPRING_PROFILES_ACTIVE=${params.profile}"
|
|
|
+ volumes:
|
|
|
+ - /app:/app
|
|
|
+ - /mnt/vdb/storlead:/mnt/vdb/storlead
|
|
|
+ ports:
|
|
|
+ - "${API_PORT}:${API_PORT}"
|
|
|
+ - "${API_REMOTE_DEBUG_PORT}:${API_REMOTE_DEBUG_PORT}"
|
|
|
+ networks:
|
|
|
+ - vonedao_net
|
|
|
+ extra_hosts:
|
|
|
+ - "www.storlead.com:172.18.194.161"
|
|
|
+ - "node1:110.41.82.21"
|
|
|
+ - "node2:110.41.174.46"
|
|
|
+ - "node3:121.37.226.174"
|
|
|
+ - "test1.storlead.com:172.18.194.168"
|
|
|
+ - "test2.storlead.com:172.18.194.163"
|
|
|
+ networks:
|
|
|
+ vonedao_net:
|
|
|
+ external: true
|
|
|
+ ' > ${ARTIFACTID}-${params.module}-${params.profile}-stack.yml
|
|
|
+ """
|
|
|
+ // if (params.profile =="dev") {
|
|
|
+ // sh "docker stack deploy -c ${ARTIFACTID}-${params.profile}-stack.yml ${ARTIFACTID}-${params.profile}"
|
|
|
+
|
|
|
+ // sh "docker ps -f name=${ARTIFACTID} -q | xargs --no-run-if-empty docker container stop"
|
|
|
+ // sh "docker container ls -a -fname=${ARTIFACTID} -q | xargs -r docker container rm"
|
|
|
+ // sh "docker run -d --restart=always -p ${API_PORT}:${API_PORT} -p ${API_REMOTE_DEBUG_PORT}:${API_REMOTE_DEBUG_PORT} -v /app:/app --name ${ARTIFACTID} ${DOCKER_IMG_NAME}"
|
|
|
+ // } else {
|
|
|
+ // 全部都以swarm 模式启动
|
|
|
+ sshPut remote: remote, from: "${ARTIFACTID}-${params.module}-${params.profile}-stack.yml", into: "/docker/sp/${ARTIFACTID}-${params.module}-${params.profile}-stack.yml"
|
|
|
+ sshCommand remote: remote, command: "docker stack deploy --resolve-image=always --with-registry-auth -c /docker/sp/${ARTIFACTID}-${params.module}-${params.profile}-stack.yml ${params.module}-${params.profile}"
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|