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
9 changes: 6 additions & 3 deletions src/VCS/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,16 @@ public function validateWebhookEvent(string $payload, string $signature, string
}

/**
* Parses webhook event payload
* Parses a webhook delivery into the events it describes.
*
* A delivery usually describes one event, but some providers batch
* several into one -- Bitbucket reports every ref a push touched.
*
* @param string $event Type of event: push, pull_request etc
* @param string $payload The webhook payload received from Git provider
* @return array<mixed> Parsed payload as a json object
* @return array<array<mixed>> Parsed payloads as json objects
*/
abstract public function getEvent(string $event, string $payload): array;
abstract public function getEvents(string $event, string $payload): array;

/**
* HTTP header name carrying the webhook event type (e.g. 'x-github-event').
Expand Down
16 changes: 8 additions & 8 deletions src/VCS/Adapter/Git/GitHub.php
Original file line number Diff line number Diff line change
Expand Up @@ -1291,9 +1291,9 @@ public function getFileUrl(string $owner, string $repositoryName, string $refere
*
* @param string $event Type of event: push, pull_request etc
* @param string $payload The webhook payload received from GitHub
* @return array<mixed> Parsed payload as a json object
* @return array<array<mixed>> Parsed payloads as json objects
*/
public function getEvent(string $event, string $payload): array
public function getEvents(string $event, string $payload): array
{
$payload = json_decode($payload, true);

Expand Down Expand Up @@ -1344,7 +1344,7 @@ public function getEvent(string $event, string $payload): array
}
}

return [
return [[
'branchCreated' => $branchCreated,
'branchDeleted' => $branchDeleted,
'branch' => $branch,
Expand All @@ -1365,7 +1365,7 @@ public function getEvent(string $event, string $payload): array
'pullRequestNumber' => '',
'action' => '',
'affectedFiles' => \array_keys($affectedFiles),
];
]];
case 'pull_request':
$payloadRepository = $payload['repository'] ?? [];
$payloadRepositoryOwner = $payloadRepository['owner'] ?? [];
Expand Down Expand Up @@ -1393,7 +1393,7 @@ public function getEvent(string $event, string $payload): array
$baseLogin = $payloadPullRequestBaseUser['login'] ?? '';
$external = $headLogin !== $baseLogin;

return [
return [[
'branch' => $branch,
'branchUrl' => $branchUrl,
'repositoryId' => $repositoryId,
Expand All @@ -1408,7 +1408,7 @@ public function getEvent(string $event, string $payload): array
'external' => $external,
'pullRequestNumber' => $pullRequestNumber,
'action' => $action,
];
]];
case 'installation':
case 'installation_repositories':
$payloadInstallation = $payload['installation'] ?? [];
Expand All @@ -1417,11 +1417,11 @@ public function getEvent(string $event, string $payload): array
$action = $payload['action'] ?? '';
$userName = $payloadInstallationAccount['login'] ?? '';

return [
return [[
'action' => $action,
'installationId' => $installationId,
'userName' => $userName,
];
]];
}

return [];
Expand Down
10 changes: 5 additions & 5 deletions src/VCS/Adapter/Git/GitLab.php
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ public function generateCloneCommand(string $owner, string $repositoryName, stri
'merge' => 'closed',
];

public function getEvent(string $event, string $payload): array
public function getEvents(string $event, string $payload): array
{
$payloadArray = json_decode($payload, true);
if ($payloadArray === null || !is_array($payloadArray)) {
Expand Down Expand Up @@ -1082,7 +1082,7 @@ public function getEvent(string $event, string $payload): array

$allZeroSha = str_repeat('0', 40);

return [
return [[
'branchCreated' => ($payloadArray['before'] ?? '') === $allZeroSha,
'branchDeleted' => ($payloadArray['after'] ?? '') === $allZeroSha,
'branch' => $branch,
Expand All @@ -1103,7 +1103,7 @@ public function getEvent(string $event, string $payload): array
'pullRequestNumber' => '',
'action' => '',
'affectedFiles' => \array_keys($affectedFiles),
];
]];

case 'Merge Request Hook':
$project = $payloadArray['project'] ?? [];
Expand All @@ -1121,7 +1121,7 @@ public function getEvent(string $event, string $payload): array
$external = isset($mr['source_project_id'], $mr['target_project_id'])
&& $mr['source_project_id'] !== $mr['target_project_id'];

return [
return [[
'branch' => $branch,
'branchUrl' => $branchUrl,
'repositoryId' => $repositoryId,
Expand All @@ -1136,7 +1136,7 @@ public function getEvent(string $event, string $payload): array
'external' => $external,
'pullRequestNumber' => $mr['iid'] ?? '',
'action' => $action,
];
]];

default:
return [];
Expand Down
10 changes: 5 additions & 5 deletions src/VCS/Adapter/Git/Gitea.php
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,7 @@ public function generateCloneCommand(string $owner, string $repositoryName, stri
* @param string $payload The webhook payload received from Gitea
* @return array<mixed> Parsed payload as an array
*/
public function getEvent(string $event, string $payload): array
public function getEvents(string $event, string $payload): array
{
$payload = json_decode($payload, true);

Expand Down Expand Up @@ -1166,7 +1166,7 @@ public function getEvent(string $event, string $payload): array
}
}

return [
return [[
'branchCreated' => $branchCreated,
'branchDeleted' => $branchDeleted,
'branch' => $branch,
Expand All @@ -1187,7 +1187,7 @@ public function getEvent(string $event, string $payload): array
'pullRequestNumber' => '',
'action' => '',
'affectedFiles' => \array_keys($affectedFiles),
];
]];

case 'pull_request':
$payloadRepository = $payload['repository'] ?? [];
Expand Down Expand Up @@ -1217,7 +1217,7 @@ public function getEvent(string $event, string $payload): array
$baseRepoFullName = $payloadRepository['full_name'] ?? '';
$external = !empty($headRepoFullName) && !empty($baseRepoFullName) && $headRepoFullName !== $baseRepoFullName;

return [
return [[
'branch' => $branch,
'branchUrl' => $branchUrl,
'repositoryId' => $repositoryId,
Expand All @@ -1232,7 +1232,7 @@ public function getEvent(string $event, string $payload): array
'external' => $external,
'pullRequestNumber' => $pullRequestNumber,
'action' => $action,
];
]];
}

return [];
Expand Down
5 changes: 4 additions & 1 deletion tests/VCS/Adapter/GitHubTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ public function testGetEventInstallation(): void
$this->fail('Failed to encode JSON payload');
}

$result = $this->vcsAdapter->getEvent('installation', $payload);
$events = $this->vcsAdapter->getEvents('installation', $payload);
$this->assertIsArray($events);
$this->assertCount(1, $events);
$result = $events[0];

$this->assertSame('deleted', $result['action']);
$this->assertSame('1234', $result['installationId']);
Expand Down
10 changes: 8 additions & 2 deletions tests/VCS/Adapter/GitLabTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,10 @@ public function testGetEventPushMatchesCheckoutSha(): void
$this->fail('Failed to encode JSON payload');
}

$result = $this->vcsAdapter->getEvent('Push Hook', $payload);
$events = $this->vcsAdapter->getEvents('Push Hook', $payload);
$this->assertIsArray($events);
$this->assertCount(1, $events);
$result = $events[0];

$this->assertIsArray($result);
$this->assertSame('def456', $result['commitHash']);
Expand All @@ -181,7 +184,10 @@ public function testGetEventPullRequestActionMapping(): void
$this->fail('Failed to encode JSON payload');
}

$result = $this->vcsAdapter->getEvent('Merge Request Hook', $payload);
$events = $this->vcsAdapter->getEvents('Merge Request Hook', $payload);
$this->assertIsArray($events);
$this->assertCount(1, $events);
$result = $events[0];
$this->assertSame($mapped, $result['action'], "native action '{$native}' should map to '{$mapped}'");
}
}
Expand Down
35 changes: 27 additions & 8 deletions tests/VCS/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -1556,7 +1556,11 @@ protected function awaitWebhook(string $eventName, string $secret): array
'Webhook signature did not validate'
);

return $this->vcsAdapter->getEvent($eventName, $payload);
$events = $this->vcsAdapter->getEvents($eventName, $payload);
$this->assertIsArray($events);
$this->assertCount(1, $events);

return $events[0];
}

public function testValidateWebhookEvent(): void
Expand Down Expand Up @@ -2312,10 +2316,13 @@ public function testGetRepositoryAfterDeleteFails(): void

public function testGetEventPush(): void
{
$result = $this->vcsAdapter->getEvent(
$events = $this->vcsAdapter->getEvents(
static::$pushEventName,
$this->pushPayload(static::$defaultBranch, ['file1.txt'], ['file2.txt'], ['file3.txt'])
);
$this->assertIsArray($events);
$this->assertCount(1, $events);
$result = $events[0];

$this->assertSame(static::$defaultBranch, $result['branch']);
$this->assertSame(self::EVENT_REPOSITORY_ID, $result['repositoryId']);
Expand All @@ -2335,29 +2342,38 @@ public function testGetEventPush(): void

public function testGetEventPushDetectsBranchCreated(): void
{
$result = $this->vcsAdapter->getEvent(
$events = $this->vcsAdapter->getEvents(
static::$pushEventName,
$this->pushPayload(static::$defaultBranch, created: true)
);
$this->assertIsArray($events);
$this->assertCount(1, $events);
$result = $events[0];

$this->assertTrue($result['branchCreated']);
$this->assertFalse($result['branchDeleted']);
}

public function testGetEventPushDetectsBranchDeleted(): void
{
$result = $this->vcsAdapter->getEvent(
$events = $this->vcsAdapter->getEvents(
static::$pushEventName,
$this->pushPayload(static::$defaultBranch, deleted: true)
);
$this->assertIsArray($events);
$this->assertCount(1, $events);
$result = $events[0];

$this->assertFalse($result['branchCreated']);
$this->assertTrue($result['branchDeleted']);
}

public function testGetEventPullRequest(): void
{
$result = $this->vcsAdapter->getEvent(static::$pullRequestEventName, $this->pullRequestPayload());
$events = $this->vcsAdapter->getEvents(static::$pullRequestEventName, $this->pullRequestPayload());
$this->assertIsArray($events);
$this->assertCount(1, $events);
$result = $events[0];

$this->assertSame('opened', $result['action']);
$this->assertSame(self::EVENT_HEAD_BRANCH, $result['branch']);
Expand All @@ -2371,15 +2387,18 @@ public function testGetEventPullRequest(): void

public function testGetEventPullRequestDetectsExternal(): void
{
$result = $this->vcsAdapter->getEvent(static::$pullRequestEventName, $this->pullRequestPayload(external: true));
$events = $this->vcsAdapter->getEvents(static::$pullRequestEventName, $this->pullRequestPayload(external: true));
$this->assertIsArray($events);
$this->assertCount(1, $events);
$result = $events[0];

$this->assertTrue($result['external']);
}

public function testGetEventInvalidPayload(): void
{
$this->expectException(Exception::class);
$this->vcsAdapter->getEvent('push', 'invalid json');
$this->vcsAdapter->getEvents('push', 'invalid json');
}

public function testGetEventUnsupportedEvent(): void
Expand All @@ -2390,7 +2409,7 @@ public function testGetEventUnsupportedEvent(): void
$this->fail('Failed to encode JSON payload');
}

$result = $this->vcsAdapter->getEvent('unsupported_event', $payload);
$result = $this->vcsAdapter->getEvents('unsupported_event', $payload);

$this->assertIsArray($result);
$this->assertEmpty($result);
Expand Down
Loading