/** * @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}"); }
/** * @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); }
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']); }
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'); }
/** * * @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'); } }
/** * @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; }
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()); }
/** * 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.'); }
/** * 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); } }
/** * 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); }
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); }
/** * @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__); }
/** * @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); }
/** * 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); }
/** * @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__); }
public function __construct() { $this->config = Diesel::create('\\Bart\\GitHook\\GitHookSystemConfig'); parent::__construct(); }
/** * 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(); } } }
/** * 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); }