时间:2022-12-11 11:54:21 | 栏目:JAVA代码 | 点击:次
背景:
使用java实现jenkins构建很简单,但是如何确定什么时候job已经构建完成才是关键,而且要实现多个job并行构建。
分析:
我有一篇文章提到过使用java实现jenkins构建,但是获取的结果是最后一次构建的结果,不能实时获取构建结果.实时获取构建结果有个关键的点,在于他会根据构建的版本号获取当前版本号的结果,如果对应版本号的结果为空则证明还在构建过程中,按照这个思路我们就可以进行编码了.
1.判断指定构建版本号的job是否执行完;
2.根据是否构建完成获取构建结果;
/** * 判断指定的构建版本号是否执行完成 * * @param number * 构建版本号 * @param jobName * 构建名称 * @return true为构建完成,false为未构建完成 */ public static boolean isFinished(int number, String jobName) { boolean isBuilding = false; if (number <= 0) { throw new IllegalArgumentException("jenkins build number must greater than 0!"); } try { JobWithDetails job = jobs.get(jobName).details(); // build 如果为空则证明正在构建,走else了 Build buildByNumber = job.getBuildByNumber(number); if (null != buildByNumber) { BuildWithDetails details = buildByNumber.details(); if (null != details) { isBuilding = details.isBuilding(); } else { isBuilding = true; } } else { isBuilding = true; } return !isBuilding; } catch (Exception e) { e.printStackTrace(); } finally { } return false; }
private static int nextNum = 0; private static JobWithDetails jobWithDetails = null; private static boolean flag = true; private static BuildResult buildResult = null; /** * 根据项目名称触发jenkins构建 * * @param paramJobName * 项目名称 * @return 构建结果:如果为null则表明项目名称在jenkins中没有匹配的job */ public static BuildResult triggerJenkins(String paramJobName) { try { jobWithDetails = jobs.get(paramJobName).details(); nextNum = jobWithDetails.getNextBuildNumber(); jobWithDetails.build(); System.out.println("正在构建……"); while (flag) { jobWithDetails = jobs.get(paramJobName).details(); if (isFinished(nextNum, paramJobName)) { flag = false; System.out.println("构建完成……"); } Thread.sleep(2000); } buildResult = jobWithDetails.getLastBuild().details().getResult(); return buildResult; } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } return buildResult;
补充知识:Java 对接Jenkins API操作(不需要勾选允许站点跨域访问)
最先的是jenkins的跨域问题 如果是一般学习直接关闭 在公司Java对接jenkins的话 还是不关闭
需要的maven 依赖
<dependency> <groupId>com.offbytwo.jenkins</groupId> <artifactId>jenkins-client</artifactId> <version>0.3.8</version> </dependency>
JenkinsUtil 不用勾选跨域也可以访问
public class JenkinsUtils { private static final Logger LOGGER = LoggerFactory.getLogger(JenkinsUtils.class); private static String job_class="hudson.model.FreeStyleProject"; private static String folder_class= "com.cloudbees.hudson.plugins.folder.Folder"; public static JenkinsServer getJenkinsServer(String userName, String password, String jenkinsUrl) { JenkinsHttpClient jenkinsHttpClient=null; JenkinsServer jenkinsServer=null; try{ jenkinsHttpClient = new JenkinsHttpClient(new URI(jenkinsUrl), userName, password); jenkinsServer = new JenkinsServer(jenkinsHttpClient); }catch (URISyntaxException ex){ LOGGER.info("JenkinsUtils :{}",ex.getMessage()); throw new ResourceCenterException(ResponseCodeEnum.SYSTEM_ERROR_MESSAGE); } return jenkinsServer; } ; public static Integer buildWithParams(HashMap<String, String> params,String jobName, JenkinsServer jenkinsServer) { JobWithDetails job=null; int nextBuildNumber =0; try{ job = jenkinsServer.getJob(jobName); /*根据名称获取job*/ if(null==job){ LOGGER.info("jenkins 不存在该Job :{}",jobName); throw new ResourceCenterException(ResponseCodeEnum.JOB_NOT_EXIST); } /*获取下一次构建的构建编号,可以用于在触发构建前,先记录构建编号。在后续获取指定编号的构建结果*/ //这里需要 一个插件 Build With Parameters Plugin nextBuildNumber=job.getNextBuildNumber(); job.build(params,true); }catch (IOException ex){ LOGGER.info("JenkinsUtils :{}",ex.getMessage()); throw new ResourceCenterException(ResponseCodeEnum.SYSTEM_ERROR_MESSAGE); } //获取结果 如果为null表示正在构建中 SUCCESS 表示构建成功 return nextBuildNumber; } ; /** * 获取job 某一个构建的日志 * @param number * @param jobName * @param jenkinsServer * @return * @throws Exception */ public static String getBuildLogPrint(Integer number, String jobName, JenkinsServer jenkinsServer) { BuildWithDetails buildWithDetails=getBuildDetails(number,jobName,jenkinsServer); String log =null; try{ log=buildWithDetails.getConsoleOutputText(); }catch (IOException ex){ LOGGER.info("JenkinsUtils :{}",ex.getMessage()); throw new ResourceCenterException(ResponseCodeEnum.SYSTEM_ERROR_MESSAGE); } return log; } /** * 获取job 某一个构建的结果 :成功,失败,取消等状态 * @param number * @param jobName * @param jenkinsServer * @return * @throws Exception */ public static String getBuildLogResult(Integer number, String jobName, JenkinsServer jenkinsServer) throws Exception { BuildWithDetails buildWithDetails=getBuildDetails(number,jobName,jenkinsServer); BuildResult result = buildWithDetails.getResult(); return result.name(); } private static BuildWithDetails getBuildDetails(Integer number, String jobName, JenkinsServer jenkinsServer){ JobWithDetails job = null; Build build=null; BuildWithDetails buildWithDetails=null; try{ job=jenkinsServer.getJob(jobName); /*根据jobName名称获取job*/ build = job.getBuildByNumber(number); buildWithDetails = build.details(); }catch (Exception e){ LOGGER.info("JenkinsUtils :{}",e.getMessage()); throw new ResourceCenterException(ResponseCodeEnum.SYSTEM_ERROR_MESSAGE); } return buildWithDetails; } //暂时解析一层文件夹 public static String getJobFullName(JenkinsServer jenkinsServer,String jobName){ String jobFullName=""; try { Map<String, Job> jobs1 = jenkinsServer.getJobs(); if(null!=jobs1.get(jobName)){ return jobName; } Set<String> params = jobs1.keySet(); for (String tempKey: params) { jobFullName=tempKey; JobWithDetails job = jenkinsServer.getJob(tempKey); if(!folder_class.equals(job.get_class())){ continue; } Optional<FolderJob> folderJob = jenkinsServer.getFolderJob(job); FolderJob folderJob1 = folderJob.get(); Map<String, Job> jobs = folderJob1.getJobs(); Job targetJob = jobs.get(jobName); if(null!=targetJob){ jobFullName=jobFullName+"/"+jobName; return jobFullName; } } }catch (IOException ex){ LOGGER.info("JenkinsUtils :{}",ex.getMessage()); throw new ResourceCenterException(ResponseCodeEnum.SYSTEM_ERROR_MESSAGE); } return jobFullName; } }
为什么Java对接jenkins 不需要勾选跨域访问也可以:
job.build(params,true);
这个方法是带参数构建job true表示需要跨域访问 所以在代码底层为true时 会去
http://JENKINS_URL/crumbIssuer/api/xml
获取crumb 然后放进header里面 就可以了