<commit_before><?php

final class DiffusionJenkinsHookAPIMethod
  extends DiffusionConduitAPIMethod {

  public function getAPIMethodName() {
    return 'diffusion.jenkinshook';
  }

  public function getMethodDescription() {
    return 'Notify about finished Jenkins build.';
  }

  public function defineParamTypes() {
    return array(
      'callsign'    => 'required string',
      'jobName'     => 'required string',
      'buildNumber' => 'required int',
    );
  }

  public function defineReturnType() {
    return 'array';
  }

  public function defineErrorTypes() {
    return array(
      'ERR_BAD_COMMIT' => pht('No commit found with that identifier'),
      'ERR_MISSING_JOB' => pht('Job is required.'),
      'ERR_BAD_JOB' => pht('Job not found.'),
      'ERR_MISSING_BUILD' => pht('Build is required.'),
      'ERR_BAD_BUILD' => pht('Build not found.'),
    );
  }

  protected function execute(ConduitAPIRequest $request) {
    $job_name = $request->getValue('jobName');
    if (!$job_name) {
      throw new ConduitException('ERR_MISSING_JOB');
    }

    $build_number = $request->getValue('buildNumber');
    if (!$build_number) {
      throw new ConduitException('ERR_MISSING_BUILD');
    }

    // Get Job Info.
    $job_info = JenkinsAPIRequest::create()
      ->addJob($job_name)
      ->addBuild($build_number)
      ->query();

    $commit_identifier = $job_info->changeSet->items[0]->revision;

    $drequest = DiffusionRequest::newFromDictionary(array(
      'user' => $request->getUser(),
      'callsign' => $request->getValue('callsign'),
      'commit' => $commit_identifier,
    ));

    $commit = $drequest->loadCommit();
    if (!$commit) {
      throw new ConduitException('ERR_BAD_COMMIT');
    }

    $property = $this->getCommitProperty($commit, 'build-recorded');

    if ($property) {
      // Don't record same build twice.
      return array(
        'commitUri' => (string)$drequest->generateURI(
          array('action' => 'commit')),
        'actionTaken' => false,
      );
    }

    $commit_paths = $this->getCommitFiles($drequest);

    // 1. record checkstyle warnings
    $checkstyle_warnings =
      id(new JenkinsWarnings($job_name, $build_number, 'checkstyleResult'))
      ->get($commit_paths);
    $this->setCommitProperty($commit, 'checkstyle:warnings', $checkstyle_warnings);

    // 2. record pmd warnings
    $pmd_warnings =
      id(new JenkinsWarnings($job_name, $build_number, 'pmdResult'))
      ->get($commit_paths);
    $this->setCommitProperty($commit, 'pmd:warnings', $pmd_warnings);

    // 3. record build information
    $message = <<<MESSAGE
    Build **#{$job_info->number}** finished with **{$job_info->result}** status: {$job_info->url}
MESSAGE;
    $this->addComment(
      $commit, $request, $message,
      count($checkstyle_warnings) + count($pmd_warnings) == 0);

    // 4. mark as processed
    $this->setCommitProperty($commit, 'build-recorded', true);

    return array(
      'commitUri' => (string)$drequest->generateURI(
        array('action' => 'commit')),
      'checkstyleWarningCount' => count($checkstyle_warnings),
      'pmdWarningCount' => count($pmd_warnings),
      'actionTaken' => true,
    );
  }

  private function getCommitFiles(DiffusionRequest $drequest) {
    $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
      $drequest);
    $path_changes = $change_query->loadChanges();

    return mpull($path_changes, 'getPath');
  }
<commit_msg>Jenkins integration improvements/bugfixes (round 2)<commit_after><?php

final class DiffusionJenkinsHookAPIMethod
  extends DiffusionConduitAPIMethod {

  public function getAPIMethodName() {
    return 'diffusion.jenkinshook';
  }

  public function getMethodDescription() {
    return 'Notify about finished Jenkins build.';
  }

  public function defineParamTypes() {
    return array(
      'callsign'    => 'required string',
      'jobName'     => 'required string',
      'buildNumber' => 'required int',
    );
  }

  public function defineReturnType() {
    return 'array';
  }

  public function defineErrorTypes() {
    return array(
      'ERR_BAD_COMMIT' => pht('No commit found with that identifier'),
      'ERR_MISSING_JOB' => pht('Job is required.'),
      'ERR_BAD_JOB' => pht('Job not found.'),
      'ERR_MISSING_BUILD' => pht('Build is required.'),
      'ERR_BAD_BUILD' => pht('Build not found.'),
    );
  }

  protected function execute(ConduitAPIRequest $request) {
    $job_name = $request->getValue('jobName');
    if (!$job_name) {
      throw new ConduitException('ERR_MISSING_JOB');
    }

    $build_number = $request->getValue('buildNumber');
    if (!$build_number) {
      throw new ConduitException('ERR_MISSING_BUILD');
    }

    // Get Job Info.
    $job_info = JenkinsAPIRequest::create()
      ->addJob($job_name)
      ->addBuild($build_number)
      ->query();

    $commit_identifier = $this->guessRevision($job_info);

    $drequest = DiffusionRequest::newFromDictionary(array(
      'user' => $request->getUser(),
      'callsign' => $request->getValue('callsign'),
      'commit' => $commit_identifier,
    ));

    $commit = $drequest->loadCommit();
    if (!$commit) {
      throw new ConduitException('ERR_BAD_COMMIT');
    }

    $property = $this->getCommitProperty($commit, 'build-recorded');

    if ($property) {
      // Don't record same build twice.
      return array(
        'commitUri' => (string)$drequest->generateURI(
          array('action' => 'commit', 'stable' => true)),
        'actionTaken' => false,
      );
    }

    $commit_paths = $this->getCommitFiles($drequest);

    // 1. record checkstyle warnings
    $checkstyle_warnings =
      id(new JenkinsWarnings($job_name, $build_number, 'checkstyleResult'))
      ->get($commit_paths);
    $this->setCommitProperty($commit, 'checkstyle:warnings', $checkstyle_warnings);

    // 2. record pmd warnings
    $pmd_warnings =
      id(new JenkinsWarnings($job_name, $build_number, 'pmdResult'))
      ->get($commit_paths);
    $this->setCommitProperty($commit, 'pmd:warnings', $pmd_warnings);

    // 3. record build information
    $message = <<<MESSAGE
    Build **#{$job_info->number}** finished with **{$job_info->result}** status: {$job_info->url}
MESSAGE;

    if ($checkstyle_warnings || $pmd_warnings) {
      $message .= "\n";

      if ($checkstyle_warnings) {
        $message .= "\nCheckstyle Warnings: **".count($checkstyle_warnings).'**';
      }

      if ($pmd_warnings) {
        $message .= "\nPMD Warnings: **".count($pmd_warnings).'**';
      }
    }

    $this->addComment(
      $commit, $request, $message,
      count($checkstyle_warnings) + count($pmd_warnings) == 0);

    // 4. mark as processed
    $this->setCommitProperty($commit, 'build-recorded', true);

    return array(
      'commitUri' => (string)$drequest->generateURI(
        array('action' => 'commit', 'stable' => true)),
      'checkstyleWarningCount' => count($checkstyle_warnings),
      'pmdWarningCount' => count($pmd_warnings),
      'actionTaken' => true,
    );
  }

  private function guessRevision($job_info) {
    if ($job_info->changeSet->items) {
      // Build triggered by commit > take it's revision.
      return $job_info->changeSet->items[0]->revision;
    }

    // Build triggered manually > get "trunk/stable tag" revision.
    foreach ($job_info->changeSet->revisions as $revision) {
      if (preg_match('/(trunk|tags\/stable)$/', $revision->module)) {
        return $revision->revision;
      }
    }

    $message = 'Unable to determine revision from build "%s" information';
    throw new Exception(sprintf($message, $job_info->fullDisplayName));
  }

  private function getCommitFiles(DiffusionRequest $drequest) {
    $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
      $drequest);
    $path_changes = $change_query->loadChanges();

    return mpull($path_changes, 'getPath');
  }

{'fraction_non_alphanumeric': 0.15212443095599393, 'fraction_numerical': 0.0016439049064238746, 'mean_word_length': 3.401224262659989, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1919120', 'n_tokens_mistral': 2507, 'n_tokens_neox': 2445, 'n_words': 484}