mirror of
https://github.com/standardebooks/web.git
synced 2025-07-13 01:52:02 -04:00
Automatically update in progress projects to stalled
This commit is contained in:
parent
c7a4e34e31
commit
9b9d93bc52
6 changed files with 118 additions and 14 deletions
|
@ -21,6 +21,7 @@ parameters:
|
||||||
- %rootDir%/../../../scripts/process-pending-payments
|
- %rootDir%/../../../scripts/process-pending-payments
|
||||||
- %rootDir%/../../../scripts/update-ebook-database
|
- %rootDir%/../../../scripts/update-ebook-database
|
||||||
- %rootDir%/../../../scripts/update-patrons-circle
|
- %rootDir%/../../../scripts/update-patrons-circle
|
||||||
|
- %rootDir%/../../../scripts/update-project-commits
|
||||||
- %rootDir%/../../../templates
|
- %rootDir%/../../../templates
|
||||||
dynamicConstantNames:
|
dynamicConstantNames:
|
||||||
- SITE_STATUS
|
- SITE_STATUS
|
||||||
|
|
|
@ -12,5 +12,6 @@ CREATE TABLE IF NOT EXISTS `Projects` (
|
||||||
`Ended` datetime DEFAULT NULL,
|
`Ended` datetime DEFAULT NULL,
|
||||||
`ManagerUserId` int(11) NOT NULL,
|
`ManagerUserId` int(11) NOT NULL,
|
||||||
`ReviewerUserId` int(11) NOT NULL,
|
`ReviewerUserId` int(11) NOT NULL,
|
||||||
|
`LastCommitTimestamp` DATETIME NULL DEFAULT NULL,
|
||||||
PRIMARY KEY (`ProjectId`)
|
PRIMARY KEY (`ProjectId`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
|
|
|
@ -25,6 +25,7 @@ class Project{
|
||||||
public ?DateTimeImmutable $Ended = null;
|
public ?DateTimeImmutable $Ended = null;
|
||||||
public int $ManagerUserId;
|
public int $ManagerUserId;
|
||||||
public int $ReviewerUserId;
|
public int $ReviewerUserId;
|
||||||
|
public ?DateTimeImmutable $LastCommitTimestamp = null;
|
||||||
|
|
||||||
protected Ebook $_Ebook;
|
protected Ebook $_Ebook;
|
||||||
protected User $_ManagerUser;
|
protected User $_ManagerUser;
|
||||||
|
@ -160,7 +161,8 @@ class Project{
|
||||||
Started,
|
Started,
|
||||||
Ended,
|
Ended,
|
||||||
ManagerUserId,
|
ManagerUserId,
|
||||||
ReviewerUserId
|
ReviewerUserId,
|
||||||
|
LastCommitTimestamp
|
||||||
)
|
)
|
||||||
values
|
values
|
||||||
(
|
(
|
||||||
|
@ -175,9 +177,10 @@ class Project{
|
||||||
?,
|
?,
|
||||||
?,
|
?,
|
||||||
?,
|
?,
|
||||||
|
?,
|
||||||
?
|
?
|
||||||
)
|
)
|
||||||
', [$this->EbookId, $this->Status, $this->ProducerName, $this->ProducerEmail, $this->DiscussionUrl, $this->VcsUrl, NOW, NOW, $this->Started, $this->Ended, $this->ManagerUserId, $this->ReviewerUserId]);
|
', [$this->EbookId, $this->Status, $this->ProducerName, $this->ProducerEmail, $this->DiscussionUrl, $this->VcsUrl, NOW, NOW, $this->Started, $this->Ended, $this->ManagerUserId, $this->ReviewerUserId, $this->LastCommitTimestamp]);
|
||||||
|
|
||||||
$this->ProjectId = Db::GetLastInsertedId();
|
$this->ProjectId = Db::GetLastInsertedId();
|
||||||
}
|
}
|
||||||
|
@ -200,10 +203,11 @@ class Project{
|
||||||
Started = ?,
|
Started = ?,
|
||||||
Ended = ?,
|
Ended = ?,
|
||||||
ManagerUserId = ?,
|
ManagerUserId = ?,
|
||||||
ReviewerUserId = ?
|
ReviewerUserId = ?,
|
||||||
|
LastCommitTimestamp = ?
|
||||||
where
|
where
|
||||||
ProjectId = ?
|
ProjectId = ?
|
||||||
', [$this->Status, $this->ProducerName, $this->ProducerEmail, $this->DiscussionUrl, $this->VcsUrl, $this->Started, $this->Ended, $this->ManagerUserId, $this->ReviewerUserId, $this->ProjectId]);
|
', [$this->Status, $this->ProducerName, $this->ProducerEmail, $this->DiscussionUrl, $this->VcsUrl, $this->Started, $this->Ended, $this->ManagerUserId, $this->ReviewerUserId, $this->LastCommitTimestamp, $this->ProjectId]);
|
||||||
|
|
||||||
if($this->Status == Enums\ProjectStatusType::Abandoned){
|
if($this->Status == Enums\ProjectStatusType::Abandoned){
|
||||||
Db::Query('
|
Db::Query('
|
||||||
|
|
89
scripts/update-project-commits
Executable file
89
scripts/update-project-commits
Executable file
|
@ -0,0 +1,89 @@
|
||||||
|
#!/usr/bin/php
|
||||||
|
<?
|
||||||
|
require_once('/standardebooks.org/web/lib/Core.php');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate over all `Project`s that are in progress or stalled and get their latest GitHub commit. If the commit is more than 30 days old, mark the `Project` as stalled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use function Safe\curl_exec;
|
||||||
|
use function Safe\curl_getinfo;
|
||||||
|
use function Safe\curl_init;
|
||||||
|
use function Safe\curl_setopt;
|
||||||
|
use function Safe\file_get_contents;
|
||||||
|
use function Safe\json_decode;
|
||||||
|
use function Safe\preg_replace;
|
||||||
|
|
||||||
|
use Safe\DateTimeImmutable;
|
||||||
|
|
||||||
|
$apiToken = trim(file_get_contents('/standardebooks.org/config/secrets/se-vcs-bot@api.github.com'));
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'Accept: application/vnd.github+json',
|
||||||
|
'Authorization: Bearer ' . $apiToken,
|
||||||
|
'X-GitHub-Api-Version: 2022-11-28',
|
||||||
|
'User-Agent: Standard Ebooks' // Required by GitHub.
|
||||||
|
];
|
||||||
|
|
||||||
|
$projects = array_merge(
|
||||||
|
Project::GetAllByStatus(Enums\ProjectStatusType::InProgress),
|
||||||
|
Project::GetAllByStatus(Enums\ProjectStatusType::Stalled)
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach($projects as $project){
|
||||||
|
// First, we check if the repo has been renamed. If so, update the repo now.
|
||||||
|
$curl = curl_init($project->VcsUrl);
|
||||||
|
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, Enums\HttpMethod::Head->value); // Only perform HTTP HEAD.
|
||||||
|
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
||||||
|
curl_exec($curl);
|
||||||
|
|
||||||
|
$finalUrl = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
|
||||||
|
// Were we redirected?
|
||||||
|
if($finalUrl != $project->VcsUrl){
|
||||||
|
$project->VcsUrl = $finalUrl;
|
||||||
|
$project->Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now check the actual commits.
|
||||||
|
$url = preg_replace('|^https://github.com/|iu', 'https://api.github.com/repos/', $project->VcsUrl . '/commits');
|
||||||
|
|
||||||
|
$curl = curl_init($url);
|
||||||
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||||
|
|
||||||
|
try{
|
||||||
|
$response = curl_exec($curl);
|
||||||
|
/** @var int $httpCode */
|
||||||
|
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||||
|
|
||||||
|
if(!is_string($response)){
|
||||||
|
throw new Exception('Response from GitHub was not a string: ' . $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($httpCode != Enums\HttpCode::Ok->value){
|
||||||
|
throw new Exception('HTTP code from GitHub was: ' . $httpCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var array<stdClass> $commits */
|
||||||
|
$commits = json_decode($response);
|
||||||
|
|
||||||
|
if(sizeof($commits) > 0){
|
||||||
|
$project->LastCommitTimestamp = new DateTimeImmutable($commits[0]->commit->committer->date);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($project->LastCommitTimestamp !== null && $project->LastCommitTimestamp < new DateTimeImmutable('30 days ago')){
|
||||||
|
$project->Status = Enums\ProjectStatusType::Stalled;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// Revive previously-stalled `Project`s.
|
||||||
|
$project->Status = Enums\ProjectStatusType::InProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
$project->Save();
|
||||||
|
}
|
||||||
|
catch(Exception $ex){
|
||||||
|
Log::WriteErrorLogEntry('Error in update-project-commits for URL <' . $url . '>: ' . $ex->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$includeTitle = $includeTitle ?? true;
|
$includeTitle = $includeTitle ?? true;
|
||||||
|
$includeStatus = $includeStatus ?? true;
|
||||||
?>
|
?>
|
||||||
<table class="data-table">
|
<table class="data-table">
|
||||||
<caption aria-hidden="hidden">Scroll right →</caption>
|
<caption aria-hidden="hidden">Scroll right →</caption>
|
||||||
|
@ -12,9 +13,12 @@ $includeTitle = $includeTitle ?? true;
|
||||||
<? if($includeTitle){ ?>
|
<? if($includeTitle){ ?>
|
||||||
<th scope="col">Title</th>
|
<th scope="col">Title</th>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
<th scope="col">Started</th>
|
|
||||||
<th scope="col">Producer</th>
|
<th scope="col">Producer</th>
|
||||||
|
<th scope="col">Started</th>
|
||||||
|
<th scope="col">Last commit</th>
|
||||||
|
<? if($includeStatus){ ?>
|
||||||
<th scope="col">Status</th>
|
<th scope="col">Status</th>
|
||||||
|
<? } ?>
|
||||||
<th/>
|
<th/>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -26,9 +30,6 @@ $includeTitle = $includeTitle ?? true;
|
||||||
<a href="<?= $project->Ebook->Url ?>"><?= Formatter::EscapeHtml($project->Ebook->Title) ?></a>
|
<a href="<?= $project->Ebook->Url ?>"><?= Formatter::EscapeHtml($project->Ebook->Title) ?></a>
|
||||||
</td>
|
</td>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
<td>
|
|
||||||
<?= $project->Started->format(Enums\DateTimeFormat::ShortDate->value) ?>
|
|
||||||
</td>
|
|
||||||
<td class="producer">
|
<td class="producer">
|
||||||
<? if($project->ProducerEmail !== null){ ?>
|
<? if($project->ProducerEmail !== null){ ?>
|
||||||
<a href="mailto:<?= Formatter::EscapeHtml($project->ProducerEmail) ?>"><?= Formatter::EscapeHtml($project->ProducerName) ?></a>
|
<a href="mailto:<?= Formatter::EscapeHtml($project->ProducerEmail) ?>"><?= Formatter::EscapeHtml($project->ProducerName) ?></a>
|
||||||
|
@ -36,11 +37,19 @@ $includeTitle = $includeTitle ?? true;
|
||||||
<?= Formatter::EscapeHtml($project->ProducerName) ?>
|
<?= Formatter::EscapeHtml($project->ProducerName) ?>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<?= $project->LastCommitTimestamp?->format(Enums\DateTimeFormat::ShortDate->value) ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?= $project->Started->format(Enums\DateTimeFormat::ShortDate->value) ?>
|
||||||
|
</td>
|
||||||
|
<? if($includeStatus){ ?>
|
||||||
<td class="status">
|
<td class="status">
|
||||||
<?= ucfirst($project->Status->GetDisplayName()) ?>
|
<?= ucfirst($project->Status->GetDisplayName()) ?>
|
||||||
</td>
|
</td>
|
||||||
|
<? } ?>
|
||||||
<td>
|
<td>
|
||||||
<a href="<?= Formatter::EscapeHtml($project->VcsUrl) ?>">GitHub repo</a>
|
<a href="<?= Formatter::EscapeHtml($project->VcsUrl) ?>">GitHub</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
|
|
|
@ -27,12 +27,12 @@ catch(Exceptions\InvalidPermissionsException){
|
||||||
<i>None.</i>
|
<i>None.</i>
|
||||||
</p>
|
</p>
|
||||||
<? }else{ ?>
|
<? }else{ ?>
|
||||||
<?= Template::ProjectsTable(['projects' => $inProgressProjects]) ?>
|
<?= Template::ProjectsTable(['projects' => $inProgressProjects, 'includeStatus' => false]) ?>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
|
|
||||||
<? if(sizeof($stalledProjects) > 0){ ?>
|
<? if(sizeof($stalledProjects) > 0){ ?>
|
||||||
<h2>Stalled projects</h2>
|
<h2>Stalled projects</h2>
|
||||||
<?= Template::ProjectsTable(['projects' => $stalledProjects]) ?>
|
<?= Template::ProjectsTable(['projects' => $stalledProjects, 'includeStatus' => false]) ?>
|
||||||
<? } ?>
|
<? } ?>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue