Example #1
1
 /**
  * @param array $conf Configurations for reaching Gerrit server
  */
 public function __construct()
 {
     /** @var \Bart\Configuration\GerritConfig $config */
     $config = Diesel::create('Bart\\Configuration\\GerritConfig');
     /** @var \Bart\SshWrapper $ssh */
     $ssh = Diesel::create('Bart\\SshWrapper', $config->host(), $config->sshPort());
     $ssh->setCredentials($config->sshUser(), $config->sshKeyFile());
     $this->ssh = $ssh;
     $this->config = $config;
     $this->logger = Log4PHP::getLogger(__CLASS__);
     $this->logger->trace("Configured Gerrit API using ssh {$ssh}");
 }
Example #2
0
 /**
  * @param array $hookConf Configuration for this hook type
  * @param string $repo Name of the repository
  */
 public function __construct(array $hookConf, $gitDir, $repo)
 {
     $this->hookConf = $hookConf;
     $this->repo = $repo;
     $this->logger = Log4PHP::getLogger(get_called_class());
     /** @var \Bart\Git git handle to current project */
     $this->git = Diesel::create('Bart\\Git', $gitDir);
 }
Example #3
0
 public function __construct(array $conf, $gitDir, $repo)
 {
     $stl_conf = $conf['jenkins'];
     if (!array_key_exists('job_name', $stl_conf)) {
         // Default to the repo for convenience
         $stl_conf['job_name'] = $repo;
     }
     parent::__construct($stl_conf, $gitDir, $repo);
     $this->job = Diesel::create('Bart\\Jenkins\\Job', $stl_conf['host'], $stl_conf['job_name']);
 }
Example #4
0
 public function __construct($server)
 {
     if (!is_string($server)) {
         throw new \Exception("Invalid server {$server}");
     }
     $this->server = $server;
     $this->ssh_user = get_current_user();
     $this->shell = Diesel::create('Bart\\Shell');
     $this->conf = Diesel::create('Bart\\Config_Parser');
 }
Example #5
0
 /**
  *
  * @param string $usename Jira username
  * @param string $password Jira password
  * @param array $options Generic soap options hash. Must, at the least, specify the WSDL to
  * your Jira SOAP, which can be a local or remote resource. It typically is available at
  * http://$your-jira-server/rpc/soap/jirasoapservice-v2?wsdl'
  */
 public function __construct($username, $password, $options)
 {
     $wsdl = $options['wsdl'];
     unset($options['wsdl']);
     $this->soap = Diesel::create('\\SoapClient', $wsdl, $options);
     try {
         $this->token = $this->soap->login($username, $password);
     } catch (\SoapFault $f) {
         throw new Soap_Exception($f, 'Authentication failed');
     }
 }
Example #6
0
 /**
  * @param string $revision
  * @return bool
  */
 private function isChangeFeatureFlip($revision)
 {
     /** @var Git $git */
     $git = Diesel::create('\\Bart\\Git');
     $fileList = $git->get_file_list($revision);
     foreach ($fileList as $file) {
         if ($file == 'conf_override/features.conf') {
             return true;
         }
     }
     return false;
 }
Example #7
0
 public function __construct()
 {
     parent::__construct();
     /** @var JenkinsConfig $jenkinsConfig */
     $jenkinsConfig = Diesel::create('\\Bart\\Jenkins\\JenkinsConfig');
     /** @var Connection $connection */
     $connection = Diesel::create('\\Bart\\Jenkins\\Connection', $jenkinsConfig->domain(), $jenkinsConfig->protocol(), $jenkinsConfig->port());
     $user = $jenkinsConfig->user();
     $token = $jenkinsConfig->token();
     if ($user !== null && $token !== null) {
         $connection->setAuth($user, $token);
     }
     /** @var Job job */
     $this->job = Diesel::create('\\Bart\\Jenkins\\Job', $connection, $jenkinsConfig->jobLocation());
 }
Example #8
0
 /**
  * Fails if review is not approved & verified in Gerrit
  * @param Commit $commit A git commit with a Change-Id
  * @throws GitHookException If Change-Id not found or the review is not approved or verified
  */
 public function run(Commit $commit)
 {
     try {
         $changeId = $commit->gerritChangeId();
     } catch (GitException $e) {
         $this->logger->warn("{$e->getMessage()}. Skipping commit.");
         throw new GitHookException("Couldn't get Change-Id for {$commit}", $e->getCode(), $e);
     }
     /** @var \Bart\Gerrit\Change $change */
     $change = Diesel::create('\\Bart\\Gerrit\\Change', $changeId);
     if (!$change->isReviewedAndVerified()) {
         $msg = "Could not find an approved & verified change in Gerrit for change {$changeId} in commit {$commit}";
         $this->logger->info($msg);
         throw new GitHookException($msg);
     }
     $this->logger->info('Gerrit approved.');
 }
Example #9
0
 /**
  * Add a comment in JIRA with the commit hash
  * @param Commit $commit The commit for which we're running the Git Hook
  * @throws GitHookException if requirement fails
  */
 public function run(Commit $commit)
 {
     /** @var \Bart\GitHook\GitHookConfig $hConfigs */
     $hConfigs = Diesel::create('\\Bart\\GitHook\\GitHookConfig', $commit);
     // Apply template to produce desired comment for JIRA issue
     $template = $hConfigs->jiraCommentTemplate();
     $count = preg_match_all('/\\%s/', $template);
     $this->logger->debug("Loaded jira template --{$template}-- and found {$count} token(s)");
     $vsprintf_args = [];
     if ($count !== false) {
         $vsprintf_args = array_fill(0, $count, $commit->revision());
     }
     $comment = vsprintf($template, $vsprintf_args);
     $jiraIssues = $commit->jiras();
     $this->logger->debug('Found ' . count($jiraIssues) . " jira issue(s) in {$commit}");
     foreach ($jiraIssues as $jira) {
         $this->logger->debug("Adding comment to jira {$jira}");
         $this->jiraClient->addComment($jira->id(), $comment);
     }
 }
Example #10
0
 /**
  * Curl Jenkins JSON API
  *
  * NOTE: This method is not meant to be used on its own. It is used by other classes,
  * e.g. \Bart\Jenkins\Job, to make API calls against Jenkins.
  *
  * @param string $apiPath The full API path to curl against. For example, to do a
  * simple GET against the Jenkins Job 'Example', the full path, 'job/Example/api/json'
  * must be passed in.
  * @param array $postData if null, then curl uses GET, otherwise POSTs data
  * @return array JSON data decoded as PHP array
  * @throws JenkinsApiException
  */
 public function curlJenkinsApi($apiPath, array $postData = null)
 {
     if (!Strings::startsWith($apiPath, '/')) {
         $apiPath = "/{$apiPath}";
     }
     $fullUrl = "{$this->baseUrl}{$apiPath}";
     $isPost = $postData !== null;
     $this->logger->debug('Curling ' . ($isPost ? 'POST ' : 'GET ') . $fullUrl);
     /** @var \Bart\Curl $curl */
     $curl = Diesel::create('\\Bart\\Curl', $fullUrl, $this->port);
     if ($this->curlOptions !== []) {
         $curl->setPhpCurlOpts($this->curlOptions);
     }
     $response = $isPost ? $curl->post('', [], $postData) : $curl->get('', []);
     $httpCode = $response['info']['http_code'];
     $content = $response['content'];
     if ($httpCode !== 200 && $httpCode !== 201 && $httpCode !== 202) {
         throw new JenkinsApiException("The Jenkins API call returned a {$httpCode}, " . "with the following content: {$content}");
     }
     return JSON::decode($content);
 }
Example #11
0
 public function run($commitHash)
 {
     $info = $this->git->get_pretty_email($commitHash);
     $msg = $info['subject'] . PHP_EOL . $info['message'];
     if (preg_match('/\\{nobuild\\:\\s(\\".+?\\")\\}/', $msg, $matches) > 0) {
         $reason = $matches[1];
         $this->logger->debug('Skipping build with message: ' . $reason);
         return;
     }
     $jobName = $this->hookConf['job_name'];
     // Default parameters that all jobs may use, but may otherwise ignore
     $params = array('GIT_HASH' => $commitHash, 'Project_Name' => $this->repo, 'Requested_By' => $info['author']);
     if (preg_match('/\\{deploy\\}/', $msg, $matches) > 0) {
         // Submit a deploy job for repo
         $jobName = $this->hookConf['deploy-job'];
         // For repos whose deploy job is one and the same as the integration job
         $params['DEPLOY'] = 'true';
     }
     /** @var \Bart\Jenkins\Job $job */
     $job = Diesel::create('Bart\\Jenkins\\Job', $this->hookConf['host'], $jobName);
     $job->start($params);
 }
Example #12
0
 /**
  * @param string $changeId Gerrit Change-Id key
  */
 public function __construct($changeId)
 {
     $this->api = Diesel::create('\\Bart\\Gerrit\\Api');
     $this->changeId = $changeId;
     $this->logger = Log4PHP::getLogger(__CLASS__);
 }
Example #13
0
 /**
  * @abstract
  * @param string $filePath Absolute path to file containing configurations
  * @param string $subclass Name of the configuration class
  * @return array Contents of configuration parsed as INI with sections
  * @throws ConfigurationException
  */
 protected function loadParsedIni($filePath, $subclass)
 {
     /** @var \Bart\Shell $shell */
     $shell = Diesel::create('\\Bart\\Shell');
     if (!$shell->file_exists($filePath)) {
         throw new ConfigurationException("No configuration file found for {$subclass} at {$filePath}");
     }
     // @NOTE we're not using the ConfigResolver to resolve environment
     // ...distinctions by default. To add this ability, a new method should
     // ...be added to this base to resolve and then reset @configurations
     return $shell->parse_ini_file($filePath, true);
 }
Example #14
0
 /**
  * Instantiate a new hook action
  * @param string $fqcn Name of GitHookAction class
  * @return \Bart\GitHook\GitHookAction
  * @throws GitHookException If class DNE
  */
 private function createHookActionFor($fqcn)
 {
     if ($fqcn === '') {
         throw new GitHookException('Got empty string for GitHookAction FQCN');
     }
     if (!class_exists($fqcn)) {
         throw new GitHookException("No such hook action ({$fqcn})");
     }
     return Diesel::create($fqcn);
 }
Example #15
0
 /**
  * @param $pidFileLocation string Full path to where the pid file should be located, e.g. '/var/run/my-process.pid'
  */
 public function __construct($pidFileLocation)
 {
     $this->pidFileLocation = $pidFileLocation;
     $this->shell = Diesel::create('\\Bart\\Shell');
     $this->logger = Log4PHP::getLogger(__CLASS__);
 }
Example #16
0
 public function __construct()
 {
     $this->config = Diesel::create('\\Bart\\GitHook\\GitHookSystemConfig');
     parent::__construct();
 }
Example #17
0
 /**
  * Run each revision against current hook
  */
 private function processRevisions()
 {
     /** @var \Bart\Git $git */
     $git = Diesel::create('\\Bart\\Git', $this->gitDir);
     /** @var \Bart\Shell $shell */
     $shell = Diesel::create('\\Bart\\Shell');
     // TODO This will need to change to support the 'update' hook
     $stdin = $shell->std_in();
     foreach ($stdin as $rangeAndRef) {
         list($startHash, $endHash, $ref) = explode(" ", $rangeAndRef);
         $endCommit = Diesel::create('\\Bart\\Git\\Commit', $this->gitRoot, $endHash);
         /** @var \Bart\GitHook\GitHookConfig $configs */
         $configs = Diesel::create('\\Bart\\GitHook\\GitHookConfig', $endCommit);
         $validRefs = $configs->getValidRefs();
         // Check whether current ref should have git hooks run or not
         if (!in_array($ref, $validRefs)) {
             $this->logger->info('Skipping hooks on ref ' . $ref);
             continue;
         }
         // TODO should this be reversed?
         // TODO This list could be massive for branches, should we have some config for how deep to go?
         $revisions = $git->getRevList($startHash, $endHash);
         $this->logger->debug('Found ' . count($revisions) . ' revision(s)');
         foreach ($revisions as $revision) {
             $commit = Diesel::create('\\Bart\\Git\\Commit', $this->gitRoot, $revision);
             // Allow a backdoor in case of emergency or broken hook configuration
             if ($this->shouldSkip($commit, $configs)) {
                 continue;
             }
             $hookRunner = $this->createHookRunner($commit);
             $this->logger->debug("Created {$hookRunner}");
             $this->logger->debug("Verifying all configured hook actions against {$revision}");
             // Let any failures bubble up to caller
             $hookRunner->runAllActions();
         }
     }
 }
Example #18
0
 /**
  * Curl Jenkins JSON API
  *
  * @param array $resource_items
  * @param array $post_data if null, then curl uses GET, otherwise POSTs data
  * @returns array JSON data decoded as PHP array
  */
 private function curl(array $resource_items, array $post_data = null)
 {
     $resource_path = implode('/', $resource_items);
     $url = $this->base_job_url . $resource_path . '/api/json';
     $is_post = $post_data != null;
     $this->logger->debug('Curling ' . ($is_post ? 'POST ' : 'GET ') . $url);
     /** @var \Bart\Curl $c */
     $c = Diesel::create('Bart\\Curl', $url, 8080);
     $response = $is_post ? $c->post('', array(), $post_data) : $c->get('', array());
     $jenkins_json = $response['content'];
     return json_decode($jenkins_json, true);
 }