实现通过Jenkins api找到job构建人信息并定时发邮件(通过公司邮箱)

news2025/1/14 18:35:57

需求

在大屏上显示出每个项目的构建情况,如果构建失败,大屏上项目颜色变红的同时要给最新构建这个项目的用户发送邮件,提醒他构建失败了。

准备知识

大屏上显示的项目构建情况,其实是通过Jenkins api 获取的,想要看Jenkins 每个页面的api内容,直接在网页地址后面加上api/json就行了,如下图所示。对Jenkins api 不理解的可以去看:Jenkins API简单使用
在这里插入图片描述

效果

在这里插入图片描述

编码过程

pom.xml

添加好 jenkins api 、邮件、模板引擎的依赖

       <!-- jenkins api -->
        <dependency>
            <groupId>com.cdancy</groupId>
            <artifactId>jenkins-rest</artifactId>
            <version>0.0.30</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.1-jre</version>
        </dependency>
        <!--freemarker-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
                <!--  微软exchange 邮箱  -->
        <dependency>
            <groupId>com.surevine</groupId>
            <artifactId>ews-java-api</artifactId>
            <version>2.15</version>
        </dependency>

        <dependency>
            <groupId>javax.xml.ws</groupId>
            <artifactId>jaxws-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.8</version>
        </dependency>

        <dependency>
            <groupId>com.sun</groupId>
            <artifactId>ldapbp</artifactId>
            <version>1.0</version>
        </dependency>

发送邮件定时任务RemindTask

@Slf4j
@Component("remindTask")
public class RemindTask {
    @Autowired
    private CiDashBoardMapper ciDashBoardMapper;

    @Autowired
    private JenkinsConfig jenkinsConfig;

    @Autowired
    private CiDashBoardService ciDashBoardService;

    public void sendRemindEmail() {
        log.info("sendRemindEmail start! ");
        List<CiDashBoardVO> ciDashBoardVOList = ciDashBoardMapper.getCiDashBoardData();
        ciDashBoardVOList.forEach(ciDashBoardVO -> {
            String color=getColor(ciDashBoardVO.getColors());
            //如果是红色就给对应责任人发邮件
            if(Objects.equals( color, "red")){
                List<remindTaskVO> remindTaskVOList= ciDashBoardMapper.getDashBoardJobUrl(ciDashBoardVO.getProjectName(),color);
                if (CollUtil.isEmpty(remindTaskVOList)) {
                    log.info("remindTaskVOList列表是空的");
                }
                remindTaskVOList.forEach(remindTaskVO -> {
                    //创建jenkins连接,根据api一层层的找对应构建责任人
                    JobsApi jobApi = jenkinsConfig.connection().jobsApi();
                    String folderName=remindTaskVO.getFolderName();
                    String jobName=remindTaskVO.getJobName();
                    JobInfo jobInfo = jobApi.jobInfo(folderName, jobName);
                    int  number=jobInfo.lastBuild().number();
                    BuildInfo buildInfo = jobApi.buildInfo(folderName, jobName,number);
                   // String userId=buildInfo.actions().get(1).causes().get(0).userId();
                    String userName=buildInfo.actions().get(1).causes().get(0).userName();
                    //找到后发邮件
                    try {
                        Boolean sendRemindEmail=ciDashBoardService.sendRemindEmail(folderName,jobName,userName);
                        if(sendRemindEmail){
                            log.info("给构建失败责任人{}发送提醒邮件成功",userName);
                        }else{
                            log.info("给构建失败责任人{}发送提醒邮件失败,请检查",userName);
                        }
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                });
            }else{
                log.info("项目没有报红");
            }
        });
        log.info("sendRemindEmail end! ");
    }

    /**
     * @Description: 计算构建的颜色
     */
    private String getColor(String colors) {
        if (StrUtil.isBlank(colors)) {
            return JenkinsColorStatusEnum.UNKNOWN.getInfo();
        }
        if (colors.contains(JenkinsColorStatusEnum.RED.getInfo())) {
            return JenkinsColorStatusEnum.RED.getInfo();
        }
        if (colors.contains(JenkinsColorStatusEnum.YELLOW.getInfo())) {
            return JenkinsColorStatusEnum.YELLOW.getInfo();
        }
        return JenkinsColorStatusEnum.BLUE.getInfo();
    }

}

remindTaskVO

/**
 * @Description: 提醒任务vo
 */
@Data
public class remindTaskVO {
    private String folderName;
    private String jobName;

}

CiDashBoardMapper :获取展示在大屏上的所有项目以及对应job的projectName和urlName

public interface CiDashBoardMapper {

    List<CiDashBoardVO> getCiDashBoardData();
    /**
     * @Description: 获取展示在大屏上的所有项目对应job的projectName和urlName
     */
    List<remindTaskVO> getDashBoardJobUrl(String projectName, String color);
}

CiDashBoardMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.iov.rcs.ci.mapper.CiDashBoardMapper">
    <resultMap id="ciDashBoardMap" type="com.iov.rcs.ci.domain.CiDashBoardVO">
        <result property="projectName" column="project_name"/>
        <result property="colors" column="colors"/>
    </resultMap>
    <resultMap id="remindTaskMap" type="com.iov.rcs.ci.domain.remindTaskVO">
        <result property="folderName" column="folder_name"/>
        <result property="jobName" column="job_name"/>
    </resultMap>

    <select id="getCiDashBoardData" resultMap="ciDashBoardMap">
        SELECT project_name,
               GROUP_CONCAT(color Separator ',') as colors
        FROM (
                 SELECT b.*,
                        j.color
                 FROM jenkins_project_binding AS b
                          LEFT JOIN jenkins_data AS j ON j.jenkins_id = b.jenkins_id
                     and j.color not in ('aborted', 'notbuilt', 'disabled', 'blue_anime')
             ) as a
        group by project_name
    </select>
    <select id="getDashBoardJobUrl" resultMap="remindTaskMap">
        SELECT folder_name,job_name
        FROM (
        SELECT j.*,
        b.project_name
        FROM jenkins_project_binding AS b
        LEFT JOIN jenkins_data AS j ON j.jenkins_id = b.jenkins_id
        and j.color not in ('aborted', 'notbuilt', 'disabled', 'blue_anime')
        ) as a
        where project_name= #{projectName}
        and color=#{color}
    </select>
</mapper>

CiDashBoardService

public interface CiDashBoardService {

    AjaxResult getCiDashBoardData();


    /**
     * @Description: 发送邮件提醒功能
     */

    public  boolean sendRemindEmail(String folderName,String jobName,String username) throws ParseException;

}

CiDashBoardServiceImpl


@Slf4j
@Service
@AllArgsConstructor
public class CiDashBoardServiceImpl implements CiDashBoardService {

    @Autowired
    private CiDashBoardMapper ciDashBoardMapper;
    private final Configuration configuration;

    /**
     * @Description: 动态获取构建大屏的数据
     */
    @Override
    public AjaxResult getCiDashBoardData() {
        List<CiDashBoardVO> ciDashBoardVOList = ciDashBoardMapper.getCiDashBoardData();
        if (CollUtil.isEmpty(ciDashBoardVOList)) {
            return AjaxResult.error("ciDashBoardVOList列表是空的");
        }
        JSONArray jsonArray = new JSONArray();
        ciDashBoardVOList.forEach(ciDashBoardVO -> {
            JSONObject jsonObject = new JSONObject();
            jsonObject.set("projectName", ciDashBoardVO.getProjectName());
            jsonObject.set("color", getColor(ciDashBoardVO.getColors()));
            jsonArray.put(jsonObject);
        });
        return AjaxResult.success(jsonArray);
    }
    /**
     * @Description: 发送邮件提醒功能
     */
    @Override
    public boolean sendRemindEmail(String folderName,String jobName,String username) throws ParseException {
        DesvMailUtil mailUtil = new DesvMailUtil(“这里写公司规定发邮件的邮箱”);
        HashMap<String, Object> params = new HashMap<>();
        Template template;
        try {
            template = configuration.getTemplate("SendRemindTask.ftl");
        } catch (IOException e) {
            log.error("configuration.getTemplate error:{}", e.getMessage());
            return Boolean.FALSE;
        }
        initRemindEmailData(params, folderName,jobName,username);
        try {
            mailUtil.sendEmailByFreemarker(params, template);
        } catch (Exception e) {
            log.error("sendMail error:{}", e.getMessage());
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }
    /**
     * @Description: 初始化邮件内容
     */
    private void initRemindEmailData(HashMap<String, Object> params,String folderName,String jobName,String username) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        //params.put("to", appCpsp.getResponseEmail());
        params.put("to", "");
        params.put("title", "项目构建失败提醒");
        params.put("ResponseName",username);
        params.put("projectName",folderName);
        params.put("jobName",jobName);
        //当前日期
        params.put("today", DateUtil.format(new Date(), DatePattern.CHINESE_DATE_PATTERN));
    }
    /**
     * @Description: 计算构建的颜色
     */
    private String getColor(String colors) {
        if (StrUtil.isBlank(colors)) {
            return JenkinsColorStatusEnum.UNKNOWN.getInfo();
        }
        if (colors.contains(JenkinsColorStatusEnum.RED.getInfo())) {
            return JenkinsColorStatusEnum.RED.getInfo();
        }
        if (colors.contains(JenkinsColorStatusEnum.YELLOW.getInfo())) {
            return JenkinsColorStatusEnum.YELLOW.getInfo();
        }
        return JenkinsColorStatusEnum.BLUE.getInfo();
    }

}


DesvMailUtil 发送邮件工具


/**
 * @Description: 发送邮件工具
 */
@Data
@Slf4j
public class DesvMailUtil {

    private String username;

    private String password;

    private String domain;

    private String uri;
    public DesvMailUtil(String username, String password, String domain, String uri) {
        this.username = username;
        this.password = password;
        this.domain = domain;
        this.uri = uri;
    }

    public void sendEmailByFreemarker(Map<String, Object> params, Template template) throws Exception {
        // 新建server版本
        ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
        // 用户名,密码,域名
        ExchangeCredentials credentials = new WebCredentials(username, password, domain);
        service.setCredentials(credentials);
        service.setUrl(new URI(uri));
        String s = FreeMarkerTemplateUtils.processTemplateIntoString(template, params);
        EmailMessage msg = new EmailMessage(service);
        msg.setSubject(MapUtil.getStr(params, "title"));
        msg.setBody(MessageBody.getMessageBodyFromText(s));
        // 收件人
        msg.getToRecipients().add(MapUtil.getStr(params, "to"));
        // 发送
        msg.send();
    }
}

SendRemindTask.ftl

<!DOCTYPE html>
<html>
<head>
<meta http-equiv = Content-Type content="text/html; charset=utf-8"/>
    </head>
     <body>
        <p class="lines title">
           <span>Dear ${ResponseName}</span>
        </p>
        <p class="lines">
          <span> 您的 ${projectName}项目中的job: ${jobName}构建失败,请及时处理。</span>
        </p>
        <p class="lines">
          <span>如您有任何疑问,可联系: </span>
        </p>

        <div class="lines">
         <p>
          <span>${today}</span>
         </p>
         </div>
    </body>

    <style>
    .lines {
        text-align: left;
        font-size: 14px;
        margin-bottom: 20px;
    }

    .lines.title {
        font-size: 18px;
    }
    </style>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/70385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动部署项目,全靠它了!

前几天我把我的开源项目部署到了云服务器。 我部署的大概流程&#xff1a; 登录到云服务器控制台&#xff0c;新建一个服务器实例&#xff08;我用的 Ubuntu Linux&#xff09;。在自己的电脑上生成 SSH 秘钥&#xff0c;将生成的公钥和实例进行绑定。使用 SSH 登录到云服务器…

大数据 linux目录操作

linux 目录操作 常用权限操作 常用权限操作 chgrp命令 功能&#xff1a;修改文件所属组 语法格式&#xff1a;chgrp 用户组 文件&#xff08;说明&#xff1a;ch - change&#xff1b;grp - group&#xff09; chown命令 功能&#xff1a;改变文件所有者 语法格式&…

R语言Outliers异常值检测方法比较

识别异常值的方法有很多种&#xff0c;R中有很多不同的方法。 最近我们被客户要求撰写关于异常值检测的研究报告&#xff0c;包括一些图形和统计输出。关于异常值方法的文章结合了理论和实践。理论一切都很好&#xff0c;但异常值是异常值&#xff0c;因为它们不遵循理论。如…

chatGPT能不能有危险活体模型

🍿*★,*:.☆欢迎您/$:*.★* 🍿

【安全狗安全研究】SkidMap挖矿木马研究

近日&#xff0c;安全狗威胁情报中心监测到多起“Skidmap”挖矿木马事件。经研判&#xff0c;这些病毒感染事件是攻击者经Redis未授权访问漏洞攻击的方式植入挖矿木马“SkidMap”导致的。虽然“SkidMap”并非新型的病毒家族&#xff0c;但鉴于该病毒家族一直保持着较高的流行热…

多种方式绘制简单的作废章

作废章是常用的长方形印章&#xff0c;其形式如下图所示&#xff08;图片来自参考文献1&#xff09;。印章的形式很简单&#xff0c;就是红色方框内显示作废两个字&#xff0c;其实在网上百度长方形印章的话&#xff0c;可以搜索出很多类似形式的印章&#xff0c;区别仅在于尺寸…

lcd屏调试记录

一&#xff0c;lcd屏介绍 LCD液晶屏的接口类型非常丰富&#xff0c;最常用的接口主要有RGB、MCU、LVDS、MIPI接口。 1、RGB接口 LCD液晶屏的RGB接口通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及三者组合来得到丰富多彩的颜色&#xff0c;RGB分别代表红、绿、蓝三个通道的…

QT:多进程

标题1.多进程2.多线程3.常用方法1.多进程 (1)创建进程对象 QProcess::QProcess(QObject *parent nullptr)(2)启动进程去执行另外一个程序 void QProcess::start(const QString &command) //类似于system()/exec函数族 参数&#xff1a;command --》你要执行的另外一个程序…

36氪2022年Q3总收入同比增长两位数超预期,连续第四个季度盈利,广告收入同比增长20%

12月7日&#xff0c;36氪&#xff08;证券代码&#xff1a;KRKR&#xff09;披露2022年第三季度业绩。该季度36氪总收入同比增长11.5%至9461万元&#xff0c;净利润249万元&#xff0c;连续第四个季度实现盈利。 本季度&#xff0c;36氪广告业务持续表现优异&#xff0c;实现了…

windows电脑关机开机后没声音,重启就有声音故障处理方法

今天遇到一件非常奇葩的windows电脑, 从关机状态下进入系统没有声音,且从以下几点判断声卡硬件及驱动不存在故障,详见如下: 1、开机后任务栏右下角声音图标正常 2、声音设置——扬声器/麦克风(Realtek(R) Audio)正常; 3、windows+x键,选择“设备管理器”,找到“音频…

Primavera Unifier 常用标准数据要素

目录 一&#xff1a;什么是数据要素 二&#xff1a; 常用数据要素字段 一&#xff1a;什么是数据要素 数据元素是Oracle Primavera Unifier维护业务单据/表达的最小单元&#xff0c;也就是我们常说的字段&#xff0c;她将数据定义与字段标签相结合&#xff0c;成为用户在 Pr…

用70行Python编写一个概率编程语言

1、简介 在这篇文章中&#xff0c;我将介绍概率编程语言&#xff08;Probabilistic Programming Languages&#xff0c;简称PPL&#xff09;的工作原理&#xff0c;并逐步演示如何用Python构建一个简单的概率编程语言。 本文主要面向的读者是统计学家、AI研究员和好奇的程序员…

Python+Appium自动化测试(14)-yaml配置Desired capabilities

目录&#xff1a;导读 一&#xff0c;前言 二&#xff0c;使用yaml文件配置Capabilities示例 三&#xff0c;更新yaml文件的内容 四&#xff0c;结语 一&#xff0c;前言 在之前的appium自动化测试示例中&#xff0c;我们都是把构造driver实例对象的数据&#xff08;即Des…

对于单例,多进程的误解

单例 单例在多线程下&#xff0c;可以保证全局唯一&#xff0c;但在多进程下呢&#xff1f;子进程不共享父进程的变量 所以&#xff0c;每个进程都维护着一个自己的单例。 验证 创建appserver 以flask为例&#xff0c;以包的形式创建一个单例 # view.py-----------------…

四十、Java 多线程编程

Java 多线程编程 Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流&#xff0c;一个进程中可以并发多个线程&#xff0c;每条线程并行执行不同的任务。 多线程是多任务的一种特别的形式&#xff0c;但多线程使用了更小的资源开销。 这里定义和…

移动WEB开发之rem布局--苏宁首页案例制作(flexible.js)

简洁高效的rem适配方案flexible.js 手机淘宝团队出的简洁高效 移动端适配库 我们再也不需要在写不同屏幕的媒体查询&#xff0c;因为里面js做了处理 它的原理是把当前设备划分为10等份&#xff0c;但是不同设备下&#xff0c;比例还是一致的。 我们要做的&#xff0c;就是确…

[附源码]Python计算机毕业设计Django学生疫情防控信息填报系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【Java面试】说说你对ThreadLocal内存泄漏问题的理解

文章目录前置知识为什么会产生内存泄漏问题&#xff1f;如何解决内存泄露问题&#xff1f;为什么要使用弱引用&#xff1f;前置知识 讲解ThreadLocal的内存泄漏问题之前&#xff0c;首先得先知道什么是内存泄漏。 Memory overflow&#xff1a;内存溢出&#xff0c;没有足够的内…

第02章_MySQL环境搭建

目录第02章_MySQL环境搭建服务启动与停止登录MySQL查看版本退出MySQL1. MySQL操作1.1 MySQL的使用演示数据库查看所有的数据库创建数据库使用数据库查看数据库的创建信息删除数据库表格查看数据库的所有表格创建新的表格查看一个表的数据添加一条记录查看表的创建信息删除表格1…

FineReport地图数据图表-按钮控件

1. 概述 1.1 版本 报表服务器版本 功能变更 11.0 -- 1.2 应用场景 「按钮控件」可应用于填报、参数等场景中&#xff0c;添加按钮后&#xff0c;点击按钮可触发某些报表操作。如下图所示&#xff1a; 1.3 如何添加 1.3.1 填报控件 选中单元格后&#xff0c;点击右侧属性…