某大佬让我实现gitlab的webhook,监听到其它分支合并到mater分支后给DY发邮件。我做过用 push 到 github触发jenkins实现自动部署,但是那个时候就是自己玩,不用考虑分支和其它。其实一旦扯到分支上,其实我个人感觉就难了。但是,还是要干的。
一开始我想简单啊,在项目里的URL添加自己阿里云的一个sout接口,选择Merge requet events,点击Add webhook。如下图所示,这不就OK了吗?
因为我自己没事整 本地push到github然后触发jenkins自动构建项目也是这么简单啊。
1)创建merge请求
2)修改merge请求
3)撤销merge请求
4)重新打开merge请求
5)同意merge请求
都触发我的请求,我哪知道哪种是哪种,而且我想要合并到master的请求,现在dev1合并到dev2也给触发,很乱。
但是我就发现其实有很多操作是会调用这个上面钩子程序的URL的,然后就在这个时候,一位叫胜哥的给我指了条明路,看文档,就是上图中的箭头,从此就解决了很多疑惑。
然后在文档中找到如下图所示的内容,这不就是我想要的东西吗?
百度了一段代码,获取了上图中的请求体(要亲自试,你才会明白里面参数的含义)
@RequestMapping("/email")
@ResponseBody
public String sendEmail(HttpServletRequest request) {
InputStream is = null;
try {
is = request.getInputStream();
StringBuilder sb = new StringBuilder();
byte[] b = new byte[4096];
for (int n; (n = is.read(b)) != -1; ) {
sb.append(new String(b, 0, n));
}
System.out.println("----------------------->");
System.out.println(sb);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 发送邮件
//emailService.sendSimpleMail();
return "success";
我有五份请求体,正如步骤(3)中的5种情况。分析他们的不同,其实就是看他们有什么区别
这里用到了超级好用 json 格式化网站 https://tool.lu/json/
因为我的需求是我要合并请求并且合并到master分支的才进行业务逻辑,所以就在网站里分析。
打开两个格式化json的网页,当你在这两个页面之间来回切换你就能发现他们的不同(除了时间)
import io.swagger.annotations.Api;
import lombok.Data;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* @author chaird
* @create 2020-06-18 23:22
*/
@Api("分支合并到master钩子接口")
@RestController
@RequestMapping("/admin/webhook")
public class WebHookController {
/** merge请求状态 */
private final String MERGE_STATUS = "can_be_merged";
/** merge操作状态 */
private final String STATUS = "merged";
/** 目标分支,即要合并到的分支 */
private final String TARGET_BRANCH = "master";
@RequestMapping(value = "/invokeMergeHook", method = RequestMethod.POST)
public Object invokeMergeHook(@RequestBody GLWHRootInfo glwhRootInfo) {
String result;
try {
// 获取项目名称
String projectName = glwhRootInfo.getProject().getName();
// 获取gitlab触发此次请求的操作类型,比如提交、同意、撤销合并分支请求
String merge_status = glwhRootInfo.getObject_attributes().getMerge_status();
String state = glwhRootInfo.getObject_attributes().getState();
// 获取source分支和获取target分支
String target_branch = glwhRootInfo.getObject_attributes().getTarget_branch();
String source_branch = glwhRootInfo.getObject_attributes().getSource_branch();
// 获取操作用户邮箱
String user_email =
glwhRootInfo.getObject_attributes().getLast_commit().getAuthor().getEmail();
// 如果merge_status为D0_MERGE 并且目标分支是master分支
if (MERGE_STATUS.equals(merge_status)
&& STATUS.equals(state)
&& TARGET_BRANCH.equals(target_branch)) {
System.out.println("--------------->发邮件");
String msg =
"此邮件为测试邮件:"
+ "此邮件为测试邮件"
+ "\n"
+ "projectName:"
+ projectName
+ "\n"
+ "target_branch:"
+ target_branch
+ "\n"
+ "source_branch:"
+ source_branch
+ "\n"
+ "user_email:"
+ user_email;
// 发送邮箱
System.out.println("-------------------------------------------------------");
result = "分支合并成功并且符合发送邮箱要求";
} else {
result = "不符合发送邮箱要求";
}
} catch (Exception e) {
return "非gitlab发送的请求";
}
return result;
}
}
/** Gitlab触发webhook中的RequestBody对应的实体类 */
@Data
class GLWHRootInfo {
private String object_kind;
private User user;
private Project project;
private Object_attributes object_attributes;
List labels = new ArrayList<>();
private Changes changes;
private Repository repository;
}
@Data
class State {
private String previous;
private String current;
}
@Data
class Author {
private String name;
private String email;
}
@Data
class Changes {
private State state;
private Updated_at updated_at;
private Total_time_spent total_time_spent;
}
@Data
class Last_commit {
private String id;
private String message;
private String timestamp;
private String url;
private Author author;
}
@Data
class Merge_params {
private String force_remove_source_branch;
}
@Data
class Object_attributes {
private String assignee_id;
private int author_id;
private String created_at;
private String description;
private String head_pipeline_id;
private int id;
private int iid;
private String last_edited_at;
private String last_edited_by_id;
private String merge_commit_sha;
private String merge_error;
private Merge_params merge_params;
private String merge_status;
private String merge_user_id;
private boolean merge_when_pipeline_succeeds;
private String milestone_id;
private String source_branch;
private Integer source_project_id;
private String state;
private String target_branch;
private Integer target_project_id;
private Integer time_estimate;
private String title;
private String updated_at;
private String updated_by_id;
private String url;
private Source source;
private Target target;
private Last_commit last_commit;
private boolean work_in_progress;
private Integer total_time_spent;
private String human_total_time_spent;
private String human_time_estimate;
private String action;
}
@Data
class Project {
private int id;
private String name;
private String description;
private String web_url;
private String avatar_url;
private String git_ssh_url;
private String git_http_url;
private String namespace;
private int visibility_level;
private String path_with_namespace;
private String default_branch;
private String ci_config_path;
private String homepage;
private String url;
private String ssh_url;
private String http_url;
}
@Data
class Repository {
private String name;
private String url;
private String description;
private String homepage;
}
@Data
class Source {
private int id;
private String name;
private String description;
private String web_url;
private String avatar_url;
private String git_ssh_url;
private String git_http_url;
private String namespace;
private Integer visibility_level;
private String path_with_namespace;
private String default_branch;
private String ci_config_path;
private String homepage;
private String url;
private String ssh_url;
private String http_url;
}
@Data
class Target {
private int id;
private String name;
private String description;
private String web_url;
private String avatar_url;
private String git_ssh_url;
private String git_http_url;
private String namespace;
private int visibility_level;
private String path_with_namespace;
private String default_branch;
private String ci_config_path;
private String homepage;
private String url;
private String ssh_url;
private String http_url;
}
@Data
class Total_time_spent {
private String previous;
private Integer current;
}
@Data
class Updated_at {
private String previous;
private String current;
}
@Data
class User {
private String name;
private String username;
private String avatar_url;
}
文档上都说了啥时候触发请求,我没用看到,我自己试出来的,然后有什么用呢,不看文档的人会吃亏的。
1)看文档,看官方文档(虽然我还没有做到),这是技术人员的必经之路。
2)其实我我没有感觉做出来多少厉害,我只是感觉从解决问题的过程中学到解决问题的思路以及看请求体的重要性。
3)有人指导,这确实是一看运气
https://git.lug.ustc.edu.cn/help/user/project/integrations/webhooks
https://blog.csdn.net/qq_37171353/article/details/106470391