我正在尝试编写一个Jenkins插件,如果在假期(或仅在给定的输入日/ s)触发该构建,则该插件可以自动中止构建。用户可以配置日期,每个作业都会有一个复选框,允许用户决定他们是否希望他们的工作在假期中止。目前我的插件扩展 JobProperty 并利用全局配置,其中列出了黑名单日期。如果今天列入我列入黑名单的日子,那么我不想让我的工作继续下去。该插件“有效”,但有一些恼人的警告。
我的主要问题是,如果碰巧是在我列入黑名单的日子之一的某一天触发,我只能对构建失败。这对我来说是一个问题,因为没有实际的错误。工作正在按预期运行,我不想收到充满错误的电子邮件,因为工作在我不想让它运行的那天停止(例如:假期)
当我的插件决定中止构建时,我希望能够以“已中止”状态结束作业。 (事实上 - 我希望能够控制状态并将其作为潜在参数。)
下面是我的prebuild()代码。
@Override
public boolean prebuild(AbstractBuild build, BuildListener listener) {
boolean stopped = false;
if(checkIfClosed) {
LocalDate today = LocalDate.now();
listener.getLogger().println("Checking the date for " + DateFormats.yyyyMMdd.print(today));
if (getDescriptor().getUseCalculatedDateChecker()) {
if (!NyseHolidayChecker.isMarketOpen(today)) {
listener.getLogger().println("Closed (From auto calculation)!");
stopped = true;
}
}
if (getDescriptor().getListOfClosedDates() != null && !getDescriptor().getListOfClosedDates().isEmpty()) {
if (getDescriptor().getListOfClosedDates().contains(DateFormats.yyyyMMdd.print(today))) {
listener.getLogger().println("Closed. Date is in the Closed Date List. " +
"If this is wrong check global configuration.");
stopped = true;
}
}
}
if(stopped) {
try {
if(build.doStop() == null) {
return false;
}
} catch (IOException e) {
listener.getLogger().println(e.getMessage());
return false;
} catch (ServletException e) {
listener.getLogger().println(e.getMessage());
return false;
}
//throw new RuntimeException("This job has been told not to run when marked as Closed!");
//throw new AbortException("This job has been told not to run when marked as Closed!");
}
return true;
}
我尝试了几种不同的方法让工作立即中止,而不是将构建标记为失败。
doc告诉我,我应该抛出一个AbortException,但是我所覆盖的函数似乎不支持它。
我也尝试调用doStop(),但是我的第一个构建步骤(总共2个)仍然至少运行一次。这是不可取的,因为我永远不会知道我的工作将会在什么状态下中止(它可能已经在某个地方被摧毁并杀死了一个进程......或者做了一些活动等等)
我错过了什么?我觉得我正在乱砍以获得我需要的东西。我希望有人能指出我如何最好地做到这一点的正确方向。
答案 0 :(得分:2)
进一步深入研究Jenkins代码,结果显示Build.doRun()方法将在do while循环中执行构建步骤,这允许一小部分构建步骤通过。 Jenkins文档建议的AbortException也会将构建标记为失败(不合需要)。我发现取消作业并将其正确标记为中止的唯一方法是抛出InterruptedException。 JobProperties prebuild()函数不允许任何抛出(运行时除外,它将标记为失败)。
该插件现在扩展BuildWrapper。这有一个setUp和preCheckout方法,它将在构建步骤执行之前运行。这两种方法也可以抛出InterruptedExceptions。现在,如果我的检查通过并且日期被列入黑名单,则会从interruptOnHoliday(...)方法中抛出InterruptedException。 BuildWrapper还使用BuildWrapperDescriptor,它将根据重写的getDisplayName()函数中提供的名称在作业配置中放置一个复选框(Acts排序为jetty optionalBlock)。选中此框后,可以调用setUp函数,否则不会调用。这有效地使假日检查插件可选(所需)。
为了向用户提供插件的帮助,在插件的资源中包含一个help.html文件,这将允许程序员向用户解释如何以及为何使用插件。 BuildWrapperDescriptor类将以编程方式知道如何使用该文件。
希望这有助于每个人。以下是杀人的新方法:
@Override
public void preCheckout(AbstractBuild build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
interruptOnHoliday(build, listener);
}
/**
* Run a check against todays date and dates from the {@link NyseHolidayChecker}
* which is an automatic calculator for New York Stock Exchange holidays and also a check against the manually
* created user date list. If either one is not checked to be used, then they will be ignored.
*
* @param build {@link hudson.model.AbstractBuild} that we are on, will kill the executor
* @param listener {@link hudson.model.BuildListener} that we will log to
*
* @throws InterruptedException
*/
private void interruptOnHoliday(AbstractBuild build, BuildListener listener) throws InterruptedException {
boolean stopped = false;
LocalDate today = LocalDate.now();
listener.getLogger().println("Checking the date for " + DateFormats.yyyyMMdd.print(today));
//if the NYSE calculator is checked then let's use it
if (getDescriptor().getUseNyseCalculatedDateChecker()) {
if (!NyseHolidayChecker.isMarketOpen(today)) {
listener.getLogger().println("The NYSE is not Open today (From auto calculation)" +
" and this job is marked to abort. Stopping the build!");
stopped = true;
}
}
//If we have inserted manual dates into the list we want to check them
if (getDescriptor().getListOfClosedDates() != null && !getDescriptor().getListOfClosedDates().isEmpty()) {
if (getDescriptor().getListOfClosedDates().contains(DateFormats.yyyyMMdd.print(today))) {
listener.getLogger().println("This date is blacklisted, and this job is marked to abort. " +
"Stopping the job! If this date should not be on the list check Jenkins Settings.");
stopped = true;
}
}
//if we should stop the job then we call doStop() on the build and we also throw an InterruptedException
//The InterruptedException is the only way to abort a build without it failing.
if (stopped) {
try {
build.doStop();
throw new InterruptedException(DateFormats.yyyyMMdd.print(today) + " is a blacklisted date.");
} catch (IOException e) {
listener.getLogger().println(e.getMessage());
} catch (ServletException e) {
listener.getLogger().println(e.getMessage());
}
}
}
@Override
public BuildWrapper.Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
interruptOnHoliday(build, listener);
return new CloseCheckerEnvironment();
}