Skip to content

Commit

Permalink
Merge pull request #39 from akeneo/TIP-1391
Browse files Browse the repository at this point in the history
TIP-1391: auto merge Nelson's PRs
  • Loading branch information
jjanvier authored Feb 21, 2020
2 parents 3463602 + 55dadbf commit ed5210b
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 45 deletions.
33 changes: 33 additions & 0 deletions spec/Akeneo/Git/PullRequestMergerSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace spec\Akeneo\Git;

use Github\Api\PullRequest;
use Github\Client;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class PullRequestMergerSpec extends ObjectBehavior
{
public function let(
Client $client,
EventDispatcherInterface $eventDispatcher
) {
$this->beConstructedWith($client, $eventDispatcher);
}

public function it_merges_a_pull_request(Client $client, PullRequest $githubMerger)
{
$client->api('pull_request')->willReturn($githubMerger);
$githubMerger->merge('nelson', 'akeneo/repo', 78556, 'Merge pull request #78556')->shouldBeCalled();

$this->mergePullRequest([
'number' => 78556,
'base' => [
'user' => ['login' => 'nelson'],
'repo' => ['name' => 'akeneo/repo']
]
]);
}
}
4 changes: 4 additions & 0 deletions src/Akeneo/Event/Events.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class Events

const POST_GITHUB_CHECK_DIFF = 'post_github_check_diff';

const PRE_GITHUB_MERGE_PR = 'pre_github_merge_pr';

const POST_GITHUB_MERGE_PR = 'post_github_merge_pr';

// Crowdin
const PRE_CROWDIN_EXPORT = 'pre_crowdin_export';

Expand Down
18 changes: 18 additions & 0 deletions src/Akeneo/Git/ConsoleLogger.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public static function getSubscribedEvents()
Events::POST_GITHUB_CREATE_PR => 'postGithubCreatePR',
Events::PRE_GITHUB_CHECK_DIFF => 'preGithubCheckDiff',
Events::POST_GITHUB_CHECK_DIFF => 'postGithubCheckDiff',
Events::PRE_GITHUB_MERGE_PR => 'preGithubMergePR',
Events::POST_GITHUB_MERGE_PR => 'postGithubMergePR',
];
}

Expand Down Expand Up @@ -114,4 +116,20 @@ public function postGithubCheckDiff(GenericEvent $event)
{
$this->writeSuccess(sprintf('%s difference(s) found!', $event->getArgument('diff')));
}

/**
* @param GenericEvent $event
*/
public function preGithubMergePR(GenericEvent $event)
{
$this->writeProcessing(Events::PRE_GITHUB_MERGE_PR, $event->getArguments());
}

/**
* @param GenericEvent $event
*/
public function postGithubMergePR(GenericEvent $event)
{
$this->writeProcessing(Events::POST_GITHUB_MERGE_PR, $event->getArguments());
}
}
57 changes: 57 additions & 0 deletions src/Akeneo/Git/DiffChecker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Akeneo\Git;

use Akeneo\Event\Events;
use Akeneo\System\Executor;
use Exception;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;

class DiffChecker
{
/** @var Executor */
private $executor;

/** @var EventDispatcherInterface */
private $eventDispatcher;

public function __construct(
Executor $executor,
EventDispatcherInterface $eventDispatcher
) {
$this->executor = $executor;
$this->eventDispatcher = $eventDispatcher;
}

/**
* Check if current repository has diff, so we know if we have to create PR or not.
*
* @param string $projectDir
*
* @return bool
* @throws Exception
*/
public function haveDiff($projectDir)
{
$this->eventDispatcher->dispatch(Events::PRE_GITHUB_CHECK_DIFF);

$commands = [
sprintf('cd %s && git diff|wc -l', $projectDir),
sprintf('cd %s && git ls-files --others --exclude-standard|wc -l', $projectDir),
];
$diff = 0;
foreach ($commands as $command) {
$result = $this->executor->execute($command, true);
$matches = null;
preg_match('/^(?P<diff>\d+)\\n$/', $result[0], $matches);
$diff += intval($matches['diff']);
}

$this->eventDispatcher->dispatch(Events::POST_GITHUB_CHECK_DIFF, new GenericEvent($this, [
'diff' => $diff
]));

return intval(0 !== $diff);
}
}
41 changes: 9 additions & 32 deletions src/Akeneo/Git/PullRequestCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Akeneo\Event\Events;
use Akeneo\System\Executor;
use Github\Client;
use Github\Exception\ValidationFailedException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;

Expand Down Expand Up @@ -68,8 +67,11 @@ public function __construct(
* @param string $baseDir
* @param string $projectDir
* @param boolean $dryRun
*
* @return array|null
* @throws \Exception
*/
public function create($baseBranch, $baseDir, $projectDir, $dryRun = false)
public function create($baseBranch, $baseDir, $projectDir, $dryRun = false): ?array
{
$branch = $this->getBranchName($baseBranch);

Expand All @@ -83,6 +85,8 @@ public function create($baseBranch, $baseDir, $projectDir, $dryRun = false)
'dryRun' => $dryRun,
]));

$pullRequest = null;

if (!$dryRun) {
$this->executor->execute(sprintf('cd %s && git checkout -B crowdin/%s', $projectDir, $branch));

Expand All @@ -92,7 +96,7 @@ public function create($baseBranch, $baseDir, $projectDir, $dryRun = false)

$this->executor->execute(sprintf('cd %s && git push origin crowdin/%s', $projectDir, $branch));

$this->client->api('pr')->create(
$pullRequest = $this->client->api('pr')->create(
$this->owner,
$this->repository,
[
Expand All @@ -109,36 +113,8 @@ public function create($baseBranch, $baseDir, $projectDir, $dryRun = false)
}

$this->eventDispatcher->dispatch(Events::POST_GITHUB_CREATE_PR);
}

/**
* Check if current repository have diff, to know if we have to create PR or not.
*
* @param string $projectDir
*
* @return bool
*/
public function haveDiff($projectDir)
{
$this->eventDispatcher->dispatch(Events::PRE_GITHUB_CHECK_DIFF);

$commands = [
sprintf('cd %s && git diff|wc -l', $projectDir),
sprintf('cd %s && git ls-files --others --exclude-standard|wc -l', $projectDir),
];
$diff = 0;
foreach ($commands as $command) {
$result = $this->executor->execute($command, true);
$matches = null;
preg_match('/^(?P<diff>\d+)\\n$/', $result[0], $matches);
$diff += intval($matches['diff']);
}

$this->eventDispatcher->dispatch(Events::POST_GITHUB_CHECK_DIFF, new GenericEvent($this, [
'diff' => $diff
]));

return intval(0 !== $diff);
return $pullRequest;
}

/**
Expand All @@ -147,6 +123,7 @@ public function haveDiff($projectDir)
* @param string|null $baseBranch
*
* @return string
* @throws \Exception
*/
protected function getBranchName($baseBranch)
{
Expand Down
55 changes: 55 additions & 0 deletions src/Akeneo/Git/PullRequestMerger.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Akeneo\Git;

use Akeneo\Event\Events;
use Github\Client;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;

class PullRequestMerger
{
/** @var Client */
private $client;

/** @var EventDispatcherInterface */
private $eventDispatcher;

public function __construct(
Client $client,
EventDispatcherInterface $eventDispatcher
) {
$this->client = $client;
$this->eventDispatcher = $eventDispatcher;
}

public function mergePullRequest(array $pullRequest): void
{
$this->waitForGithubCheckMergeableBranch();

$mergeTitle = sprintf('Merge pull request #%s', $pullRequest['number']);

$this->eventDispatcher->dispatch(Events::PRE_GITHUB_MERGE_PR, new GenericEvent($this, [
'number' => $pullRequest['number'],
]));

$this->client->api('pull_request')->merge(
$pullRequest['base']['user']['login'],
$pullRequest['base']['repo']['name'],
$pullRequest['number'],
$mergeTitle
);

$this->eventDispatcher->dispatch(Events::POST_GITHUB_MERGE_PR, new GenericEvent($this, [
'number' => $pullRequest['number'],
]));
}

/**
* cf. https://github.community/t5/GitHub-API-Development-and/Merging-via-REST-API-returns-405-Base-branch-was-modified-Review/td-p/19281
*/
private function waitForGithubCheckMergeableBranch(): void
{
sleep(3);
}
}
55 changes: 42 additions & 13 deletions src/Akeneo/Nelson/PullTranslationsExecutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
use Akeneo\Crowdin\PackagesDownloader;
use Akeneo\Crowdin\TranslatedProgressSelector;
use Akeneo\Event\Events;
use Akeneo\Git\DiffChecker;
use Akeneo\Git\ProjectCloner;
use Akeneo\Git\PullRequestCreator;
use Akeneo\Git\PullRequestMerger;
use Akeneo\System\Executor;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
Expand All @@ -21,16 +23,36 @@
*/
class PullTranslationsExecutor
{
/**
* @param ProjectCloner $cloner
* @param PullRequestCreator $pullRequestCreator
* @param PackagesDownloader $downloader
* @param TranslatedProgressSelector $status
* @param PackagesExtractor $extractor
* @param TranslationFilesCleaner $translationsCleaner
* @param Executor $systemExecutor
* @param EventDispatcherInterface $eventDispatcher
*/
/** @var EventDispatcherInterface */
private $eventDispatcher;

/** @var Executor */
private $systemExecutor;

/** @var TranslationFilesCleaner */
private $translationsCleaner;

/** @var PackagesExtractor */
private $extractor;

/** @var TranslatedProgressSelector */
private $status;

/** @var PackagesDownloader */
private $downloader;

/** @var PullRequestCreator */
private $pullRequestCreator;

/** @var ProjectCloner */
private $cloner;

/** @var DiffChecker */
private $diffChecker;

/** @var PullRequestMerger */
private $pullRequestMerger;

public function __construct(
ProjectCloner $cloner,
PullRequestCreator $pullRequestCreator,
Expand All @@ -39,7 +61,9 @@ public function __construct(
PackagesExtractor $extractor,
TranslationFilesCleaner $translationsCleaner,
Executor $systemExecutor,
EventDispatcherInterface $eventDispatcher
EventDispatcherInterface $eventDispatcher,
DiffChecker $diffChecker,
PullRequestMerger $pullRequestMerger
) {
$this->cloner = $cloner;
$this->pullRequestCreator = $pullRequestCreator;
Expand All @@ -49,6 +73,8 @@ public function __construct(
$this->translationsCleaner = $translationsCleaner;
$this->systemExecutor = $systemExecutor;
$this->eventDispatcher = $eventDispatcher;
$this->diffChecker = $diffChecker;
$this->pullRequestMerger = $pullRequestMerger;
}

/**
Expand Down Expand Up @@ -100,8 +126,11 @@ protected function pullTranslations($githubBranch, $crowdinFolder, array $packag
$this->translationsCleaner->cleanFiles($options['locale_map'], $cleanerDir, $projectDir);
$this->translationsCleaner->moveFiles($cleanerDir, $projectDir);

if ($this->pullRequestCreator->haveDiff($projectDir)) {
$this->pullRequestCreator->create($githubBranch, $options['base_dir'], $projectDir, $dryRun);
if ($this->diffChecker->haveDiff($projectDir)) {
$pullRequest = $this->pullRequestCreator->create($githubBranch, $options['base_dir'], $projectDir, $dryRun);
if (null !== $pullRequest) {
$this->pullRequestMerger->mergePullRequest($pullRequest);
}
}

$this->eventDispatcher->dispatch(Events::POST_NELSON_PULL);
Expand Down
12 changes: 12 additions & 0 deletions src/Akeneo/Resources/config/github.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,15 @@ services:
- %github.fork_owner%
- %github.owner%
- %github.repository%

github.diff_checker:
class: Akeneo\Git\DiffChecker
arguments:
- '@system.executor'
- '@event_dispatcher'

github.pull_request_merger:
class: Akeneo\Git\PullRequestMerger
arguments:
- '@github.client'
- '@event_dispatcher'
2 changes: 2 additions & 0 deletions src/Akeneo/Resources/config/nelson.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ services:
- @nelson.translation_files.cleaner
- @system.executor
- @event_dispatcher
- @github.diff_checker
- @github.pull_request_merger

nelson.push_translation_keys_executor:
class: Akeneo\Nelson\PushTranslationKeysExecutor
Expand Down
2 changes: 2 additions & 0 deletions src/Akeneo/Resources/translations/en.fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ pre_github_check_diff: Vérifie les différences avec la branche courante
post_github_check_diff: '%diff% différence(s) trouvée(s) !'
pre_crowdin_packages: Vérifie les archives à mettre à jour
post_crowdin_packages: '%count% archive(s) trouvée(s) !'
pre_github_merge_pr: 'Merge Pull Request %number%'
post_github_merge_pr: 'Pull Request mergée!'
Loading

0 comments on commit ed5210b

Please sign in to comment.