/** * @param InputInterface $input * @param OutputInterface $output * @return int|null|void */ protected function execute(InputInterface $input, OutputInterface $output) { $changelog = array(); $client = new Client(new \Github\HttpClient\CachedHttpClient(array('cache_dir' => '/tmp/github-api-cache'))); $client->authenticate($input->getArgument("token"), null, Client::AUTH_HTTP_TOKEN); $pullRequestAPI = $client->api('pull_request'); $paginator = new ResultPager($client); $parameters = array($input->getArgument("organisation"), $input->getArgument("repository"), array('state' => 'closed')); $pullRequests = $paginator->fetchAll($pullRequestAPI, 'all', $parameters); $mergedPullRequests = array_filter($pullRequests, function ($pullRequest) { return !empty($pullRequest["merged_at"]); }); foreach ($mergedPullRequests as $pullRequest) { if (empty($pullRequest['milestone'])) { $milestone = "No Milestone Selected"; } else { $milestone = $pullRequest['milestone']['title'] . " / " . strftime("%Y-%m-%d", strtotime($pullRequest['milestone']['due_on'])); } if (!array_key_exists($milestone, $changelog)) { $changelog[$milestone] = array(); } $changelog[$milestone][] = $pullRequest; } uksort($changelog, 'version_compare'); $changelog = array_reverse($changelog); echo "# Changelog"; foreach ($changelog as $milestone => $pullRequests) { echo "\n\n## {$milestone}\n\n"; foreach ($pullRequests as $pullRequest) { echo "* " . $pullRequest['title'] . " [#" . $pullRequest['number'] . "](" . $pullRequest['html_url'] . ") ([@" . $pullRequest['user']['login'] . "](" . $pullRequest['user']['html_url'] . ")) \n"; } } //var_dump($changelog); }
public function showIndex($login, $repo) { $repoInfo = GitHub::repos()->show($login, $repo); if ($repoInfo['fork']) { $pullFrom = $repoInfo['parent']['owner']['login']; $defaultBranch = $repoInfo['parent']['default_branch']; } else { $pullFrom = $login; $defaultBranch = $repoInfo['default_branch']; } if ($pullFrom != $login) { // Get pulls requests from issue list $pulls = []; $paginator = new ResultPager(GitHub::connection()); $issues = $paginator->fetchAll(GitHub::issues(), 'all', [$pullFrom, $repo, ['creator' => $repoInfo['owner']['login']]]); foreach ($issues as $issue) { if (isset($issue['pull_request'])) { $pull = GitHub::pullRequest()->show($pullFrom, $repo, $issue['number']); $pulls[$pull['head']['ref']][] = $pull; } } } // Get branches for this repo $branches = GitHub::gitData()->references()->branches($login, $repo); foreach ($branches as &$branch) { $branch['name'] = str_replace('refs/heads/', '', $branch['ref']); if ($pullFrom == $login) { $branch['pulls'] = GitHub::pullRequests()->all($pullFrom, $repo, ['base' => $branch['name']]); } else { $branch['pulls'] = isset($pulls[$branch['name']]) ? $pulls[$branch['name']] : []; } } return view('branches.index', ['login' => $login, 'repo' => $repo, 'branches' => $branches, 'rateLimits' => $this->getRateLimit(), 'defaultBranch' => $defaultBranch]); }
public function getContributors($link = null) { $api = $this->client->api('repo'); $paginator = new ResultPager($this->client); $parameters = [$this->config['contributors']['user'], $this->config['contributors']['repository']]; return ['contributors' => $paginator->fetch($api, 'contributors', $parameters), 'links' => $paginator->getPagination()]; }
public function build($username, $repository) { $this->repository = new Repository($username, $repository); // repository data $data = $this->client->api('repo')->show($this->repository->username, $this->repository->repository); $this->repository->size = $data['size']; $this->repository->stargazersCount = $data['stargazers_count']; $this->repository->forks = $data['forks']; $this->repository->openIssues = $data['open_issues']; $this->repository->subscribersCount = $data['subscribers_count']; // repository commit activity do { $activity = $this->client->api('repo')->activity($this->repository->username, $this->repository->repository); $responseStatusCode = $this->client->getHttpClient()->getLastResponse()->getStatusCode(); if ($responseStatusCode != 200) { sleep(3); } else { break; } } while (true); $commitsLastYear = array_map(function (array $weekCommits) { return $weekCommits['total']; }, $activity); $this->repository->commitsCount = array_sum($commitsLastYear); $this->repository->commitsLastMonthCount = array_sum(array_slice($commitsLastYear, -4)); $this->repository->avgCommitsPerWeek = count($commitsLastYear) > 0 ? floor(array_sum($commitsLastYear) / count($commitsLastYear)) : 0; // repository contributors $paginator = new ResultPager($this->client); $contributors = $paginator->fetchAll($this->client->api('repo'), 'contributors', [$this->repository->username, $this->repository->repository, true]); $this->repository->contributorsCount = count($contributors); // user data $user = $this->client->api('user')->show($this->repository->username); $this->repository->userPublicRepos = $user['public_repos']; return $this; }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $destroy_prs = array(); $pull_request = $this->getConfigParameter('pull_request'); $pr_directories = $this->getConfigParameter('pr_directories'); // Get deployed PR's based on directories in $pr_directories and compare // that to the PR's open on GitHub. if ($input->getOption('closed')) { $deployed_prs = array(); $finder = new Finder(); // @TODO need to ensure that prefix is alphanumeric ONLY. $pattern = '/^' . $pull_request['prefix'] . '\\-([0-9]+)/'; $iterator = $finder->directories()->name($pattern)->depth(0)->in($pr_directories); foreach ($iterator as $directory) { preg_match($pattern, $directory->getFilename(), $matches); $deployed_prs[] = $matches[1]; } if (!empty($deployed_prs)) { $github = $this->getGithub(); $open_prs = array(); $paginator = new Github\ResultPager($github); $prs = $paginator->fetchAll($github->api('pr'), 'all', array($this->getConfigParameter('organization'), $this->getConfigParameter('repository'), array('state' => 'open'))); foreach ($prs as $pr) { $open_prs[] = $pr['number']; } // PR's to destroy are deployed PR's that are not open. $destroy_prs = array_diff($deployed_prs, $open_prs); } } else { $pr_number = $input->getArgument('pull-request'); if (!is_numeric($pr_number)) { throw new \Exception("PR must be a number."); } $destroy_prs[] = $pr_number; } if (!empty($destroy_prs)) { $fs = new Filesystem(); $site_dir = $input->getOption('site-dir'); foreach ($destroy_prs as $destroy_pr) { // @TODO get this path from a central place. $pr_path = rtrim($pr_directories, '/') . "/{$pull_request['prefix']}-{$destroy_pr}.{$pull_request['domain']}"; if ($fs->exists($pr_path)) { // Drop the database. // @TODO set/get database name in central place, and use in DrupalSettings. $database = $pull_request['prefix'] . '_' . $destroy_pr; $process = new Process("drush sqlq 'DROP database {$database}'", $pr_path . "/docroot/sites/" . $site_dir); $process->run(); // Remove the PR's web root. $fs->remove($pr_path); // @TODO destroy memcache bins. $output->writeln("<info>Successfully destroyed PR #{$destroy_pr}</info>"); } } } else { $output->writeln("<info>No PR's to destroy.</info>"); } }
/** * Fetch a repo's collaborators from github. * * @param \StyleCI\StyleCI\Models\User $user * @param string $name * * @return array */ protected function fetchFromGitHub(User $user, $name) { $client = $this->factory->make($user); $paginator = new ResultPager($client); $list = []; foreach ($paginator->fetchAll($client->repo()->collaborators(), 'all', explode('/', $name)) as $user) { $list[] = $user['id']; } return $list; }
/** * @test */ public function shouldPaginateGetRequests() { $repositoriesApi = $this->client->api('user'); $repositoriesApi->setPerPage(10); $pager = new ResultPager($this->client); $repositories = $pager->fetch($repositoriesApi, 'repositories', array('KnpLabs')); $this->assertCount(10, $repositories); $repositoriesApi->setPerPage(20); $repositories = $pager->fetch($repositoriesApi, 'repositories', array('KnpLabs')); $this->assertCount(20, $repositories); }
/** * {@inheritdoc} */ public function getIssues(array $criteria = ['state' => 'open']) { list($username, $repo) = explode('/', $this->getName()); $pager = new ResultPager($this->client); $issues = $pager->fetchAll($this->client->issue(), 'all', [$username, $repo, $criteria]); $newIssues = []; foreach ($issues as $issue) { $newIssues[] = new GithubIssue($issue); } return $newIssues; }
/** * Fetch a user's repos from github. * * @param \StyleCI\StyleCI\Models\User $user * * @return array */ protected function fetchFromGitHub(User $user) { $client = $this->factory->make($user); $paginator = new ResultPager($client); $list = []; foreach ($paginator->fetchAll($client->me(), 'repositories', ['public']) as $repo) { // set enabled to false by default // we'll mark those that are enabled at a later point $list[$repo['id']] = ['name' => $repo['full_name'], 'default_branch' => $repo['default_branch'], 'language' => $repo['language'], 'admin' => $repo['permissions']['admin'], 'enabled' => false]; } return $list; }
/** * Disable the styleci webhook for the given repo. * * @param \StyleCI\StyleCI\Models\Repo $repo * * @return void */ public function disable(Repo $repo) { $url = route('home'); $args = explode('/', $repo->name); $client = $this->factory->make($repo); $hooks = $client->repo()->hooks(); $paginator = new ResultPager($client); foreach ($paginator->fetchAll($hooks, 'all', $args) as $hook) { if ($hook['name'] !== 'web' || StaticStringy::contains($hook['config']['url'], $url, false) !== true) { continue; } $hooks->remove($args[0], $args[1], $hook['id']); } }
public function getUserRepositoriesMatching($pattern) { $this->assertAuthenticated(); // Temporary header https://developer.github.com/v3/repos/#list-your-repositories $this->github->setHeaders(['Accept' => 'application/vnd.github.moondragon+json']); $paginator = new ResultPager($this->github); $repositories = $paginator->fetchAll($this->github->currentUser(), 'repositories'); $repositories = array_map(function ($repository) { return $repository['full_name']; }, $repositories); $pattern = '/^' . preg_quote($pattern, '/') . '$/'; $pattern = str_replace('\\*', '.+', $pattern); return array_filter($repositories, function ($repository) use($pattern) { return preg_match($pattern, $repository) === 1; }); }
/** * @param $repositories * @param $org * @param $me */ private function getIssuesAndPRs(&$repositories, $org, $me) { foreach ($repositories as &$repo) { // Get pulls requests from issue list $pulls = []; $issues = []; $paginator = new ResultPager(GitHub::connection()); $allIssues = $paginator->fetchAll(GitHub::issues(), 'all', [$org['login'], $repo['name'], ['creator' => $me['login']]]); foreach ($allIssues as $issue) { if (isset($issue['pull_request'])) { $pulls[] = $issue; } else { $issues[] = $issue; } } $repo['issues'] = $issues; $repo['pulls'] = $pulls; } }
private function getUserRepositories(Client $client) { $api = $client->api('me'); $paginator = new ResultPager($client); return $paginator->fetchAll($api, 'repositories'); }
/** * Fetch the raw branch list from github. * * @param \StyleCI\StyleCI\Models\Repo $repo * * @return array */ protected function fetchFromGitHub(Repo $repo) { $client = $this->factory->make($repo); $paginator = new ResultPager($client); return $paginator->fetchAll($client->repos(), 'branches', explode('/', $repo->name)); }
public function generate($login, $repo, $milestone) { // Find the milestone number by fetching all milestones $paginator = new ResultPager(GitHub::connection()); $milestones = $paginator->fetchAll(GitHub::issues()->milestones(), 'all', [$login, $repo]); // Fetch the issues for this milestone $milestoneIssues = []; foreach ($milestones as $result) { if ($milestone == $result['title']) { $milestoneIssues = $paginator->fetchAll(GitHub::issues(), 'all', [$login, $repo, ['milestone' => $result['number'], 'state' => 'all']]); break; } } $pullRequests = []; $issues = []; $acknowledgements = []; $labels = []; $hideAuthors = explode(',', $_SERVER['GITHUB_HIDE_AUTHORS']); $labelGroups = explode(',', $_SERVER['GITHUB_LABELS']); foreach ($labelGroups as &$label) { list($labelName, $groupName) = explode('|', $label); $labels[$labelName] = $groupName; } $defaultGroup = $labels[$_SERVER['GITHUB_DEFAULT_GROUP']]; foreach ($milestoneIssues as $k => $issue) { $issue['submitter'] = in_array($issue['user']['login'], $hideAuthors) ? '' : $issue['user']['login']; if (!empty($issue['submitter']) && !in_array('@' . $issue['submitter'], $acknowledgements)) { $acknowledgements[] = '@' . $issue['submitter']; } if (isset($issue['pull_request'])) { $labelFound = false; foreach ($issue['labels'] as $label) { if (array_key_exists($label['name'], $labels)) { $pullRequests[$labels[$label['name']]][] = $issue; $labelFound = true; break; } } if (!$labelFound) { $pullRequests[$defaultGroup][] = $issue; } } else { $labelFound = false; foreach ($issue['labels'] as $label) { if (array_key_exists($label['name'], $labels)) { $issues[$labels[$label['name']]][] = $issue; $labelFound = true; break; } } if (!$labelFound) { $issues[$defaultGroup][] = $issue; } } } // Sort by label order $pullRequests = array_merge(array_flip($labels), $pullRequests); $issues = array_merge(array_flip($labels), $issues); // Set acknowledgements natcasesort($acknowledgements); $acknowledgements = implode(', ', $acknowledgements); return view('milestones.changelog', ['login' => $login, 'repo' => $repo, 'milestone' => $milestone, 'pullRequests' => $pullRequests, 'issues' => $issues, 'acknowledgements' => $acknowledgements, 'rateLimits' => $this->getRateLimit()]); }
/** * @return array|mixed */ public function fetchAllAccessibleRepos() { return $this->paginator->fetchAll($this->getMeApi(), 'repositories', ['type' => 'all']); }
/** * @test * * description hasPrevious */ public function shouldHavePrevious() { $responseMock = $this->getResponseMock('<http://github.com/previous>; rel="prev"'); $httpClient = $this->getHttpClientMock($responseMock); $client = $this->getClientMock($httpClient); $paginator = new Github\ResultPager($client); $paginator->postFetch(); $this->assertEquals($paginator->hasPrevious(), true); $this->assertEquals($paginator->hasNext(), false); }
/** * Process Integration job. * * - Get all the Issues (We need issues since they have labels). * - Figure our if they're a Pull Request or Not. * - Ignore all Pull Request with GITHUB_LABEL_MERGE_FAILED based labels. * - Apply each Pull Request locally to "integration" branch. * - Deploy integration branch to acquia (DEV set up to track it) */ protected function execute(InputInterface $input, OutputInterface $output) { $github = $this->getGithub(); // Request all open issues in created order. 1st come 1st serve. $paginator = new Github\ResultPager($github); $issues_api = $github->api('issue'); $pull_requests = $paginator->fetchAll($issues_api, 'all', array($this->getConfigParameter('organization'), $this->getConfigParameter('repository'), array('state' => 'open', 'sort' => 'created', 'direction' => 'asc'))); // Get current branch or commit. $current_head = ''; $process = new Process('git symbolic-ref --short HEAD'); $process->run(); if ($process->isSuccessful()) { $current_head = trim($process->getOutput()); } else { $process = new Process('git rev-parse HEAD'); $process->run(); if ($process->isSuccessful()) { $current_head = trim($process->getOutput()); } } $process = new Process('git checkout -B integration'); $process->run(); if (!$process->isSuccessful()) { throw new \RuntimeException($process->getErrorOutput()); } foreach ($pull_requests as $pr) { // If the issue is not a PR we skip it. if (empty($pr['pull_request']['patch_url'])) { continue; } // If this issue has any of the following labels, we also skip it. foreach ($pr['labels'] as $label) { // TODO: Have a function check this. if (in_array($label['name'], $this->invalid_labels)) { // This continue breaks us out of the top foreach. continue 2; } } // Now try to apply the patch or else mark it as failure. $url = $pr['pull_request']['html_url']; if ($input->getOption('am')) { $command = "hub am --3way {$url}"; } else { $command = "hub merge {$url}"; } $output->writeln("\n" . $command); $process = new Process($command); $process->run(); if (!$process->isSuccessful()) { // We reset the failed AM & mark the PR as GITHUB_LABEL_MERGE_FAILED. $output->writeln("<error>Failed to applied PR# {$pr['number']}: {$url}.</error>"); $output->writeln($process->getOutput()); if (!$input->getOption('no-label')) { $this->addGithubLabel($pr['number'], self::GITHUB_LABEL_MERGE_FAILED); $this->addGithubComment($pr['number'], implode('\\n\\n', array('I was unable to merge this Pull Request with the other open Pull Requests.', 'Perhaps the following log will assist your debugging…', '```sh', $process->getErrorOutput(), '```'))); } $process = new Process('git merge --abort'); $process->run(); } else { $output->writeln("<info>Successfully applied PR #{$pr['number']}: {$url}.</info>"); } } // Now we deploy integration to acquia always fresh. // We only do this if the --push flag is set. if ($input->getOption('push')) { $process = new Process('git push acquia integration --force'); $process->run(); if (!$process->isSuccessful()) { throw new \RuntimeException($process->getErrorOutput()); } $output->writeln("<info>Successfully Pushed integration branch to Acquia.</info>"); } // Return to the branch the user was previously on, if they were on one. if (!empty($current_head)) { $process = new Process("git checkout {$current_head}"); $process->run(); } }
/** * @param Client $client * @param string $method * @param array $params * @return \Generator */ protected function fetchUsersAsGenerator(Client $client, $method, $params) { $paginator = new ResultPager($client); $userApi = $client->api('user'); $results = $paginator->fetch($userApi, $method, $params); while (true) { foreach ($results as $result) { if (is_array($result) && isset($result[0]) && is_array($result[0])) { foreach ($result as $user) { (yield $user); } } else { (yield $result); } } if (!$paginator->hasNext()) { break; } $results = $paginator->fetchNext(); } }
/** * @return array */ private function getAllReleases() { $client = $this->getClient(); $paginator = new GitHubResultPager($client); return $paginator->fetchAll($client->repo()->releases(), 'all', [self::GITHUB_USER, self::GITHUB_REPO]); }
/** * Retrieves all the Gists using the ResultPager api * * @return array All the Gists for the logged in use * @since 0.5.0 */ protected function all() { $pager = new ResultPager($this->client); return $pager->fetchAll($this->call(), 'all'); }
/** * Gets the status of a commit reference. * * @param string $org * @param string $repo * @param string $hash * * @return array[] */ public function getCommitStatuses($org, $repo, $hash) { $pager = new ResultPager($this->client); return $pager->fetchAll($this->client->api('repo')->statuses(), 'combined', [$org, $repo, $hash])['statuses']; }
/** * @param string $user * @param string $repository * @return Issue[] */ private function fetchIssues($user, $repository) { /** @var \GitHub\Api\Issue $issueApi */ $issueApi = $this->github->api('issue'); $paginator = new ResultPager($this->github); $issues = $paginator->fetchAll($issueApi, 'all', [$user, $repository, ['state' => 'all']]); $issues = array_map(function (array $data) { return Issue::fromArray($data); }, $issues); return $issues; }
public function generate($login, $repo, $milestone) { // Find the milestone number by fetching all milestones $paginator = new ResultPager(GitHub::connection()); $milestones = $paginator->fetchAll(GitHub::issues()->milestones(), 'all', [$login, $repo]); // Fetch the issues for this milestone $milestoneIssues = []; foreach ($milestones as $result) { if ($milestone == $result['title']) { $milestoneIssues = $paginator->fetchAll(GitHub::issues(), 'all', [$login, $repo, ['milestone' => $result['number'], 'state' => 'all']]); $milestone = $result; break; } } $prs = []; $team = explode(',', $_SERVER['GITHUB_HIDE_AUTHORS']); foreach ($milestoneIssues as $k => $issue) { if (isset($issue['pull_request']) && $issue['state'] !== 'closed') { $needsDocumentation = false; $hasConflicts = false; $status = false; foreach ($issue['labels'] as $label) { switch (true) { case 'Pending Test Confirmation' == $label['name']: $status = 'Pending Test Confirmation'; break; case 'Code Review' == $label['name']: $status = 'Code Review'; break; case 'Pending Feedback' == $label['name']: $status = 'Pending Feedback'; break; case 'Ready To Commit' == $label['name']: $status = "Ready To Commit"; break; } if ('Needs Documentation' == $label['name']) { $needsDocumentation = true; } if ($status) { break; } } if (!$status) { $status = 'Needs Testing'; } $pull = GitHub::pullRequest()->show($login, $repo, $issue['number']); if (empty($pull['mergeable'])) { $hasConflicts = true; } $plusOne = []; $feedBackBy = []; $comments = $event['comments'] = GitHub::issue()->comments()->all($login, $repo, $issue['number']); foreach ($comments as $comment) { if (in_array($comment['user']['login'], $team)) { if (strpos($comment['body'], '+1') !== false) { $plusOne[] = $comment['user']['login']; } $feedBackBy[$comment['user']['login']] = $comment['user']['login']; } } $prs[$issue['number']] = ['author' => $issue['user']['login'], 'name' => $issue['title'], 'link' => $issue['html_url'], 'status' => $status, 'hasConflicts' => $hasConflicts, 'needsDocs' => $needsDocumentation, 'plusOne' => $plusOne, 'feedbackBy' => $feedBackBy]; } } uasort($prs, function ($a, $b) { return strnatcasecmp($a['author'], $b['author']); }); return view('milestones.analyasis', ['login' => $login, 'repo' => $repo, 'milestone' => $milestone, 'pullRequests' => $prs, 'rateLimits' => $this->getRateLimit()]); }
/** * Fetch the commits for the repo's branch. * * @param string $branch The branch to check * @return array The commits made to the repository's branch. */ public function getCommitsOnBranch($branch = 'master') { $paginator = new ResultPager($this->_client); return $paginator->fetchAll($this->_client->api('repo')->commits(), 'all', [$this->_owner, $this->_repo, ['sha' => $branch]]); }
/** * Get repositories data * * @param string $username * @return array */ public function getUserRepositories($username) { return $this->pager->fetchAll($this->userApi, 'repositories', [$username]); }
/** * {@inheritdoc} */ public function getTags() { list($repoUser, $repoName) = explode('/', $this->clearGitURL($this->url)); $paginator = new ResultPager($this->githubClient); $tags = $paginator->fetchAll($this->githubClient->api('repo'), 'tags', array($repoUser, $repoName)); // edge case: no tags if (count($tags) === 0) { return array(); } $sortedTags = $this->sortTags($tags); // Filters out bad tag specs return array_keys($sortedTags); }
public function getOrgMembers($orgName) { $API = $this->client->api('organizations')->members(); $paginator = new ResultPager($this->client); return $paginator->fetchAll($API, 'all', [$orgName]); }