Skip to content

Commit 8ad7054

Browse files
committed
Close stale issues
1 parent 541ad5e commit 8ad7054

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

config/services.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ services:
6868
Github\Api\Search:
6969
factory: ['@Github\Client', api]
7070
arguments: [search]
71+
calls:
72+
- ['setPerPage', [100]]
7173

7274
Github\Api\Issue\Labels:
7375
factory: ['@Github\Api\Issue', labels]

src/Api/Issue/GithubIssueApi.php

+7
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,11 @@ public function commentOnIssue(Repository $repository, $issueNumber, string $com
6161
['body' => $commentBody]
6262
);
6363
}
64+
65+
public function findStaleIssues(Repository $repository, \DateTimeImmutable $noUpdateAfter)
66+
{
67+
$issues = $this->searchApi->issues(sprintf('repo:%s is:issue -linked:pr -label:"Keep open" is:open updated:<%s', $repository->getFullName(), $noUpdateAfter->format('Y-m-d')));
68+
69+
return $issues['items'] ?? [];
70+
}
6471
}
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
namespace App\Command;
4+
5+
use App\Api\Issue\IssueApi;
6+
use App\Service\RepositoryProvider;
7+
use Symfony\Component\Console\Command\Command;
8+
use Symfony\Component\Console\Input\InputArgument;
9+
use Symfony\Component\Console\Input\InputInterface;
10+
use Symfony\Component\Console\Output\OutputInterface;
11+
12+
/**
13+
* Close issues not been updated in a long while
14+
*
15+
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
16+
*/
17+
class CloseStaleIssuesCommand extends Command
18+
{
19+
protected static $defaultName = 'app:issue:close-stale';
20+
private $repositoryProvider;
21+
private $issueApi;
22+
23+
public function __construct(RepositoryProvider $repositoryProvider, IssueApi $issueApi)
24+
{
25+
parent::__construct();
26+
$this->repositoryProvider = $repositoryProvider;
27+
$this->issueApi = $issueApi;
28+
}
29+
30+
protected function configure()
31+
{
32+
$this->addArgument('repository', InputArgument::REQUIRED, 'The full name to the repository, eg symfony/symfony-docs');
33+
}
34+
35+
protected function execute(InputInterface $input, OutputInterface $output)
36+
{
37+
/** @var string $repositoryName */
38+
$repositoryName = $input->getArgument('repository');
39+
$repository = $this->repositoryProvider->getRepository($repositoryName);
40+
if (null === $repository) {
41+
$output->writeln('Repository not configured');
42+
return 1;
43+
}
44+
45+
$notUpdatedAfter = new \DateTimeImmutable('-3months');
46+
$issues = $this->issueApi->findStaleIssues($repository, $notUpdatedAfter);
47+
48+
foreach ($issues as $issue) {
49+
$this->issueApi->commentOnIssue($repository, $issue['number'], <<<TXT
50+
Hey,
51+
52+
Is this issue still relevant? It has not been any activity in a while. I will close this if nobody makes a comment soon.
53+
54+
Cheers!
55+
56+
Carsonbot
57+
TXT
58+
);
59+
60+
// TODO add a scheduled task to process this issue again after 2 weeks
61+
}
62+
63+
return 0;
64+
}
65+
}

src/Service/RepositoryProvider.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
*/
1010
class RepositoryProvider
1111
{
12+
/**
13+
* @var Repository[]
14+
*/
1215
private $repositories = [];
1316

1417
public function __construct(array $repositories)
@@ -28,14 +31,17 @@ public function __construct(array $repositories)
2831
}
2932
}
3033

31-
public function getRepository($repositoryName)
34+
public function getRepository($repositoryName): ?Repository
3235
{
3336
$repository = strtolower($repositoryName);
3437

3538
return $this->repositories[$repository] ?? null;
3639
}
3740

38-
public function getAllRepositories()
41+
/**
42+
* @return Repository[]
43+
*/
44+
public function getAllRepositories(): array
3945
{
4046
return array_values($this->repositories);
4147
}

0 commit comments

Comments
 (0)