2015-01-06 1 views
2

Я пытаюсь написать плагин Jenkins, который может автоматически прервать сборку, если эта сборка запускается в праздничный день (или только определенный входной день/с). Пользователь может настроить дни, и каждое задание получает флажок, который позволяет пользователю решить, хотят ли они, чтобы их работа прерывалась в отпуске или нет. В настоящее время мой плагин расширяет JobProperty и использует глобальную конфигурацию, где у меня есть список вложенных в черный список дат. Если сегодня в моем списке занесенных в черный список дней, то я не хочу, чтобы моя работа выполнялась. Плагин «работает», но с несколькими раздражающими оговорками.Вызов build.doStop() в prebuild не останавливается достаточно быстро

Моя основная проблема заключается в том, что я могу только СБЕРЕЖАТЬ сборку, если она срабатывает в день, который является одним из моих дней с черным списком. Это проблема для меня, потому что нет реальной ошибки. Работа работает так, как должно быть, и я не хочу получать электронные письма с ошибками только потому, что задание было остановлено в тот день, когда я не хотел его запускать (например: праздник)

Когда мой плагин решает прервать сборку, я хочу, чтобы я мог закончить работу с статусом «Прерванный». (Фактически - я хотел бы иметь возможность контролировать состояние и оставлять его в качестве потенциального параметра.)

Ниже представлен мой код 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; 
} 

Я пробовал несколько разных способов, чтобы заставить работу немедленно прекратить работу и не иметь сборки, помеченной как неудачная.

  1. doc говорит мне, что я должен бросить AbortException, но это, кажется, не поддерживается функцией я переопределяя.

  2. Я также попытался вызвать doStop(), но мой первый шаг сборки (из 2) по-прежнему работает хотя бы немного. Это нежелательно, потому что я никогда не буду знать, в каком состоянии моя работа будет, когда она будет прервана (она могла бы уже sshed где-то и убил процесс ... или сделал что-то живое и т.д.)

Что я пропал без вести? Я чувствую, что я взламываю, чтобы получить то, что мне нужно. Я надеюсь, что кто-то может указать мне в правильном направлении, как лучше всего это сделать.

ответ

2

Копаем дальше в код Дженкинса показано, что метод Build.doRun() будет выполнять шаги сборки в цикле do while, который позволял пройти небольшую бит этапа сборки. Исключение AbortException, которое рекомендует документация Jenkins, также будет означать сборку как отказ (нежелательно). Единственное средство, которое я обнаружил, чтобы отменить работу и правильно ее отметить, как только что прервано, - это бросить InterruptedException. Функция prebuild() JobProperties не допускает никаких бросков (кроме Runtime, которые будут отмечены как сбой).

Плагин теперь распространяется BuildWrapper. У этого есть метод setUp и preCheckout, который будет выполняться до выполнения шагов сборки. Эти два метода также могут вызывать InterruptedExceptions. Теперь, если мои проверки пройдены и дата занесена в черный список, InterruptException выбрано из метода interruptOnHoliday (...). BuildWrapper также использует BuildWrapperDescriptor, который поместит флажок в настройке задания на основе имени, указанного в переопределенной функции getDisplayName() (действует как тип причала optionBlock). При этом флажке проверяется, что функция setUp может быть вызвана, иначе она не будет. Это эффективно делает плагин проверки праздника необязательным (желаемым).

Чтобы предоставить помощь пользователю о том, что делает плагин, включите файл справки .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(); 
} 
Смежные вопросы