Skip to content

Commit cfb218b

Browse files
committed
Support for approve workflows
1 parent f285645 commit cfb218b

11 files changed

+138
-16
lines changed

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"doctrine/doctrine-migrations-bundle": "^3.0",
1212
"doctrine/orm": "^2.7",
1313
"incenteev/composer-parameter-handler": "~2.0",
14-
"knplabs/github-api": "^3.2",
14+
"knplabs/github-api": "3.3.x-dev",
1515
"nyholm/psr7": "^1.3",
1616
"sensio/framework-extra-bundle": "^5.2",
1717
"symfony/console": "^5.2",

composer.lock

+12-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/packages/github_api.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,6 @@ services:
6969
Github\Api\Search:
7070
factory: ['@Github\Client', api]
7171
arguments: [search]
72+
73+
Github\Api\Repository\Actions\WorkflowRuns:
74+
factory: ['@Github\Api\Repo', workflowRuns]

config/services.yaml

+4-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ parameters:
1515
- 'App\Subscriber\UnsupportedBranchSubscriber'
1616
- 'App\Subscriber\RemoveStalledLabelOnCommentSubscriber'
1717
- 'App\Subscriber\AllowEditFromMaintainerSubscriber'
18+
- 'App\Subscriber\ApproveCiForNonContributors'
1819
secret: '%env(SYMFONY_SECRET)%'
1920

2021
symfony/symfony-docs:
@@ -31,6 +32,7 @@ parameters:
3132
- 'App\Subscriber\RemoveStalledLabelOnCommentSubscriber'
3233
- 'App\Subscriber\UpdateMilestoneWhenLabeledWaitingCodeMergeSubscriber'
3334
- 'App\Subscriber\AllowEditFromMaintainerSubscriber'
35+
- 'App\Subscriber\ApproveCiForNonContributors'
3436
secret: '%env(SYMFONY_DOCS_SECRET)%'
3537

3638
# used in a functional test
@@ -51,6 +53,7 @@ parameters:
5153
- 'App\Subscriber\RemoveStalledLabelOnCommentSubscriber'
5254
- 'App\Subscriber\UpdateMilestoneWhenLabeledWaitingCodeMergeSubscriber'
5355
- 'App\Subscriber\AllowEditFromMaintainerSubscriber'
56+
- 'App\Subscriber\ApproveCiForNonContributors'
5457

5558
services:
5659
_defaults:
@@ -75,12 +78,12 @@ services:
7578
resource: '../src/Subscriber/*'
7679
autoconfigure: false
7780

78-
7981
App\Api\Issue\IssueApi: '@App\Api\Issue\GithubIssueApi'
8082
App\Api\Label\LabelApi: '@App\Api\Label\GithubLabelApi'
8183
App\Api\Milestone\MilestoneApi: '@App\Api\Milestone\GithubMilestoneApi'
8284
App\Api\PullRequest\PullRequestApi: '@App\Api\PullRequest\GithubPullRequestApi'
8385
App\Api\Status\StatusApi: '@App\Api\Status\GitHubStatusApi'
86+
App\Api\Workflow\WorkflowApi: '@App\Api\Workflow\GithubWorkflowApi'
8487

8588
App\Service\RepositoryProvider:
8689
arguments: [ '%repositories%' ]

config/services_test.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ services:
88
App\Api\Milestone\MilestoneApi: '@App\Api\Milestone\StaticMilestoneApi'
99
App\Api\PullRequest\PullRequestApi: '@App\Api\PullRequest\NullPullRequestApi'
1010
App\Api\Status\StatusApi: '@App\Api\Status\NullStatusApi'
11+
App\Api\Workflow\WorkflowApi: '@App\Api\Workflow\NullWorkflowApi'
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace App\Api\Workflow;
4+
5+
use App\Model\Repository;
6+
use Github\Api\Repository\Actions\WorkflowRuns;
7+
use Github\ResultPager;
8+
use Psr\Log\LoggerInterface;
9+
10+
/**
11+
* @author Tobias Nyholm <[email protected]>
12+
*/
13+
class GithubWorkflowApi implements WorkflowApi
14+
{
15+
private ResultPager $resultPager;
16+
private WorkflowRuns $workflowApi;
17+
private LoggerInterface $logger;
18+
19+
public function __construct(ResultPager $resultPager, WorkflowRuns $workflowApi, LoggerInterface $logger)
20+
{
21+
$this->resultPager = $resultPager;
22+
$this->workflowApi = $workflowApi;
23+
$this->logger = $logger;
24+
}
25+
26+
public function approveWorkflowsForPullRequest(Repository $repository, string $headRepository, string $headBranch): void
27+
{
28+
$runs = $this->resultPager->fetchAllLazy($this->workflowApi, 'all', [$repository->getVendor(), $repository->getName(), [
29+
'branch' => $headBranch,
30+
'status' => 'action_required',
31+
]]);
32+
33+
foreach ($runs as $run) {
34+
if ($headRepository === $run['head_repository']['full_name']) {
35+
$this->workflowApi->approve($repository->getVendor(), $repository->getName(), $run['id']);
36+
}
37+
}
38+
}
39+
}

src/Api/Workflow/NullWorkflowApi.php

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace App\Api\Workflow;
4+
5+
use App\Model\Repository;
6+
7+
class NullWorkflowApi implements WorkflowApi
8+
{
9+
public function approveWorkflowsForPullRequest(Repository $repository, string $headRepository, string $headBranch): void
10+
{
11+
}
12+
}

src/Api/Workflow/WorkflowApi.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace App\Api\Workflow;
4+
5+
use App\Model\Repository;
6+
7+
/**
8+
* @author Tobias Nyholm <[email protected]>
9+
*/
10+
interface WorkflowApi
11+
{
12+
/**
13+
* Find workflow runs related to the PR and approve them.
14+
*/
15+
public function approveWorkflowsForPullRequest(Repository $repository, string $headRepository, string $headBranch): void;
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace App\Subscriber;
4+
5+
use App\Api\Workflow\WorkflowApi;
6+
use App\Event\GitHubEvent;
7+
use App\GitHubEvents;
8+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
9+
10+
/**
11+
* Make sure CI is running for all PRs.
12+
*
13+
* @author Tobias Nyholm <[email protected]>
14+
*/
15+
class ApproveCiForNonContributors implements EventSubscriberInterface
16+
{
17+
private WorkflowApi $workflowApi;
18+
19+
public function __construct(WorkflowApi $workflowApi)
20+
{
21+
$this->workflowApi = $workflowApi;
22+
}
23+
24+
public function onPullRequest(GitHubEvent $event)
25+
{
26+
$data = $event->getData();
27+
if (!in_array($data['action'], ['opened', 'reopened', 'synchronize'])) {
28+
return;
29+
}
30+
31+
$repository = $event->getRepository();
32+
$headRepository = $data['pull_request']['head']['repo']['full_name'];
33+
$headBranch = $data['pull_request']['head']['ref'];
34+
$this->workflowApi->approveWorkflowsForPullRequest($repository, $headRepository, $headBranch);
35+
36+
$event->setResponseData(['approved_run' => true]);
37+
}
38+
39+
public static function getSubscribedEvents()
40+
{
41+
return [
42+
GitHubEvents::PULL_REQUEST => 'onPullRequest',
43+
];
44+
}
45+
}

tests/Controller/WebhookControllerTest.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@ public function getTests()
6767
'On pull request opened' => [
6868
'pull_request',
6969
'pull_request.opened.json',
70-
['pull_request' => 3, 'status_change' => 'needs_review', 'pr_labels' => ['Console', 'Bug'], 'unsupported_branch' => '2.5'],
70+
['pull_request' => 3, 'status_change' => 'needs_review', 'pr_labels' => ['Console', 'Bug'], 'unsupported_branch' => '2.5', 'approved_run' => true],
7171
],
7272
'On draft pull request opened' => [
7373
'pull_request',
7474
'pull_request.opened_draft.json',
75-
['pull_request' => 3, 'draft_comment' => true],
75+
['pull_request' => 3, 'draft_comment' => true, 'approved_run' => true],
7676
],
7777
'On pull request draft to ready' => [
7878
'pull_request',
@@ -87,7 +87,7 @@ public function getTests()
8787
'On pull request opened with target branch' => [
8888
'pull_request',
8989
'pull_request.opened_target_branch.json',
90-
['pull_request' => 3, 'status_change' => 'needs_review', 'pr_labels' => ['Bug'], 'milestone' => '4.4'],
90+
['pull_request' => 3, 'status_change' => 'needs_review', 'pr_labels' => ['Bug'], 'milestone' => '4.4', 'approved_run' => true],
9191
],
9292
'On issue labeled bug' => [
9393
'issues',
@@ -102,7 +102,7 @@ public function getTests()
102102
'Welcome first users' => [
103103
'pull_request',
104104
'pull_request.new_contributor.json',
105-
['pull_request' => 4, 'status_change' => 'needs_review', 'pr_labels' => [], 'new_contributor' => true, 'squash_comment' => true],
105+
['pull_request' => 4, 'status_change' => 'needs_review', 'pr_labels' => [], 'new_contributor' => true, 'squash_comment' => true, 'approved_run' => true],
106106
],
107107
'Waiting Code Merge' => [
108108
'pull_request',

tests/webhook_examples/pull_request.opened.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
"repo": {
7171
"id": 21151556,
7272
"name": "symfony",
73-
"full_name": "carsonbot-playground/symfony",
73+
"full_name": "weaverryan/symfony",
7474
"owner": {
7575
"login": "weaverryan",
7676
"id": 121003,

0 commit comments

Comments
 (0)