构建触发器新增批量触发、构建支持定时触发

This commit is contained in:
bwcx_jzy 2021-12-14 15:28:10 +08:00
parent 8ca27386c4
commit d9e5bc70b3
22 changed files with 418 additions and 142 deletions

View File

@ -30,34 +30,39 @@ package io.jpom.common;
*/
public class ServerOpenApi {
public static final String HEAD = "JPOM-TOKEN";
public static final String HEAD = "JPOM-TOKEN";
/**
* 用户的token
*/
public static final String USER_TOKEN_HEAD = "JPOM-USER-TOKEN";
/**
* 用户的token
*/
public static final String USER_TOKEN_HEAD = "JPOM-USER-TOKEN";
/**
* 存放token的http head
*/
public static final String HTTP_HEAD_AUTHORIZATION = "Authorization";
/**
* 存放token的http head
*/
public static final String HTTP_HEAD_AUTHORIZATION = "Authorization";
public static final String API = "/api/";
public static final String API = "/api/";
public static final String UPDATE_NODE_INFO = API + "node/update";
public static final String UPDATE_NODE_INFO = API + "node/update";
/**
* 安装id
*/
public static final String INSTALL_ID = API + "/installId";
/**
* 安装id
*/
public static final String INSTALL_ID = API + "/installId";
/**
* 触发构建, 第一级构建id,第二级token
*/
public static final String BUILD_TRIGGER_BUILD = API + "/build/{id}/{token}";
/**
* 触发构建, 第一级构建id,第二级token
*/
public static final String BUILD_TRIGGER_BUILD = API + "/build/{id}/{token}";
/**
* 触发构建(), 第一级构建id,第二级token
*/
public static final String BUILD_TRIGGER_BUILD2 = API + "/build2/{id}/{token}";
/**
* 触发构建 批量触发
*/
public static final String BUILD_TRIGGER_BUILD_BATCH = API + "/build_batch";
}

View File

@ -24,6 +24,7 @@ package io.jpom.util;
import cn.hutool.cron.CronUtil;
import cn.hutool.cron.Scheduler;
import cn.hutool.cron.task.Task;
/**
* @author bwcx_jzy
@ -32,7 +33,7 @@ import cn.hutool.cron.Scheduler;
public class CronUtils {
/**
*
* 开始
*/
public static void start() {
// 开启秒级
@ -43,4 +44,23 @@ public class CronUtils {
CronUtil.start();
}
}
/**
* 添加任务自动去重
*
* @param id 任务ID
* @param cron 表达式
* @param task 任务作业
*/
public static void upsert(String id, String cron, Task task) {
Scheduler scheduler = CronUtil.getScheduler();
Task schedulerTask = scheduler.getTask(id);
if (schedulerTask != null) {
CronUtil.remove(id);
}
// 创建任务
CronUtil.schedule(id, cron, task);
//
CronUtils.start();
}
}

View File

@ -168,6 +168,7 @@ public class BuildExtraModule extends BaseModel {
this.setClearOld(buildHistoryLog.getClearOld());
this.setResultDirFile(buildHistoryLog.getResultDirFile());
this.setName(buildHistoryLog.getBuildName());
//
this.setId(buildHistoryLog.getBuildDataId());
this.setWorkspaceId(buildHistoryLog.getWorkspaceId());
}

View File

@ -22,7 +22,6 @@
*/
package io.jpom.build;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.SystemClock;
import cn.hutool.core.io.FileUtil;
@ -82,6 +81,7 @@ public class BuildInfoManage extends BaseBuild implements Runnable {
* 缓存构建中
*/
private static final Map<String, BuildInfoManage> BUILD_MANAGE_MAP = new ConcurrentHashMap<>();
private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
private final BuildInfoModel buildInfoModel;
@ -94,15 +94,25 @@ public class BuildInfoManage extends BaseBuild implements Runnable {
/**
* 延迟执行的时间单位秒
*/
private Integer delay;
private final Integer delay;
/**
* 触发类型
*/
private final int triggerBuildType;
private BuildInfoManage(final BuildInfoModel buildInfoModel, final RepositoryModel repositoryModel, final UserModel userModel) {
private BuildInfoManage(final BuildInfoModel buildInfoModel,
final RepositoryModel repositoryModel,
final UserModel userModel,
Integer delay,
int triggerBuildType) {
super(BuildUtil.getLogFile(buildInfoModel.getId(), buildInfoModel.getBuildId()),
buildInfoModel.getId());
this.buildInfoModel = buildInfoModel;
this.repositoryModel = repositoryModel;
this.gitFile = BuildUtil.getSourceById(buildInfoModel.getId());
this.userModel = userModel;
this.triggerBuildType = triggerBuildType;
this.delay = delay;
// 解析 其他配置信息
BuildExtraModule buildExtraModule = StringUtil.jsonConvert(this.buildInfoModel.getExtraData(), BuildExtraModule.class);
Assert.notNull(buildExtraModule, "构建信息缺失");
@ -136,22 +146,23 @@ public class BuildInfoManage extends BaseBuild implements Runnable {
/**
* 创建构建
*
* @param buildInfoModel 构建项
* @param userModel 操作人
* @param repositoryModel 仓库信息
* @param delay 延迟执行的时间 单位秒
* @param buildInfoModel 构建项
* @param userModel 操作人
* @param repositoryModel 仓库信息
* @param delay 延迟执行的时间 单位秒
* @param triggerBuildType 触发构建类型
* @return this
*/
public static BuildInfoManage create(final BuildInfoModel buildInfoModel,
final RepositoryModel repositoryModel,
final UserModel userModel,
Integer delay) {
Integer delay,
int triggerBuildType) {
if (BUILD_MANAGE_MAP.containsKey(buildInfoModel.getId())) {
throw new JpomRuntimeException("当前构建还在进行中");
}
BuildInfoManage manage = new BuildInfoManage(buildInfoModel, repositoryModel, userModel);
BuildInfoManage manage = new BuildInfoManage(buildInfoModel, repositoryModel, userModel, delay, triggerBuildType);
BUILD_MANAGE_MAP.put(buildInfoModel.getId(), manage);
manage.delay = delay;
//
ThreadUtil.execute(manage);
return manage;
@ -188,20 +199,21 @@ public class BuildInfoManage extends BaseBuild implements Runnable {
BuildHistoryLog buildHistoryLog = new BuildHistoryLog();
// 更新其他配置字段
buildHistoryLog.setResultDirFile(buildExtraModule.getResultDirFile());
buildHistoryLog.setTriggerBuildType(triggerBuildType);
buildHistoryLog.setReleaseMethod(buildExtraModule.getReleaseMethod());
buildHistoryLog.setReleaseMethodDataId(buildExtraModule.getReleaseMethodDataId());
buildHistoryLog.setAfterOpt(buildExtraModule.getAfterOpt());
buildHistoryLog.setWorkspaceId(this.buildInfoModel.getWorkspaceId());
buildHistoryLog.setReleaseCommand(buildExtraModule.getReleaseCommand());
BeanUtil.copyProperties(this.buildInfoModel, buildHistoryLog);
buildHistoryLog.setId(this.logId);
buildHistoryLog.setBuildDataId(buildInfoModel.getId());
buildHistoryLog.setStatus(BuildStatus.Ing.getCode());
buildHistoryLog.setStartTime(System.currentTimeMillis());
buildHistoryLog.setReleasePath(buildExtraModule.getReleasePath());
buildHistoryLog.setReleaseCommand(buildExtraModule.getReleaseCommand());
buildHistoryLog.setBuildNumberId(buildInfoModel.getBuildId());
buildHistoryLog.setBuildName(buildInfoModel.getName());
buildHistoryLog.setClearOld(buildExtraModule.isClearOld());
//
buildHistoryLog.setWorkspaceId(this.buildInfoModel.getWorkspaceId());
buildHistoryLog.setId(this.logId);
buildHistoryLog.setStatus(BuildStatus.Ing.getCode());
buildHistoryLog.setStartTime(SystemClock.now());
DbBuildHistoryLogService dbBuildHistoryLogService = SpringUtil.getBean(DbBuildHistoryLogService.class);
dbBuildHistoryLogService.insert(buildHistoryLog);
}
@ -393,7 +405,12 @@ public class BuildInfoManage extends BaseBuild implements Runnable {
suppliers.put("release", BuildInfoManage.this::packageRelease);
// 依次执行流程发生异常结束整个流程
String processName = StrUtil.EMPTY;
BaseServerController.resetInfo(this.userModel);
if (this.triggerBuildType == 2) {
// 系统触发构建
BaseServerController.resetInfo(UserModel.EMPTY);
} else {
BaseServerController.resetInfo(this.userModel);
}
try {
for (Map.Entry<String, Supplier<Boolean>> stringSupplierEntry : suppliers.entrySet()) {
processName = stringSupplierEntry.getKey();
@ -473,6 +490,7 @@ public class BuildInfoManage extends BaseBuild implements Runnable {
httpRequest.form("buildId", this.buildInfoModel.getId());
httpRequest.form("buildName", this.buildInfoModel.getName());
httpRequest.form("type", type, other);
httpRequest.form("triggerBuildType", this.triggerBuildType);
httpRequest.form("triggerTime", triggerTime);
String body = httpRequest.execute().body();
DefaultSystemLog.getLog().info(this.buildInfoModel.getName() + ":" + body);

View File

@ -28,6 +28,7 @@ import cn.hutool.core.lang.RegexPool;
import cn.hutool.core.lang.Tuple;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.cron.pattern.CronPattern;
import cn.jiangzeyin.common.JsonMessage;
import cn.jiangzeyin.common.validator.ValidatorConfig;
import cn.jiangzeyin.common.validator.ValidatorItem;
@ -117,15 +118,17 @@ public class BuildInfoController extends BaseServerController {
/**
* edit build info
*
* @param id
* @param name
* @param repositoryId
* @param resultDirFile
* @param script
* @param releaseMethod
* @param branchName
* @param webhook
* @param extraData
* @param id 构建ID
* @param name 构建名称
* @param repositoryId 仓库ID
* @param resultDirFile 构建产物目录
* @param script 构建命令
* @param releaseMethod 发布方法
* @param branchName 分支名称
* @param webhook webhook
* @param extraData 构建的其他信息
* @param autoBuildCron 自动构建表达是
* @param branchTagName 标签名
* @return json
*/
@RequestMapping(value = "/build/edit", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ -136,7 +139,7 @@ public class BuildInfoController extends BaseServerController {
@ValidatorConfig(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "构建产物目录不能为空,长度1-200", range = "1:200")) String resultDirFile,
@ValidatorConfig(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "构建命令不能为空")) String script,
@ValidatorItem(value = ValidatorRule.POSITIVE_INTEGER, msg = "发布方法不正确") int releaseMethod,
String branchName, String branchTagName, String webhook,
String branchName, String branchTagName, String webhook, String autoBuildCron,
String extraData) {
// 根据 repositoryId 查询仓库信息
RepositoryModel repositoryModel = repositoryService.getByKey(repositoryId, getRequest());
@ -161,6 +164,14 @@ public class BuildInfoController extends BaseServerController {
if (StrUtil.isNotEmpty(webhook)) {
Validator.validateMatchRegex(RegexPool.URL_HTTP, webhook, "WebHooks 地址不合法");
}
if (StrUtil.isNotEmpty(autoBuildCron)) {
try {
new CronPattern(autoBuildCron);
} catch (Exception e) {
throw new IllegalArgumentException("定时构建表达式格式不正确");
}
}
buildInfoModel.setAutoBuildCron(autoBuildCron);
buildInfoModel.setWebhook(webhook);
buildInfoModel.setRepositoryId(repositoryId);
buildInfoModel.setName(name);
@ -324,9 +335,7 @@ public class BuildInfoController extends BaseServerController {
Objects.requireNonNull(buildInfoModel, "没有对应数据");
//
String e = buildInfoService.checkStatus(buildInfoModel.getStatus());
if (e != null) {
return e;
}
Assert.isNull(e, () -> e);
dbBuildHistoryLogService.delByBuildId(buildInfoModel.getId());
// 删除构建信息文件

View File

@ -27,7 +27,6 @@ import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.LineHandler;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.jiangzeyin.common.JsonMessage;
import cn.jiangzeyin.common.validator.ValidatorConfig;
import cn.jiangzeyin.common.validator.ValidatorItem;
@ -89,18 +88,10 @@ public class BuildInfoManageController extends BaseServerController {
public String start(@ValidatorConfig(@ValidatorItem(value = ValidatorRule.NOT_BLANK, msg = "没有数据")) String id) {
BuildInfoModel item = buildInfoService.getByKey(id, getRequest());
Assert.notNull(item, "没有对应数据");
String e = buildInfoService.checkStatus(item.getStatus());
Assert.isNull(e, () -> e);
// set buildId field
int buildId = ObjectUtil.defaultIfNull(item.getBuildId(), 0);
item.setBuildId(buildId + 1);
// userModel
UserModel userModel = getUser();
//String optUserName = userModel == null ? "openApi" : UserModel.getOptUserName(userModel);
//item.setModifyUser(optUserName);
buildInfoService.update(item);
// 执行构建
return buildInfoService.start(item, userModel, null);
return buildInfoService.start(item.getId(), userModel, null, 0).toString();
}
/**
@ -141,9 +132,7 @@ public class BuildInfoManageController extends BaseServerController {
BuildInfoModel item = buildInfoService.getByKey(buildHistoryLog.getBuildDataId());
Objects.requireNonNull(item, "没有对应数据");
String e = buildInfoService.checkStatus(item.getStatus());
if (e != null) {
return e;
}
Assert.isNull(e, () -> e);
UserModel userModel = getUser();
ReleaseManage releaseManage = new ReleaseManage(buildHistoryLog, userModel);
// 标记发布中

View File

@ -26,6 +26,12 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity;
import cn.hutool.extra.servlet.ServletUtil;
import cn.jiangzeyin.common.DefaultSystemLog;
import cn.jiangzeyin.common.JsonMessage;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.jpom.common.BaseJpomController;
import io.jpom.common.ServerOpenApi;
import io.jpom.common.interceptor.NotLogin;
import io.jpom.controller.build.BuildInfoTriggerController;
@ -37,10 +43,12 @@ import org.h2.util.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author bwcx_jzy
@ -48,7 +56,7 @@ import java.util.List;
*/
@RestController
@NotLogin
public class BuildTriggerApiController {
public class BuildTriggerApiController extends BaseJpomController {
private final BuildInfoService buildInfoService;
@ -107,6 +115,66 @@ public class BuildTriggerApiController {
Assert.state(StrUtil.equals(token, item.getTriggerToken()), "触发token错误,或者已经失效");
return buildInfoService.start(item, userModel, Convert.toInt(delay, 0));
JsonMessage<Integer> start = buildInfoService.start(id, userModel, Convert.toInt(delay, 0), 1);
return start.toString();
}
/**
* 构建触发器
* <p>
* 参数 <code>[
* {
* "id":"1",
* "token":"a",
* "delay":"0"
* }
* ]</code>
* <p>
* 响应 <code>[
* {
* "id":"1",
* "token":"a",
* "delay":"0",
* "msg":"开始构建",
* "data":1
* }
* ]</code>
*
* @return json
*/
@PostMapping(value = ServerOpenApi.BUILD_TRIGGER_BUILD_BATCH, produces = MediaType.APPLICATION_JSON_VALUE)
public String triggerBatch() {
try {
String body = ServletUtil.getBody(getRequest());
JSONArray jsonArray = JSONArray.parseArray(body);
List<Object> collect = jsonArray.stream().peek(o -> {
JSONObject jsonObject = (JSONObject) o;
String id = jsonObject.getString("id");
String token = jsonObject.getString("token");
Integer delay = jsonObject.getInteger("delay");
BuildInfoModel item = buildInfoService.getByKey(id);
if (item == null) {
jsonObject.put("msg", "没有对应数据");
return;
}
UserModel userModel = BuildTriggerApiController.this.getByUrlToken(token);
if (userModel == null) {
jsonObject.put("msg", "没有对应数据");
return;
}
//
if (!StrUtil.equals(token, item.getTriggerToken())) {
jsonObject.put("msg", "触发token错误,或者已经失效");
return;
}
JsonMessage<Integer> start = buildInfoService.start(id, userModel, delay, 1);
jsonObject.put("msg", start.getMsg());
jsonObject.put("buildId", start.getData());
}).collect(Collectors.toList());
return JsonMessage.getString(200, "触发成功", collect);
} catch (Exception e) {
DefaultSystemLog.getLog().error("构建触发批量触发异常", e);
return JsonMessage.getString(500, "触发异常", e.getMessage());
}
}
}

View File

@ -29,7 +29,7 @@ import io.jpom.service.h2db.TableName;
* @author Hotstrip
* new BuildModel class, for replace old BuildModel
*/
@TableName(value = "BUILD_INFO",name = "构建信息")
@TableName(value = "BUILD_INFO", name = "构建信息")
public class BuildInfoModel extends BaseWorkspaceModel {
/**
@ -85,9 +85,22 @@ public class BuildInfoModel extends BaseWorkspaceModel {
* 额外信息JSON 字符串格式
*/
private String extraData;
/**
* 构建 webhook
*/
private String webhook;
/**
* 定时构建表达式
*/
private String autoBuildCron;
public String getAutoBuildCron() {
return autoBuildCron;
}
public void setAutoBuildCron(String autoBuildCron) {
this.autoBuildCron = autoBuildCron;
}
public String getRepositoryId() {
return repositoryId;

View File

@ -96,6 +96,10 @@ public class BuildHistoryLog extends BaseWorkspaceModel {
* @see BuildInfoModel#getBuildId()
*/
private Integer buildNumberId;
/**
* 触发构建类型 触发类型{0手动1 触发器,2 自动触发}
*/
private Integer triggerBuildType;
/**
* 状态
*
@ -121,6 +125,15 @@ public class BuildHistoryLog extends BaseWorkspaceModel {
@PropIgnore
private Boolean hasLog;
public Integer getTriggerBuildType() {
return triggerBuildType;
}
public void setTriggerBuildType(Integer triggerBuildType) {
this.triggerBuildType = triggerBuildType;
}
public Boolean getHashFile() {
File file = BuildUtil.getHistoryPackageFile(getBuildDataId(), getBuildNumberId(), getResultDirFile());
hashFile = FileUtil.exist(file);

View File

@ -32,6 +32,7 @@ import cn.hutool.http.HttpStatus;
import cn.jiangzeyin.common.DefaultSystemLog;
import cn.jiangzeyin.common.JsonMessage;
import cn.jiangzeyin.common.spring.SpringUtil;
import io.jpom.JpomApplication;
import io.jpom.model.AfterOpt;
import io.jpom.model.data.NodeModel;
import io.jpom.model.data.OutGivingModel;
@ -123,7 +124,8 @@ public class OutGivingItemRun implements Callable<OutGivingNodeProject.Status> {
OutGivingNodeProject outGivingNodeProjectItem,
OutGivingNodeProject.Status status,
String msg) {
updateStatus(this.logId, outGivingId, outGivingNodeProjectItem, status, msg, this.userModel.getId());
String userId = this.userModel == null ? JpomApplication.SYSTEM_ID : this.userModel.getId();
updateStatus(this.logId, outGivingId, outGivingNodeProjectItem, status, msg, userId);
}
/**

View File

@ -28,6 +28,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.jiangzeyin.common.JsonMessage;
import cn.jiangzeyin.common.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import io.jpom.JpomApplication;
import io.jpom.common.forward.NodeForward;
import io.jpom.common.forward.NodeUrl;
import io.jpom.model.AfterOpt;
@ -78,7 +79,8 @@ public class OutGivingRun {
boolean cancel = false;
for (OutGivingNodeProject outGivingNodeProject : outGivingNodeProjects) {
if (cancel) {
OutGivingItemRun.updateStatus(null, id, outGivingNodeProject, OutGivingNodeProject.Status.Cancel, "前一个节点分发失败,取消分发", userModel.getId());
String userId = userModel == null ? JpomApplication.SYSTEM_ID : userModel.getId();
OutGivingItemRun.updateStatus(null, id, outGivingNodeProject, OutGivingNodeProject.Status.Cancel, "前一个节点分发失败,取消分发", userId);
} else {
OutGivingItemRun outGivingRun = new OutGivingItemRun(item, outGivingNodeProject, file, userModel, unzip);
OutGivingNodeProject.Status status = outGivingRun.call();

View File

@ -22,8 +22,11 @@
*/
package io.jpom.service.dblog;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.cron.task.Task;
import cn.hutool.db.Entity;
import cn.jiangzeyin.common.DefaultSystemLog;
import cn.jiangzeyin.common.JsonMessage;
import io.jpom.build.BuildInfoManage;
import io.jpom.model.BaseEnum;
@ -33,9 +36,11 @@ import io.jpom.model.data.UserModel;
import io.jpom.model.enums.BuildReleaseMethod;
import io.jpom.model.enums.BuildStatus;
import io.jpom.service.h2db.BaseWorkspaceService;
import io.jpom.util.CronUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.List;
import java.util.Objects;
/**
@ -53,37 +58,99 @@ public class BuildInfoService extends BaseWorkspaceService<BuildInfoModel> {
this.repositoryService = repositoryService;
}
// /**
// * load date group by group name
// *
// * @return list
// */
// public List<String> listGroup() {
// String sql = "select `GROUP` from " + getTableName() + " where 1=1 group by `GROUP`";
// List<Entity> list = super.query(sql);
// // 筛选字段
// return list.stream()
// .filter(entity -> StringUtils.hasLength(String.valueOf(entity.get(Const.GROUP_STR))))
// .flatMap(entity -> Stream.of(String.valueOf(entity.get(Const.GROUP_STR))))
// .distinct()
// .collect(Collectors.toList());
// }
@Override
public void insert(BuildInfoModel buildInfoModel) {
super.insert(buildInfoModel);
this.checkCron(buildInfoModel);
}
@Override
public int update(BuildInfoModel buildInfoModel) {
int update = super.update(buildInfoModel);
if (update > 0) {
this.checkCron(buildInfoModel);
}
return update;
}
/**
* 开启定时构建任务
*/
public void startCron() {
String sql = "select * from " + super.getTableName() + " where autoBuildCron is not null and autoBuildCron <> ''";
List<BuildInfoModel> buildInfoModels = super.queryList(sql);
if (buildInfoModels == null) {
return;
}
for (BuildInfoModel buildInfoModel : buildInfoModels) {
this.checkCron(buildInfoModel);
}
// 恢复异常数据
String updateSql = "update " + super.getTableName() + " set status=? where status=? or status=?";
int execute = super.execute(updateSql, BuildStatus.No.getCode(), BuildStatus.Ing.getCode(), BuildStatus.PubIng.getCode());
if (execute > 0) {
DefaultSystemLog.getLog().info("build Recover bad data {}", execute);
}
}
private void checkCron(BuildInfoModel buildInfoModel) {
String autoBuildCron = buildInfoModel.getAutoBuildCron();
if (StrUtil.isEmpty(autoBuildCron)) {
return;
}
String id = buildInfoModel.getId();
DefaultSystemLog.getLog().debug("start build cron {} {} {}", id, buildInfoModel.getName(), autoBuildCron);
CronUtils.upsert("build:" + id, autoBuildCron, new CronTask(id));
}
private class CronTask implements Task {
private final String buildId;
public CronTask(String buildId) {
this.buildId = buildId;
}
@Override
public void execute() {
try {
BuildInfoService.this.start(this.buildId, null, null, 2);
} catch (Exception e) {
DefaultSystemLog.getLog().error("触发自动构建异常", e);
}
}
}
/**
* start build
*
* @param buildInfoModel 构建信息
* @param userModel 用户信息
* @param delay 延迟的时间
* @param buildInfoId 构建Id
* @param userModel 用户信息
* @param delay 延迟的时间
* @param triggerBuildType 触发构建类型
* @return json
*/
public String start(final BuildInfoModel buildInfoModel, final UserModel userModel, Integer delay) {
// load repository
RepositoryModel repositoryModel = repositoryService.getByKey(buildInfoModel.getRepositoryId(), false);
Assert.notNull(repositoryModel, "仓库信息不存在");
BuildInfoManage.create(buildInfoModel, repositoryModel, userModel, delay);
String msg = (delay == null || delay <= 0) ? "开始构建中" : "延迟" + delay + "秒后开始构建";
return JsonMessage.getString(200, msg, buildInfoModel.getBuildId());
public JsonMessage<Integer> start(String buildInfoId, UserModel userModel, Integer delay, int triggerBuildType) {
synchronized (buildInfoId.intern()) {
BuildInfoModel buildInfoModel = super.getByKey(buildInfoId);
String e = this.checkStatus(buildInfoModel.getStatus());
Assert.isNull(e, () -> e);
// set buildId field
int buildId = ObjectUtil.defaultIfNull(buildInfoModel.getBuildId(), 0);
{
BuildInfoModel buildInfoModel1 = new BuildInfoModel();
buildInfoModel1.setBuildId(buildId + 1);
buildInfoModel1.setId(buildInfoId);
buildInfoModel.setBuildId(buildInfoModel1.getBuildId());
super.update(buildInfoModel1);
}
// load repository
RepositoryModel repositoryModel = repositoryService.getByKey(buildInfoModel.getRepositoryId(), false);
Assert.notNull(repositoryModel, "仓库信息不存在");
BuildInfoManage.create(buildInfoModel, repositoryModel, userModel, delay, triggerBuildType);
String msg = (delay == null || delay <= 0) ? "开始构建中" : "延迟" + delay + "秒后开始构建";
return new JsonMessage<>(200, msg, buildInfoModel.getBuildId());
}
}
/**

View File

@ -71,7 +71,7 @@ public class DbBuildHistoryLogService extends BaseWorkspaceService<BuildHistoryL
public void delByBuildId(String buildDataId) {
Entity where = new Entity(getTableName());
where.set("buildDataId", buildDataId);
del(where);
super.del(where);
}
/**

View File

@ -117,10 +117,12 @@ public abstract class BaseDbService<T extends BaseDbModel> extends BaseDbCommonS
if (t instanceof BaseUserModifyDbModel) {
// 获取数据修改人
BaseUserModifyDbModel modifyDbModel = (BaseUserModifyDbModel) t;
UserModel userModel = BaseServerController.getUserModel();
userModel = userModel == null ? BaseServerController.getUserByThreadLocal() : userModel;
if (userModel != null) {
modifyDbModel.setModifyUser(ObjectUtil.defaultIfNull(modifyDbModel.getModifyUser(), userModel.getId()));
if (StrUtil.isEmpty(modifyDbModel.getModifyUser())) {
UserModel userModel = BaseServerController.getUserModel();
userModel = userModel == null ? BaseServerController.getUserByThreadLocal() : userModel;
if (userModel != null) {
modifyDbModel.setModifyUser(ObjectUtil.defaultIfNull(modifyDbModel.getModifyUser(), userModel.getId()));
}
}
}
}

View File

@ -24,7 +24,6 @@ package io.jpom.system.init;
import cn.hutool.core.lang.Console;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.cron.CronUtil;
import cn.jiangzeyin.common.DefaultSystemLog;
import cn.jiangzeyin.common.PreLoadClass;
import cn.jiangzeyin.common.PreLoadMethod;
@ -32,6 +31,7 @@ import cn.jiangzeyin.common.spring.SpringUtil;
import io.jpom.build.BuildUtil;
import io.jpom.common.RemoteVersion;
import io.jpom.service.dblog.BackupInfoService;
import io.jpom.service.dblog.BuildInfoService;
import io.jpom.service.monitor.MonitorService;
import io.jpom.service.node.NodeService;
import io.jpom.system.ConfigBean;
@ -58,16 +58,19 @@ public class CheckMonitor {
Console.log("已经开启监听调度:节点信息采集");
}
// 缓存检测调度
CronUtil.schedule("cache_manger_schedule", "0 0/10 * * * ?", () -> {
CronUtils.upsert("cache_manger_schedule", "0 0/10 * * * ?", () -> {
BuildUtil.reloadCacheSize();
ConfigBean.getInstance().dataSize();
});
ThreadUtil.execute(() -> {
BuildUtil.reloadCacheSize();
ConfigBean.getInstance().dataSize();
// 加载构建定时器
BuildInfoService buildInfoService = SpringUtil.getBean(BuildInfoService.class);
buildInfoService.startCron();
});
// 开启版本检测调度
CronUtil.schedule("system_monitor", "0 0 0,12 * * ?", () -> {
CronUtils.upsert("system_monitor", "0 0 0,12 * * ?", () -> {
try {
BackupInfoService backupInfoService = SpringUtil.getBean(BackupInfoService.class);
backupInfoService.checkAutoBackup();
@ -77,7 +80,5 @@ public class CheckMonitor {
DefaultSystemLog.getLog().error("系统调度执行出现错误", e);
}
});
// 开启调度
CronUtils.start();
}
}

View File

@ -1,10 +1,20 @@
-- @author bwcx_jzy
ALTER TABLE USEROPERATELOGV1 ALTER COLUMN NODEID VARCHAR(50) COMMENT '节点ID';
ALTER TABLE USEROPERATELOGV1
ALTER COLUMN NODEID VARCHAR(50) COMMENT '节点ID';
ALTER TABLE MONITORNOTIFYLOG ALTER COLUMN NODEID VARCHAR(50) COMMENT '节点ID';
ALTER TABLE MONITORNOTIFYLOG
ALTER COLUMN NODEID VARCHAR(50) COMMENT '节点ID';
ALTER TABLE OUTGIVINGLOG ADD IF NOT EXISTS MODIFYUSER VARCHAR (50) comment '操作人';
ALTER TABLE OUTGIVINGLOG
ADD IF NOT EXISTS MODIFYUSER VARCHAR(50) comment '操作人';
ALTER TABLE SSHTERMINALEXECUTELOG ADD IF NOT EXISTS MODIFYUSER VARCHAR (50) comment '操作人';
ALTER TABLE SSHTERMINALEXECUTELOG
ADD IF NOT EXISTS MODIFYUSER VARCHAR(50) comment '操作人';
ALTER TABLE BUILDHISTORYLOG
ADD IF NOT EXISTS triggerBuildType int DEFAULT 0 comment '触发类型{0手动1 触发器,2 自动触发}';
ALTER TABLE BUILDHISTORYLOG
ADD IF NOT EXISTS triggerBuildType int DEFAULT 0 comment '触发类型{0手动1 触发器,2 自动触发}';

View File

@ -23,3 +23,6 @@ ALTER TABLE REPOSITORY
ADD IF NOT EXISTS RESULTDIRFILE VARCHAR(200) comment '构建产物目录';
ALTER TABLE REPOSITORY
ADD IF NOT EXISTS GITURL varchar(255) comment '仓库地址';
ALTER TABLE BUILD_INFO
ADD IF NOT EXISTS autoBuildCron VARCHAR(100) comment '自动构建表达式';

View File

@ -0,0 +1,32 @@
package io.jpom;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.jpom.common.ServerOpenApi;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
/**
* @author bwcx_jzy
* @since 2021/12/14
*/
public class BuildTriggerTest {
@Test
public void test() {
// 8cf594526db74f0eb79cac6da141c655/219a4009a0a68173d8d643d237f2ca8ad797d41dc5bcfceb83da4f4f1d1dbe933a1
JSONObject jsonObject = new JSONObject();
jsonObject.put("id", "8cf594526db74f0eb79cac6da141c655");
jsonObject.put("token", "219a4009a0a68173d8d643d237f2ca8ad797d41dc5bcfceb83da4f4f1d1dbe933a1");
//
JSONArray jsonArray = new JSONArray();
jsonArray.add(jsonObject);
//
HttpRequest post = HttpUtil.createPost("http://127.0.0.1:2122/" + ServerOpenApi.BUILD_TRIGGER_BUILD_BATCH);
post.body(jsonArray.toString(), MediaType.APPLICATION_JSON_VALUE);
String body = post.execute().body();
System.out.println(body);
}
}

View File

@ -72,6 +72,7 @@ export function editBuild(params) {
// 其他参数
extraData: params.extraData,
webhook: params.webhook,
autoBuildCron: params.autoBuildCron,
};
return axios({
url: "/build/edit",
@ -246,6 +247,12 @@ export const releaseMethodMap = {
4: "本地命令",
};
export const triggerBuildTypeMap = {
0: "手动",
1: "触发器",
2: "定时",
};
export const releaseMethodArray = Object.keys(releaseMethodMap).map((item) => {
return {
value: Number(item),

View File

@ -7,6 +7,9 @@
<a-select show-search option-filter-prop="children" v-model="listQuery.status" allowClear placeholder="请选择状态" class="filter-item">
<a-select-option v-for="(val, key) in statusMap" :key="key">{{ val }}</a-select-option>
</a-select>
<a-select show-search option-filter-prop="children" v-model="listQuery.triggerBuildType" allowClear placeholder="请选择触发类型" class="filter-item">
<a-select-option v-for="(val, key) in triggerBuildTypeMap" :key="key">{{ val }}</a-select-option>
</a-select>
<a-range-picker class="filter-item" :show-time="{ format: 'HH:mm:ss' }" format="YYYY-MM-DD HH:mm:ss" @change="onchangeTime" />
<a-tooltip title="按住 Ctr 或者 Alt 键点击按钮快速回到第一页">
<a-button type="primary" @click="loadData">搜索</a-button>
@ -27,9 +30,15 @@
<template slot="releaseMethod" slot-scope="text" placement="topleft" :title="text">
<span>{{ releaseMethodMap[text] }}</span>
</template>
<!-- <a-tooltip slot="buildUser" slot-scope="text" placement="topLeft" :title="text">
<span>{{ text }}</span>
</a-tooltip> -->
<template slot="triggerBuildType" slot-scope="text" placement="topleft" :title="text">
<span>{{ triggerBuildTypeMap[text] }}</span>
</template>
<template slot="startTime" slot-scope="text, record" placement="topLeft">
<a-tooltip :title="`开始时间:${parseTime(record.startTime)}${record.endTime ? '结束时间:' + parseTime(record.endTime) : ''}`">
<span>{{ parseTime(record.startTime) }}</span>
</a-tooltip>
</template>
<template slot="operation" slot-scope="text, record">
<a-button type="primary" :disabled="!record.hasLog" @click="handleDownload(record)"><a-icon type="download" />日志</a-button>
<a-button type="primary" :disabled="!record.hashFile" @click="handleFile(record)"><a-icon type="download" />产物</a-button>
@ -57,7 +66,7 @@
</template>
<script>
import BuildLog from "./log";
import { geteBuildHistory, getBuildListAll, downloadBuildLog, rollback, deleteBuildHistory, releaseMethodMap, statusMap, downloadBuildFile } from "@/api/build-info";
import { geteBuildHistory, getBuildListAll, downloadBuildLog, rollback, deleteBuildHistory, releaseMethodMap, statusMap, downloadBuildFile, triggerBuildTypeMap } from "@/api/build-info";
import { parseTime } from "@/utils/time";
import { PAGE_DEFAULT_LIMIT, PAGE_DEFAULT_SIZW_OPTIONS, PAGE_DEFAULT_SHOW_TOTAL, PAGE_DEFAULT_LIST_QUERY } from "@/utils/const";
@ -68,6 +77,7 @@ export default {
data() {
return {
releaseMethodMap: releaseMethodMap,
triggerBuildTypeMap: triggerBuildTypeMap,
loading: false,
list: [],
buildList: [],
@ -80,26 +90,25 @@ export default {
{ title: "构建名称", dataIndex: "buildName", /*width: 120,*/ ellipsis: true, scopedSlots: { customRender: "buildName" } },
{ title: "构建 ID", dataIndex: "buildNumberId", width: 100, ellipsis: true, scopedSlots: { customRender: "buildNumberId" } },
{ title: "状态", dataIndex: "status", width: 120, ellipsis: true, scopedSlots: { customRender: "status" } },
{ title: "触发类型", dataIndex: "triggerBuildType", width: 100, ellipsis: true, scopedSlots: { customRender: "triggerBuildType" } },
{
title: "开始时间",
dataIndex: "startTime",
sorter: true,
customRender: (text) => {
return parseTime(text);
},
width: 180,
},
{
title: "结束时间",
dataIndex: "endTime",
sorter: true,
customRender: (text) => {
return parseTime(text);
},
width: 180,
scopedSlots: { customRender: "startTime" },
width: 170,
},
// {
// title: "",
// dataIndex: "endTime",
// sorter: true,
// customRender: (text) => {
// return parseTime(text);
// },
// width: 170,
// },
{ title: "发布方式", dataIndex: "releaseMethod", width: 100, ellipsis: true, scopedSlots: { customRender: "releaseMethod" } },
{ title: "构建人", dataIndex: "modifyUser", /*width: 150,*/ ellipsis: true, scopedSlots: { customRender: "modifyUser" } },
{ title: "构建人", dataIndex: "modifyUser", width: 150, ellipsis: true, scopedSlots: { customRender: "modifyUser" } },
{ title: "操作", dataIndex: "operation", scopedSlots: { customRender: "operation" }, width: 280, fixed: "right" },
],
};
@ -123,6 +132,7 @@ export default {
this.loadData();
},
methods: {
parseTime: parseTime,
//
loadBuildList() {
getBuildListAll().then((res) => {

View File

@ -223,6 +223,9 @@
</template>
<a-input v-model="temp.webhook" placeholder="构建过程请求,非必填GET请求" />
</a-form-model-item>
<a-form-model-item label="自动构建" prop="autoBuildCron">
<a-input v-model="temp.autoBuildCron" placeholder="如果需要定时自动构建则填写,cron 表达式" />
</a-form-model-item>
</a-form-model>
</a-modal>
<!-- 触发器 -->

View File

@ -574,7 +574,7 @@ export default {
this.loadNodeList(() => {
this.loadProjectListAll(() => {
//
this.temp = {};
JSON.parse(record.outGivingNodeProjectList).forEach((ele, eleIndex) => {
let index = "";
let projects = [];
@ -595,18 +595,19 @@ export default {
});
// console.log(ele, eleIndex);
});
this.temp = {
...{
type: "edit",
projectId: record.projectId,
name: record.name,
afterOpt: record.afterOpt,
id: record.id,
intervalTime: record.intervalTime,
clearOld: record.clearOld,
},
};
this.temp = { ...this.temp };
this.temp = {
...this.temp,
type: "edit",
projectId: record.projectId,
name: record.name,
afterOpt: record.afterOpt,
id: record.id,
intervalTime: record.intervalTime,
clearOld: record.clearOld,
};
// console.log(this.temp);
this.linkDispatchVisible = true;
});
});
@ -1009,7 +1010,7 @@ export default {
if (this.dispatchList[value].index !== "") {
this.nodeNameList[this.dispatchList[value].index].openStatus = true;
}
delete this.temp[`node_${this.dispatchList[value].nodeId}`];
delete this.temp[`node_${this.dispatchList[value].nodeId}_${this.dispatchList[value].index}`];
this.dispatchList[value].status = false;
this.dispatchList.splice(value, 1);
},