Skip to content

Commit

Permalink
experimental github support (refs #24)
Browse files Browse the repository at this point in the history
  • Loading branch information
mborne committed Nov 24, 2018
1 parent 51fbee1 commit 0efcc2d
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/nbproject/
/vendor/
/satis.json
/web
/web/
/output/

/composer.phar
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,23 @@ Some command line options provide a basic customization options. You may also us
[default-template.json](src/MBO/SatisGitlab/Resources/default-template.json)


## Experimental support for github

Experimental support for github allows to perform :

```bash
bin/satis-gitlab gitlab-to-config https://api.github.com/orgs/symfony/repos $GITHUB_TOKEN
bin/satis-gitlab gitlab-to-config https://api.github.com/users/mborne/repos $GITHUB_TOKEN
bin/satis-gitlab build --skip-errors satis.json web
```

Note that :

* GITHUB_TOKEN is required to avoid rate request limitation
* Config may change (maybe better to support `--orgs=symfony,FriendsOfSymfony --users=mborne`)
* `src/MBO/SatisGitlab/Git` will probably be moved to a dedicated project `hosted-git-client` (avoid using this classes)


## Requirements

* GITLAB API v4
Expand Down
3 changes: 2 additions & 1 deletion src/MBO/SatisGitlab/Command/GitlabToConfigCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use MBO\SatisGitlab\Filter\IgnoreRegexpFilter;
use MBO\SatisGitlab\Filter\IncludeIfHasFileFilter;
use MBO\SatisGitlab\Filter\ProjectTypeFilter;
use MBO\SatisGitlab\Git\ClientFactory;



Expand Down Expand Up @@ -97,7 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output) {
* see https://github.com/mborne/satis-gitlab/issues/2
*/
$clientOptions->setUnsafeSsl(true);
$client = GitlabClient::createClient(
$client = ClientFactory::createClient(
$clientOptions,
$logger
);
Expand Down
65 changes: 65 additions & 0 deletions src/MBO/SatisGitlab/Git/ClientFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace MBO\SatisGitlab\Git;

use Psr\Log\LoggerInterface;
use \GuzzleHttp\Client as GuzzleHttpClient;

/**
* Helper to create clients
*/
class ClientFactory {

/**
* Create a client with options
*
* @param ClientOptions $options
* @param LoggerInterface $logger
* @return ClientInterface
*/
public static function createClient(
ClientOptions $options,
LoggerInterface $logger
) {
$clientClass = self::detectClientClass($options->getUrl());

/* common http options */
$guzzleOptions = array(
'base_uri' => $options->getUrl(),
'timeout' => 10.0,
'headers' => []
);
if ( $options->isUnsafeSsl() ){
$guzzleOptions['verify'] = false;
}
if ( $options->hasToken() ){
if ( GitlabClient::class === $clientClass ){
$guzzleOptions['headers']['Private-Token'] = $options->getToken();
}else if ( GithubClient::class === $clientClass ){
$guzzleOptions['headers']['Authorization'] = 'token '.$options->getToken();
}
}

$httpClient = new GuzzleHttpClient($guzzleOptions);

/* create gitlab client */
return new $clientClass($httpClient,$logger);
}

/**
* Get client class according to URL content
*
* @param string $url
* @return string
*/
public static function detectClientClass($url){
$hostname = parse_url($url, PHP_URL_HOST);
if ( 'api.github.com' === $hostname ){
return GithubClient::class;
}else{
return GitlabClient::class;
}
}

}

83 changes: 83 additions & 0 deletions src/MBO/SatisGitlab/Git/GithubClient.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace MBO\SatisGitlab\Git;

use \GuzzleHttp\Client as GuzzleHttpClient;
use Psr\Log\LoggerInterface;

/**
* Client implementation for github
*/
class GithubClient implements ClientInterface {

const DEFAULT_PER_PAGE = 100;

/**
* @var GuzzleHttpClient
*/
protected $httpClient;

/**
* @var LoggerInterface
*/
protected $logger;

/**
* Constructor with an http client and a logger
* @param $httpClient http client
* @param $logger
*/
public function __construct(
GuzzleHttpClient $httpClient,
LoggerInterface $logger
){
$this->httpClient = $httpClient ;
$this->logger = $logger ;
}

/*
* @{inheritDoc}
*/
public function find(array $options){
/* https://developer.github.com/v3/#pagination */
$page = empty($options['page']) ? 1 : $options['page'];
$perPage = empty($options['per_page']) ? self::DEFAULT_PER_PAGE : $options['per_page'];
$uri = '?page='.$page.'&per_page='.$perPage;

$this->logger->debug('GET '.$uri);
$response = $this->httpClient->get($uri);
$projects = json_decode( (string)$response->getBody(), true ) ;

$result = array();
foreach ( $projects as $project ){
$result[] = new GithubProject($project);
}
return $result;
}

/*
* @{inheritDoc}
*/
public function getRawFile(
ProjectInterface $project,
$filePath,
$ref
){
$metadata = $project->getRawMetadata();
$uri = str_replace(
'{+path}',
urlencode($filePath),
$metadata['contents_url']
);
$uri .= '?ref='.$ref;
$this->logger->debug('GET '.$uri);
$response = $this->httpClient->get($uri,[
'headers' => [
'Accept' => 'application/vnd.github.v3.raw'
]
]);
return (string)$response->getBody();
}


}
53 changes: 53 additions & 0 deletions src/MBO/SatisGitlab/Git/GithubProject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace MBO\SatisGitlab\Git;

/**
* Project implementation for github
*/
class GithubProject implements ProjectInterface {

protected $rawMetadata;

public function __construct($rawMetadata)
{
$this->rawMetadata = $rawMetadata;
}

/*
* @{inheritDoc}
*/
public function getId(){
return $this->rawMetadata['id'];
}

/*
* @{inheritDoc}
*/
public function getName(){
return $this->rawMetadata['full_name'];
}

/*
* @{inheritDoc}
*/
public function getDefaultBranch(){
return $this->rawMetadata['default_branch'];
}

/*
* @{inheritDoc}
*/
public function getHttpUrl(){
return $this->rawMetadata['clone_url'];
}

/*
* @{inheritDoc}
*/
public function getRawMetadata(){
return $this->rawMetadata;
}


}
31 changes: 1 addition & 30 deletions src/MBO/SatisGitlab/Git/GitlabClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/
class GitlabClient implements ClientInterface {

const DEFAULT_PER_PAGE = 50;
const DEFAULT_PER_PAGE = 100;

/**
* @var GuzzleHttpClient
Expand All @@ -38,35 +38,6 @@ public function __construct(
$this->logger = $logger ;
}

/**
* Create GitlabClient with options
*
* @param ClientOptions $options
* @param LoggerInterface $logger
* @return GitlabClient
*/
public static function createClient(
ClientOptions $options,
LoggerInterface $logger
) {
/* create http client for gitlab */
$guzzleOptions = array(
'base_uri' => $options->getUrl(),
'timeout' => 10.0,
'headers' => []
);
if ( $options->isUnsafeSsl() ){
$guzzleOptions['verify'] = false;
}
if ( $options->hasToken() ){
$guzzleOptions['headers']['Private-Token'] = $options->getToken();
}
$httpClient = new GuzzleHttpClient($guzzleOptions);

/* create gitlab client */
return new GitlabClient($httpClient,$logger);
}

/*
* @{inheritDoc}
*/
Expand Down
65 changes: 65 additions & 0 deletions tests/Git/GithubClientTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Tests\SatisGitlab\Git;

use Tests\SatisGitlab\TestCase;

use GuzzleHttp\Client as GuzzleHttpClient;
use MBO\SatisGitlab\Git\GitlabClient;

use Psr\Log\NullLogger;
use MBO\SatisGitlab\Git\ClientOptions;
use MBO\SatisGitlab\Git\ClientFactory;
use MBO\SatisGitlab\Git\GithubClient;
use MBO\SatisGitlab\Git\GithubProject;

class GithubClientTest extends TestCase {

/**
* Ensure client can find mborne's projects
*/
public function testUserRepositories(){
$clientOptions = new ClientOptions();
$clientOptions
->setUrl('https://api.github.com/users/mborne/repos')
;

/* create client */
$client = ClientFactory::createClient(
$clientOptions,
new NullLogger()
);
$this->assertInstanceOf(GithubClient::class,$client);

/* search projects */
$options = array();
$projects = $client->find($options);
$projectsByName = array();
foreach ( $projects as $project ){
$this->assertInstanceOf(GithubProject::class,$project);
$projectsByName[$project->getName()] = $project;
}

/* check project found */
$this->assertArrayHasKey(
'mborne/satis-gitlab',
$projectsByName
);

$project = $projectsByName['mborne/satis-gitlab'];
$composer = $client->getRawFile(
$project,
'composer.json',
$project->getDefaultBranch()
);
$this->assertContains('[email protected]',$composer);

$testFileInSubdirectory = $client->getRawFile(
$project,
'tests/TestCase.php',
$project->getDefaultBranch()
);
$this->assertContains('class TestCase',$testFileInSubdirectory);
}

}
5 changes: 3 additions & 2 deletions tests/Git/GitlabClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
use MBO\SatisGitlab\Git\GitlabClient;

use Psr\Log\NullLogger;
use MBO\SatisGitlab\Git\ClientclientOptions;
use MBO\SatisGitlab\Git\ClientOptions;
use MBO\SatisGitlab\Git\ClientFactory;


class GitlabClientTest extends TestCase {
Expand All @@ -32,10 +32,11 @@ public function testGitlabDotComAuthenticated(){


/* create client */
$client = GitlabClient::createClient(
$client = ClientFactory::createClient(
$clientOptions,
new NullLogger()
);
$this->assertInstanceOf(GitlabClient::class,$client);

/* search projects */
$projects = $client->find(array(
Expand Down

0 comments on commit 0efcc2d

Please sign in to comment.