Skip to content

Commit

Permalink
Track source of a package update, refs #1490
Browse files Browse the repository at this point in the history
  • Loading branch information
Seldaek committed Dec 10, 2024
1 parent a624697 commit b1cc627
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 10 deletions.
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ parameters:
PackageSource: 'array{url: string|null, type: string|null, reference: string|null}|null'

AnyJob: 'array<string, bool|int|string>'
PackageUpdateJob: 'array{id: int, update_equal_refs: bool, delete_before: bool, force_dump: bool}'
PackageUpdateJob: 'array{id: int, update_equal_refs: bool, delete_before: bool, force_dump: bool, source: string}'
GitHubUserMigrateJob: 'array{id: int, old_scope: string, new_scope: string}'
SecurityAdvisoryJob: 'array{source: string}'

Expand Down
2 changes: 1 addition & 1 deletion src/Command/UpdatePackagesCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$idsGroup = array_splice($ids, 0, 100);

foreach ($idsGroup as $id) {
$job = $this->scheduler->scheduleUpdate($id, $updateEqualRefs, $deleteBefore, $randomTimes ? new \DateTime('+'.random_int(1, 600).'seconds') : null);
$job = $this->scheduler->scheduleUpdate($id, 'update cmd', $updateEqualRefs, $deleteBefore, $randomTimes ? new \DateTime('+'.random_int(1, 600).'seconds') : null);
if ($verbose) {
$output->writeln('Scheduled update job '.$job->getId().' for package '.$id);
}
Expand Down
17 changes: 12 additions & 5 deletions src/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ protected function receiveUpdateRequest(Request $request, string $url, string $u
$user = null;
$autoUpdated = Package::AUTO_MANUAL_HOOK;
$receiveType = 'manual';
$source = 'unknown';

// manual hook set up with user API token as secret
if ($match['host'] === 'github.com' && $request->getContent() && $request->query->has('username') && $request->headers->has('X-Hub-Signature')) {
Expand All @@ -428,8 +429,9 @@ protected function receiveUpdateRequest(Request $request, string $url, string $u
if ($sig && $user && $user->isEnabled()) {
[$algo, $sig] = explode('=', $sig);
$expected = hash_hmac($algo, $request->getContent(), $user->getApiToken());
$source = 'manual_github_hook';
if (hash_equals($expected, $sig)) {
$packages = $this->findGitHubPackagesByRepository($match['path'], (string) $remoteId, $user);
$packages = $this->findGitHubPackagesByRepository($match['path'], (string) $remoteId, $source, $user);
$autoUpdated = Package::AUTO_GITHUB_HOOK;
$receiveType = 'github_user_secret';
} else {
Expand All @@ -443,15 +445,20 @@ protected function receiveUpdateRequest(Request $request, string $url, string $u
if (!$user) {
// find the user
$user = $this->findUser($request, ApiType::Safe);
if ($user) {
$source = 'manual_hook ('.$user->getUsername().' @ '.$request->getPathInfo().')';
}
}

if (!$user && $match['host'] === 'github.com' && $request->getContent()) {
$sig = $request->headers->get('X-Hub-Signature');
if ($sig) {
[$algo, $sig] = explode('=', $sig);
$expected = hash_hmac($algo, $request->getContent(), $githubWebhookSecret);
$source = 'github_official_hook';

if (hash_equals($expected, $sig)) {
$packages = $this->findGitHubPackagesByRepository($match['path'], (string) $remoteId);
$packages = $this->findGitHubPackagesByRepository($match['path'], (string) $remoteId, $source);
$autoUpdated = Package::AUTO_GITHUB_HOOK;
$receiveType = 'github_auto';
}
Expand All @@ -477,7 +484,7 @@ protected function receiveUpdateRequest(Request $request, string $url, string $u
foreach ($packages as $package) {
$package->setAutoUpdated($autoUpdated);

$job = $this->scheduler->scheduleUpdate($package);
$job = $this->scheduler->scheduleUpdate($package, $source);
$jobs[] = $job->getId();
}

Expand Down Expand Up @@ -566,7 +573,7 @@ protected function findPackagesByUrl(User $user, string $url, string $urlRegex,
* @param User|null $user If provided it means the request came with a user's API token and not the packagist-configured secret, so we cannot be sure it is a request coming directly from github
* @return Package[] the packages found
*/
protected function findGitHubPackagesByRepository(string $path, string $remoteId, ?User $user = null): array
protected function findGitHubPackagesByRepository(string $path, string $remoteId, string $source, ?User $user = null): array
{
$url = 'https://github.com/'.$path;

Expand Down Expand Up @@ -617,7 +624,7 @@ protected function findGitHubPackagesByRepository(string $path, string $remoteId
$package->setRepository($url);
if ($url !== $previousUrl) {
// ensure we do a full update of all versions to update the repo URL
$this->scheduler->scheduleUpdate($package, updateEqualRefs: true, forceDump: true);
$this->scheduler->scheduleUpdate($package, $source, updateEqualRefs: true, forceDump: true);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Controller/PackageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ public function updatePackageAction(Request $req, string $name, #[CurrentUser] U
}

if ($update) {
$job = $this->scheduler->scheduleUpdate($package, $updateEqualRefs, false, null, $manualUpdate);
$job = $this->scheduler->scheduleUpdate($package, 'button/api', $updateEqualRefs, false, null, $manualUpdate);

return new JsonResponse(['status' => 'success', 'job' => $job->getId()], 202);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Service/Scheduler.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function __construct(
* @param Package|int $packageOrId
* @return Job<PackageUpdateJob>
*/
public function scheduleUpdate($packageOrId, bool $updateEqualRefs = false, bool $deleteBefore = false, ?\DateTimeInterface $executeAfter = null, bool $forceDump = false): Job
public function scheduleUpdate($packageOrId, string $source, bool $updateEqualRefs = false, bool $deleteBefore = false, ?\DateTimeInterface $executeAfter = null, bool $forceDump = false): Job
{
if ($packageOrId instanceof Package) {
$packageOrId = $packageOrId->getId();
Expand Down Expand Up @@ -60,7 +60,7 @@ public function scheduleUpdate($packageOrId, bool $updateEqualRefs = false, bool
$this->getEM()->flush();
}

return $this->createJob('package:updates', ['id' => $packageOrId, 'update_equal_refs' => $updateEqualRefs, 'delete_before' => $deleteBefore, 'force_dump' => $forceDump], $packageOrId, $executeAfter);
return $this->createJob('package:updates', ['id' => $packageOrId, 'update_equal_refs' => $updateEqualRefs, 'delete_before' => $deleteBefore, 'force_dump' => $forceDump, 'source' => $source], $packageOrId, $executeAfter);
}

/**
Expand Down

0 comments on commit b1cc627

Please sign in to comment.