/** Performs the actual update based on job configuration. */
  @Override
  public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
      throws InterruptedException, IOException {
    String realComment = Util.fixEmptyAndTrim(build.getEnvironment(listener).expand(comment));
    String realJql = Util.fixEmptyAndTrim(build.getEnvironment(listener).expand(jqlSearch));
    String realWorkflowActionName =
        Util.fixEmptyAndTrim(build.getEnvironment(listener).expand(workflowActionName));

    JiraSite site = JiraSite.get(build.getProject());

    if (site == null) {
      listener.getLogger().println(Messages.Updater_NoJiraSite());
      build.setResult(Result.FAILURE);
      return true;
    }

    if (StringUtils.isNotEmpty(realWorkflowActionName)) {
      listener
          .getLogger()
          .println(Messages.JiraIssueUpdateBuilder_UpdatingWithAction(realWorkflowActionName));
    }

    listener.getLogger().println("[JIRA] JQL: " + realJql);

    try {
      if (!site.progressMatchingIssues(
          realJql, realWorkflowActionName, realComment, listener.getLogger())) {
        listener.getLogger().println(Messages.JiraIssueUpdateBuilder_SomeIssuesFailed());
        build.setResult(Result.UNSTABLE);
      }
    } catch (ServiceException e) {
      listener.getLogger().println(Messages.JiraIssueUpdateBuilder_Failed());
      e.printStackTrace(listener.getLogger());
      return false;
    }

    return true;
  }