在Jenkins中直接使用File对象读取文件,会存在权限问题,读写文件只能用readFile、writeFile两个步骤,大多情况这两个步骤已经够用,但是如果需要读取maven的pom.xml文件的版本号,或者maven项目存在多模块情况下,需要检测当前被更新过的模块,可以使用共享库来实现。
1、设置全局共享库
设置方式Manage Jenkins » Configure System » Global Pipeline Libraries
Library Name #共享库的标识,在jenkinsfile中使用。
Default version #默认版本号,可以是分支名或tag标签。
Load implicitly #隐式加载,不再需要显式@Library('jenkins-penngo-library@main')的方式加载使用。
Allow default version to be overridden #如果勾选,允许被jenkinsfile配置的版本号覆盖。
Include @Library changes in job recent changes #如果勾选,则共享库的变更信息也会打印在构建信息中。
Cache fetched versions on controller for quick retrieval #如果选中此项,使用此库获取的版本将缓存在控制器上。
Retrieval method #配置公共库获取的方式,选择“Modern SCM”,选择使用Git仓库。也支持SVN仓库。
Library Path (optional) #允许您设置从SCM根目录到库目录的相对路径。针对根目录不是库目录的情况
共享库在系统内默认是是“可信的”,可以运行Java、Groovy、Jenkins内部API、Jenkins插件或第三方库中的所有方法。涉及安全更高级别的库或API应该封装在共享库中,以便在流水线中安全使用。
2、共享库的目录结构
├─src
│ ├─PomUtils.groovy
│ └─ModuleChange.groovy
├─var
├─sayHello.groovy
src #目录是标准的java源码结构,目录中放置的主要为类库。
var #目录是函数目录,主要存放全局调用的函数。
PomUtils.groovy
使用Dom读取pom.xml,获取version节点的版本号
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.Serializable;
class PomUtils implements Serializable{
static def getVersion(file){
def dbFactory = null;
def db = null;
def document = null;
String version = "";
try{
File f = new File(file);
dbFactory = DocumentBuilderFactory.newInstance();
db = dbFactory.newDocumentBuilder();
document = db.parse(file);
Element projectElement = document.getDocumentElement();
NodeList nodeList = projectElement.getChildNodes();
for(int i = 0; i < nodeList.getLength(); i++){
Node node = nodeList.item(i);
if(Node.ELEMENT_NODE == node.getNodeType()){
if("version".equalsIgnoreCase(node.getNodeName().trim())){
version = node.getTextContent();
break;
}
}
}
}
catch(Exception e){
System.out.println("error=" + e.getMessage());
version = e.getMessage();
}
return version;
}
}
ModuleChange.groovy
import java.io.File;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
class ModuleChange {
static boolean isChangeFile(path, millis){
File[] files = path.listFiles();
if(files != null){
for(File file:files){
if(file.isFile() == true && millis < file.lastModified()){
return true;
}
if(file.isDirectory() && isChangeFile(file, millis) == true){
return true;
}
}
}
return false;
}
static String checkModule(project){
long millis = System.currentTimeMillis() - 1000 * 60 * 2;
List<String> paths = Arrays.asList("task","web");
String module = "";
for(String path:paths){
File file = new File(project, path);
System.out.println(file.getAbsolutePath());
if(isChangeFile(file, millis) == true){
module = path;
break;
}
}
System.out.println("更新模块=={" + module + "}");
return module;
}
}
sayHello.groovy
def call(String info) {
echo "=====${info}======="
}
3、Jenkinsfile使用共享库
共享库使用的是Groovy代码,在Jenkinsfile中使用时,必须放在script指令里面。
需要部署的项目
test
├─task
│ ├─src
│ └─pom.xml
├─web
│ ├─src
│ └─pom.xml
├─pom.xml
@Library('jenkins-penngo-library@main') _
pipeline{
stages{
stage("发布"){
steps{
script{
sayHello("准备构建")
// ......省略的代码
def module = ModuleChange.checkModule(".");
def version = PomUtis.getVersion("${module}/pom.xml")
sh("""
cd ${module}
mvn clean package -Dmaven.test.skip=true
""")
// ......省略的代码
sh("""
cd target
zip -q -r ${module}-${version}.zip ${module}-${version}.jar bootstrap.yml
""")
// ......省略的代码,sshPublisher上传到服务器
sh("""
unzip -oq ${module}-${version}.zip -d ${app_name}
cd ${app_name}
java -XX:+UseG1GC -Xmx1G -jar ${module}-${version}.jar -Dspring.config.location=./bootstrap.yml --spring.profiles.active=prod
""")
}
}
}
}
}