Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ APP_SECRET=5dd8ffca252d95e8b4fb5b2d15310e92

SYMFONY_DOCS_SECRET=''
SYMFONY_SECRET=''
BOT_USERNAME='carsonbot-test'
BOT_USERNAME='carsonbot'
###> knplabs/github-api ###
#GITHUB_TOKEN=XXX
###< knplabs/github-api ###
Expand Down
93 changes: 93 additions & 0 deletions .github/workflows/find-reviewer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Find Reviewer

on:
repository_dispatch:
types: [find-reviewer]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean this workflow is called each time a find-reviewer webhooks is received? Can you help me understand how this works? thx :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@stof stof Nov 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I've defined a special event id called find-reviewer. In the GithubPullRequestApi::findReviewer() that @stof linked, I am dispatching this special event.

It is basically me saying: "Hey start the specific CI job called find-reviewer".


jobs:
find:
name: Search
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Create path
run: mkdir -p build/reviewer

- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: composer-${{ runner.os }}-7.4-${{ hashFiles('composer.*') }}
restore-keys: |
composer-${{ runner.os }}-7.4-
composer-${{ runner.os }}-
composer-

- name: Download dependencies
run: composer install --no-interaction --optimize-autoloader

- name: Cache dependencies
uses: actions/cache@v2
with:
path: build/reviewer/var
key: nyholm-git-reviewer

- name: Checkout GitReviewer repo
run: |
mkdir -p build/reviewer/var
mv build/reviewer/var build/reviewer_tmp
composer create-project nyholm/git-reviewer build/reviewer
mv build/reviewer_tmp build/reviewer/var

- name: Download dependencies
run: |
cd build/reviewer
composer update --no-interaction --prefer-dist --optimize-autoloader --prefer-stable

- name: Checkout target repo
id: target-repo
run: |
git clone https://github.com/${{ github.event.client_payload.repository }} build/target/${{ github.event.client_payload.repository }}
echo "::set-output name=dir::$(pwd)/build/target/${{ github.event.client_payload.repository }}"

- name: Find branch base
id: target-base
run: |
cd build/reviewer
BASE=$(./git-reviewer.php pull-request:base ${{ github.event.client_payload.pull_request_number }} ${{ steps.target-repo.outputs.dir }})
echo "::set-output name=branch::$BASE"

- name: Checkout branch base
run: |
cd ${{ steps.target-repo.outputs.dir }}
echo ${{ steps.target-base.outputs.branch }}
git pull
git checkout ${{ steps.target-base.outputs.branch }}

- name: Find reviwers
env:
GITHUB_TOKEN: ${{ secrets.CARSONPROD_GITHUB_TOKEN }}
run: |
cd build/reviewer
./git-reviewer.php find ${{ github.event.client_payload.pull_request_number }} ${{ steps.target-repo.outputs.dir }} \
--after `date +%Y-%m-%d --date="2 year ago"` \
--ignore-path "src/Symfony/FrameworkBundle/*" \
--ignore-path "src/Symfony/Bundle/FrameworkBundle/*" \
--ignore-path "src/**/Tests/*" \
--ignore-path CHANGELOG*.md \
--ignore-path UPGRADE*.md \
--pretty-print > output.json

cat output.json

- name: Write comment
env:
GITHUB_TOKEN: ${{ secrets.CARSONPROD_GITHUB_TOKEN }}
run: bin/console app:review:suggest ${{ github.event.client_payload.repository }} ${{ github.event.client_payload.pull_request_number }} ${{ github.event.client_payload.type }} `pwd`/build/reviewer/output.json
4 changes: 3 additions & 1 deletion config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ parameters:
- 'App\Subscriber\StatusChangeByReviewSubscriber'
- 'App\Subscriber\NeedsReviewNewPRSubscriber'
- 'App\Subscriber\BugLabelNewIssueSubscriber'
- 'App\Subscriber\FindReviewerSubscriber'
- 'App\Subscriber\AutoLabelFromContentSubscriber'
- 'App\Subscriber\MilestoneNewPRSubscriber'
- 'App\Subscriber\WelcomeFirstTimeContributorSubscriber'
Expand All @@ -23,6 +24,7 @@ parameters:
- 'App\Subscriber\StatusChangeByReviewSubscriber'
- 'App\Subscriber\NeedsReviewNewPRSubscriber'
- 'App\Subscriber\BugLabelNewIssueSubscriber'
- 'App\Subscriber\FindReviewerSubscriber'
- 'App\Subscriber\AutoLabelFromContentSubscriber'
- 'App\Subscriber\UnsupportedBranchSubscriber'
- 'subscriber.symfony_docs.milestone'
Expand All @@ -39,6 +41,7 @@ parameters:
- 'App\Subscriber\StatusChangeByReviewSubscriber'
- 'App\Subscriber\NeedsReviewNewPRSubscriber'
- 'App\Subscriber\BugLabelNewIssueSubscriber'
- 'App\Subscriber\FindReviewerSubscriber'
- 'App\Subscriber\AutoLabelFromContentSubscriber'
- 'App\Subscriber\MilestoneNewPRSubscriber'
- 'App\Subscriber\WelcomeFirstTimeContributorSubscriber'
Expand All @@ -51,7 +54,6 @@ services:
_defaults:
autowire: true
autoconfigure: true

bind:
string $botUsername: '%env(BOT_USERNAME)%'

Expand Down
55 changes: 53 additions & 2 deletions src/Api/Issue/GithubIssueApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,27 @@
use App\Model\Repository;
use Github\Api\Issue;
use Github\Api\Issue\Comments;
use Github\Api\Issue\Timeline;
use Github\Api\PullRequest\Review;
use Github\Api\Search;
use Github\Exception\RuntimeException;

class GithubIssueApi implements IssueApi
{
private $issueCommentApi;
private $botUsername;
private $reviewApi;
private $issueApi;
private $searchApi;
private $timelineApi;
private $botUsername;

public function __construct(Comments $issueCommentApi, Issue $issueApi, Search $searchApi, string $botUsername)
public function __construct(Comments $issueCommentApi, Review $reviewApi, Issue $issueApi, Search $searchApi, Timeline $timelineApi, string $botUsername)
{
$this->issueCommentApi = $issueCommentApi;
$this->reviewApi = $reviewApi;
$this->issueApi = $issueApi;
$this->searchApi = $searchApi;
$this->timelineApi = $timelineApi;
$this->botUsername = $botUsername;
}

Expand Down Expand Up @@ -52,6 +59,31 @@ public function lastCommentWasMadeByBot(Repository $repository, $number): bool
return $this->botUsername === ($lastComment['user']['login'] ?? null);
}

/**
* Has this PR or issue comments/reviews from others than the author?
*/
public function hasActivity(Repository $repository, $number): bool
{
$issue = $this->issueApi->show($repository->getVendor(), $repository->getName(), $number);
$author = $issue['user']['login'] ?? null;

try {
$reviewComments = $this->reviewApi->all($repository->getVendor(), $repository->getName(), $number);
} catch (RuntimeException $e) {
// This was not a PR =)
$reviewComments = [];
}

$all = array_merge($reviewComments, $this->issueCommentApi->all($repository->getVendor(), $repository->getName(), $number));
foreach ($all as $comment) {
if (!in_array($comment['user']['login'], [$author, $this->botUsername])) {
return true;
}
}

return false;
}

public function show(Repository $repository, $issueNumber): array
{
return $this->issueApi->show($repository->getVendor(), $repository->getName(), $issueNumber);
Expand Down Expand Up @@ -81,4 +113,23 @@ public function findStaleIssues(Repository $repository, \DateTimeImmutable $noUp

return $issues['items'] ?? [];
}

public function getUsers(Repository $repository, $issueNumber): array
{
$timeline = $this->timelineApi->all($repository->getVendor(), $repository->getName(), $issueNumber);
$users = [];
foreach ($timeline as $event) {
$users[] = $event['actor']['login'] ?? $event['user']['login'] ?? $event['author']['email'] ?? '';
if (isset($event['body'])) {
// Parse body for user reference
if (preg_match_all('|@([a-zA-z_\-0-9]+)|', $event['body'], $matches)) {
foreach ($matches[1] as $match) {
$users[] = $match;
}
}
}
}

return array_map(function ($a) { return strtolower($a); }, array_unique($users));
}
}
7 changes: 7 additions & 0 deletions src/Api/Issue/IssueApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public function show(Repository $repository, $issueNumber): array;

public function commentOnIssue(Repository $repository, $issueNumber, string $commentBody);

public function hasActivity(Repository $repository, $number): bool;

public function lastCommentWasMadeByBot(Repository $repository, $number): bool;

public function findStaleIssues(Repository $repository, \DateTimeImmutable $noUpdateAfter): array;
Expand All @@ -29,4 +31,9 @@ public function findStaleIssues(Repository $repository, \DateTimeImmutable $noUp
* Close an issue or a pull request.
*/
public function close(Repository $repository, $issueNumber);

/**
* Get users active or mentioned in this issue/pull request.
*/
public function getUsers(Repository $repository, $issueNumber): array;
}
10 changes: 10 additions & 0 deletions src/Api/Issue/NullIssueApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public function commentOnIssue(Repository $repository, $issueNumber, string $com
{
}

public function hasActivity(Repository $repository, $number): bool
{
return false;
}

public function lastCommentWasMadeByBot(Repository $repository, $number): bool
{
return false;
Expand All @@ -32,4 +37,9 @@ public function findStaleIssues(Repository $repository, \DateTimeImmutable $noUp
public function close(Repository $repository, $issueNumber)
{
}

public function getUsers(Repository $repository, $issueNumber): array
{
return [];
}
}
32 changes: 32 additions & 0 deletions src/Api/Issue/StdErrIssueApi.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Api\Issue;

use App\Model\Repository;

/**
* This will not write to Github, only output to STDERR. But it will try to read from Github.
*
* @author Tobias Nyholm <[email protected]>
*/
class StdErrIssueApi extends GithubIssueApi
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is never used. But it was really useful when testing/debugging, so I kept it in the PR.

{
public function open(Repository $repository, string $title, string $body, array $labels)
{
error_log(sprintf('Open new issue on %s', $repository->getFullName()));
error_log('Title: '.$title);
error_log('Labels: '.json_encode($labels));
error_log($body);
}

public function close(Repository $repository, $issueNumber)
{
error_log(sprintf('Closing %s#%d', $repository->getFullName(), $issueNumber));
}

public function commentOnIssue(Repository $repository, $issueNumber, string $commentBody)
{
error_log(sprintf('Commenting on %s#%d', $repository->getFullName(), $issueNumber));
error_log($commentBody);
}
}
Loading