Bootstrap

Jenkins实践(三):分包编译部署到Maven私仓

本文主要是针对springboot多模块项目,参数化构建、分包部署到maven私仓的记录。本文以上篇文章为基础进行记录。

系列文章:

Jenkins入门(一):从搭建到部署第一个Springboot项目(踩坑记录)_ub24.04安装jenkins-CSDN博客

Jenkins入门(二):流水线方式部署多模块Springboot项目-CSDN博客

目录

一、Maven私仓搭建

1.1 创建Ubuntu虚拟机

1.2 安装NATAPP内网穿透工具

1.3 安装 JDK8

1.4 安装 Nexus

1.5 配置Nexus私库地址

二、Jenkinsfile分包部署脚本

2.1 Jenkinsfile修改

2.2 idea 格式化Jenkins

三、Jenkins多参数配置


一、Maven私仓搭建

目前Jenkins和项目部署到服务器上,Maven私仓部署到ubuntu虚拟机上。

1.1 创建Ubuntu虚拟机

使用VMware创建Ubuntu虚拟机。注意记住创建的用户和密码

参考:VMware 虚拟机图文安装和配置 Ubuntu Server 22.04 LTS 教程_00-installer-config.yaml-CSDN博客

1.2 安装NATAPP内网穿透工具

用于提供Maven私仓的外网地址。

NATAPP1分钟快速新手图文教程 - NATAPP-内网穿透 基于ngrok的国内高速内网映射工具 参考官方文档NATAPP1分钟快速新手图文教程 - NATAPP-内网穿透 基于ngrok的国内高速内网映射工具

1.3 安装 JDK8

参考:Linux开发环境搭建(二)之安装JDK和Maven_amazon linux2 安装java-CSDN博客 

1.4 安装 Nexus

下载

Nexus3.x官网

Unix 3.54.1版本:unix或者linux下载
提取码:tymn

解压
tar -zxvf nexus-3.54.1-01-unix.tar.gz -C /home/mlj/soft/Nexus/
修改环境变量
vi /etc/profile
export NEXUS_HOME=/home/hsp/data/Nexus/nexus-3.54.1-01
export PATH=$NEXUS_HOME/bin
source /etc/profile
启动nexus

进入路径/home/mlj/soft/Nexus/nexus-3.54.1-01/bin执行

./nexus start

默认端口为8081,访问ip:8081进去,按照步骤填写密码,修改密码。

注意:用户名和密码谨慎填写,需要记住,后面项目中要使用

启动natapp

设置映射端口为8081,启动natapp,访问日志打印的域名就进入了nexus控制台

关于nexus控制台的学习可以参考如下文档:

使用Nexus在Ubuntu环境下搭建Maven私服_ubuntu 安装 nexus-CSDN博客

1.5 配置Nexus私库地址

修改Maven settings文件

<servers>
    <!-- 这是配置访问私有仓库的用户名密码 -->
    <server>
      <!-- id标签可以随便填,只需要在servers中唯一即可,后面很多地方会使用该id -->
      <id>self-maven</id>
      <username>nexus</username>
      <password>deplyment123</password>
    </server>
</servers>   

<profiles>
	<profile>
        <id>nexus</id>
        <!--声明一个或多个远程仓库  -->
		<repositories>
			<!-- 声明一个 Nexus 私服上的仓库  -->
			<repository>
				<!--仓库id,这个id就是上面配置的账号密码id  -->
				<id>self-maven</id>
				<!-- 仓库的名称 -->
				<name>nexus</name>
				<!--仓库的地址  修改为natapp动态域名-->
				<url>http://localhost:8081/repository/maven-public/</url>
				<!-- 是否开启该仓库的 release 版本下载支持 -->
				<releases>
					<enabled>true</enabled>
				</releases>
				<!-- 是否开启该仓库的 snapshot 版本下载支持 -->
				<snapshots>
					<enabled>true</enabled>
				</snapshots>
			</repository>
		</repositories>
		<!-- 声明一个或多个远程插件仓库 修改为natapp动态域名 -->
		<pluginRepositories>
			<!--声明一个 Nexus 私服上的插件仓库  -->
			<pluginRepository>
				<!--插件仓库 id -->
				<id>self-maven</id>
				<!--插件仓库 名称 -->
				<name>nexus</name>
				<!-- 配置的插件仓库的地址 -->
				<url>http://localhost:8081/repository/maven-public/</url>
				<!-- 是否开启该插件仓库的 release 版本下载支持 -->
				<releases>
					<enabled>true</enabled>
				</releases>
				<!-- 是否开启该插件仓库的 snapshot 版本下载支持 -->
				<snapshots>
					<enabled>true</enabled>
				</snapshots>
			</pluginRepository>
		</pluginRepositories>
          <properties>
              <maven.compiler.source>1.8</maven.compiler.source>
              <maven.compiler.target>1.8</maven.compiler.target>
              <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
          </properties>
	<!-- 默认该profile生效 -->
          <activation>
              <activeByDefault>true</activeByDefault>
          </activation>
      </profile>
</profiles>       

 修改项目中pom文件,主要用于依赖上传

<distributionManagement>
        <repository>
            <!--注意这个id一定要填写我们maven的setting.xml当中配置的id-->
            <id>self-maven</id>
            <url>http://i97e4t.natappfree.cc/repository/maven-releases/</url>
        </repository>
        <snapshotRepository>
            <!--注意这个id一定要填写我们maven的setting.xml当中配置的id-->
            <id>self-maven</id>
            <url>http://i97e4t.natappfree.cc/repository/maven-snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

部署测试:

mvn deploy -Dmaven.test.skip=true

刷新nexus控制台能看到依赖已上传:

测试下载:

 <dependency>
        <groupId>com.xx</groupId>
        <artifactId>xx-common</artifactId>
        <version>1.2.1-SNAPSHOT</version>
 </dependency>

报错:Since Maven 3.8.1 http repositories are blocked

解决:

使用私服作为mirrors,如果maven是3.8.1+的版本,会提示:Since Maven 3.8.1 http repositories are blocked。3.8.1版本开始,处于安全考虑,maven禁用了http的镜像仓库,但是我们安装的私服通常都是http的地址,所以报这个错误。

将setting里下面配置注释掉:

<mirrors>
    	<mirror>
			  <id>maven-default-http-blocker</id>
			  <mirrorOf>dummy</mirrorOf>
			  <name>Dummy mirror to override default blocking mirror that blocks http</name>
			  <url>http://0.0.0.0/</url>
			  <blocked>true</blocked>
		</mirror>
	</mirros>

参考:【有手就行】:从无到有搭建个人Maven私有仓库_maven搭建私有仓库-CSDN博客 

二、Jenkinsfile分包部署脚本

背景:springboot项目模块太多,主项目只有一个,每次修改代码需要编译所有模块会浪费资源,也会导致jenkins构建很慢,后面考虑优化成增量部署,可选择修改过的模块进行编译部署,没改过的从私仓拉取,最后对主项目进行打包即可。

项目结构:

思路:

  • 对基础模块进行编译部署上传私仓,包括业务模块的api(因为可能会引用业务模块的api)
  • 对业务模块的biz进行编译部署上传私仓
  • 对server启动类模块打包,不上传私仓

2.1 Jenkinsfile修改

#!groovy
pipeline {

    agent any

    environment {
        // DockerHub 凭证 ID(登录您的

        DOCKER_CREDENTIAL_ID = 'dockerhub-id'
        //  GitHub 凭证 ID (推送 tag 到 GitHub 仓库)
        //         GITHUB_CREDENTIAL_ID = 'github-id'
        // kubeconfig 凭证 ID (访问接入正在运行的 Kubernetes 集群)
        KUBECONFIG_CREDENTIAL_ID = 'demo-kubeconfig'
        // 镜像的推送
        REGISTRY = 'docker.io'
        //  DockerHub 账号名
        DOCKERHUB_NAMESPACE = 'docker_username'
        // GitHub 账号名
        //         GITHUB_ACCOUNT = 'https://gitee.com/zhijiantianya/ruoyi-vue-pro'
        // 应用名称
        APP_NAME = 'hbintrade-server'
        // 应用部署路径
        APP_DEPLOY_BASE_DIR = '/var/jenkins_home/workspace/'
        //         /var/jenkins_home/workspace/hbintrade-framework
        def SERVER_NAME = "$project_name"
        def BASIC_MODULE_NAME = "$basic_module_name"
        def BUSINESS_MODULE_NAME = "$business_module_name"
    }


    stages {
        stage('打印信息') {      //打印信息
            steps {
                echo '变量打印信息'
                echo "Project_Pipeline_name: $JOB_NAME"
                echo "BASIC_MODULE_NAME: $BASIC_MODULE_NAME"
                echo "BUSINESS_MODULE_NAME: $BUSINESS_MODULE_NAME"
                echo "SERVER_NAME: $SERVER_NAME"
                echo "workspace: $WORKSPACE"
                echo "branch: $branch_name"           //gitlab分支名
                echo "build_id: $BUILD_ID"
// 			echo "target_action: $action"
                //                 echo "registryUrl: $registryUrl"
                //                 echo "image_repository: $registryUrl/$Project_name"
            }
        }
        stage('检出') {
            steps {
                git credentialsId: 'xxx', url: 'https://gitee.com/xxx/xxx-framework.git',
                        branch: "$branch_name"
            }
        }

        stage('构建') {
            steps {
//			echo "跳过构建!!! "
//                sh 'mvn deploy -Dmaven.test.skip=true'
                script {
                    // 使用 replace 方法去除双引号
                    def BASIC_MODULE_NAME_STR = BASIC_MODULE_NAME.replace("\"", "")
                    def BUSINESS_MODULE_NAME_STR = BUSINESS_MODULE_NAME.replace("\"", "")
                    def SERVER_NAME_STR = SERVER_NAME.replace("\"", "")

                    if (BASIC_MODULE_NAME_STR != '') {
                        for (item in BASIC_MODULE_NAME.tokenize(',')) {
                            echo "开始构建基础模块并上传到maven私仓 " + item
                            END_STR = item[-3..-1]
                            if ("$END_STR" == "api") {
                                sh 'cd ' + item[0..-5] + ' && mvn deploy -pl ' + item + ' -Dmaven.test.skip=true'
                            } else {
                                sh 'mvn deploy -pl ' + item + ' -Dmaven.test.skip=true'
                            }
                        }
                    }

                    if (BUSINESS_MODULE_NAME_STR != '') {
                        for (item in BUSINESS_MODULE_NAME.tokenize(',')) {
                            echo "开始构建业务模块并上传到maven私仓 " + item + '-biz'
                            sh 'cd ' + item + ' && mvn deploy -pl ' + item + '-biz -Dmaven.test.skip=true'
                        }
                    }

                    if (SERVER_NAME_STR != '') {
                        for (item in SERVER_NAME.tokenize(',')) {
                            echo "开始打包主项目" + item
                            sh 'mvn clean package -pl ' + item + ' -Dmaven.test.skip=true'
                        }
                    }
                }
            }
        }

        stage('部署') {
            steps {
                sh 'cp -f ' + ' script/shell/deploy.sh ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" + '/'
                sh 'cp -f ' + "${env.APP_NAME}" + '/target/*.jar ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" + '/build/'
                archiveArtifacts "${env.APP_NAME}" + '/target/*.jar'
                sh 'chmod +x ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" + '/deploy.sh'
                sh 'bash ' + "${env.APP_DEPLOY_BASE_DIR}" + "${env.APP_NAME}" + '/deploy.sh'
            }
        }
    }
}

注意:部署业务模块时,由于项目结构不同,需要进入 业务模块目录内执行构建,否则找不到业务模块的api子模块。

问题:groovy.lang.MissingPropertyException: No such property: Missing for class: Script3

解决:Jenkins里Quote Value勾选,Jenkinsfile获取变量值后要去除引号

2.2 idea 格式化Jenkins

Jenkinsfile是Groovy语言编写的,写Jenkinsfile过程中发现idea没办法对Jenkinsfile格式化,需要设置一下。

打开idea -> 设置 -> File Types -> Groovy ->添加新的文件类型,即添加上Jenkinsfile即可

三、Jenkins多参数配置

注意:参数name与Jenkins里面保持一致,Quote Value勾选否则不选择模块的话会报错“变量未定义”,选择后Jenkins里面处理参数值,去除双引号。具体参考Jenkinsfile

3.1 Jenkins项目参数配置

basic_module_name基础模块配置

business_module_name业务模块

 project_name主项目

3.2 选择需要的模块构建

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;