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
3 changes: 2 additions & 1 deletion inc/Loader/Git.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ public function download(): ?string {
* @since 4.0.0
*
* @param string $branch Name of the Git branch to clone. Empty string clones the default branch.
* @param \Required\Traduttore\Repository $repository Full repository instance.
*/
$branch = apply_filters( 'traduttore.git_clone_branch', '' );
$branch = apply_filters( 'traduttore.git_clone_branch', '', $this->repository );
if ( '' !== $branch ) {
$cmd .= ' --branch ' . escapeshellarg( $branch );
}
Expand Down
32 changes: 32 additions & 0 deletions inc/WebhookHandler/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
namespace Required\Traduttore\WebhookHandler;

use Required\Traduttore\Project;
use Required\Traduttore\ProjectLocator;
use Required\Traduttore\WebhookHandler;
use WP_REST_Request;
use WP_REST_Response;

/**
* Base webhook handler class.
Expand Down Expand Up @@ -85,4 +87,34 @@ protected function get_secret( ?Project $project = null ): ?string {
*/
return apply_filters( 'traduttore.webhook_secret', $secret, $this, $project );
}

/**
* Return a valid project or errors. Allows to customize the pulled branch.
*
* @param string $repository Metadata to find a GlotPress project.
* @param string $default_branch Name of the repository's default branch.
* @param string $ref Name of the received branch through the webhook.
* @return \Required\Traduttore\Project|\WP_REST_Response|\WP_Error
*/
protected function resolve_project( string $repository, string $default_branch = '', string $ref = '' ): Project|WP_REST_Response|\WP_Error {
$locator = new ProjectLocator( $repository );
$project = $locator->get_project();

if ( ! $project ) {
return new \WP_Error( '404', 'Could not find project for this repository', [ 'status' => 404 ] );
}

if ( empty( $default_branch ) || empty( $ref ) ) {
return $project;
}

$branch = 'refs/heads/' . (string) apply_filters( 'traduttore.git_clone_branch', $default_branch, $project->get_repository_name() );

// We only care about the default or custom branch but don't want to send an error still.
if ( $branch !== $ref ) {
return new WP_REST_Response( [ 'result' => 'Not the default or custom branch' ] );
}

return $project;
}
}
11 changes: 6 additions & 5 deletions inc/WebhookHandler/Bitbucket.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Required\Traduttore\WebhookHandler;

use Required\Traduttore\Project;
use Required\Traduttore\ProjectLocator;
use Required\Traduttore\Repository;
use Required\Traduttore\Updater;
Expand Down Expand Up @@ -79,20 +80,20 @@ public function callback(): \WP_Error|\WP_REST_Response {
* @var array{repository: array{scm: string, full_name: string, links: array{html: array{href: string}}, is_private: bool}} $params
*/
$params = $this->request->get_params();
$href = (string) $params['repository']['links']['html']['href'];

$locator = new ProjectLocator( $params['repository']['links']['html']['href'] );
$project = $locator->get_project();
$project = $this->resolve_project( $href );

if ( ! $project ) {
return new \WP_Error( '404', 'Could not find project for this repository' );
if ( ! $project instanceof Project ) {
return $project;
}

if ( ! $project->get_repository_vcs_type() ) {
$project->set_repository_vcs_type( 'git' === $params['repository']['scm'] ? Repository::VCS_TYPE_GIT : Repository::VCS_TYPE_HG );
}

$project->set_repository_name( $params['repository']['full_name'] );
$project->set_repository_url( $params['repository']['links']['html']['href'] );
$project->set_repository_url( $href );

$ssh_url = sprintf( 'git@bitbucket.org:%s.git', $project->get_repository_name() );
$https_url = sprintf( 'https://bitbucket.org/%s.git', $project->get_repository_name() );
Expand Down
24 changes: 13 additions & 11 deletions inc/WebhookHandler/GitHub.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Required\Traduttore\WebhookHandler;

use Required\Traduttore\Project;
use Required\Traduttore\ProjectLocator;
use Required\Traduttore\Repository;
use Required\Traduttore\Updater;
Expand Down Expand Up @@ -117,24 +118,25 @@ public function callback(): \WP_Error|\WP_REST_Response {
* @var array{repository: array{ default_branch?: string, html_url: string, full_name: string, ssh_url: string, clone_url: string, private: bool }, ref: string } $params
*/

if ( ! isset( $params['repository']['default_branch'] ) ) {
return new \WP_Error( '400', 'Request incomplete', [ 'status' => 400 ] );
}
$default_branch = (string) ( $params['repository']['default_branch'] ?? '' );
$html_url = (string) $params['repository']['html_url'];
$ref = (string) $params['ref'];

// We only care about the default branch but don't want to send an error still.
if ( 'refs/heads/' . $params['repository']['default_branch'] !== $params['ref'] ) {
return new WP_REST_Response( [ 'result' => 'Not the default branch' ] );
if ( '' === $default_branch
| '' === $html_url
| '' === $ref
) {
return new \WP_Error( '400', 'Request incomplete', [ 'status' => 400 ] );
}

$locator = new ProjectLocator( $params['repository']['html_url'] );
$project = $locator->get_project();
$project = $this->resolve_project( $html_url, $default_branch, $ref );

if ( ! $project ) {
return new \WP_Error( '404', 'Could not find project for this repository', [ 'status' => 404 ] );
if ( ! $project instanceof Project ) {
return $project;
}

$project->set_repository_name( $params['repository']['full_name'] );
$project->set_repository_url( $params['repository']['html_url'] );
$project->set_repository_url( $html_url );
$project->set_repository_ssh_url( $params['repository']['ssh_url'] );
$project->set_repository_https_url( $params['repository']['clone_url'] );
$project->set_repository_visibility( false === $params['repository']['private'] ? 'public' : 'private' );
Expand Down
25 changes: 15 additions & 10 deletions inc/WebhookHandler/GitLab.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Required\Traduttore\WebhookHandler;

use Required\Traduttore\Project;
use Required\Traduttore\ProjectLocator;
use Required\Traduttore\Repository;
use Required\Traduttore\Updater;
Expand Down Expand Up @@ -77,22 +78,26 @@ public function callback(): \WP_Error|\WP_REST_Response {
*
* @var array{project: array{default_branch: string, homepage: string, path_with_namespace: string, ssh_url: string, http_url: string, visibility_level: int}, ref: string} $params
*/
$params = $this->request->get_params();

// We only care about the default branch but don't want to send an error still.
if ( 'refs/heads/' . $params['project']['default_branch'] !== $params['ref'] ) {
return new WP_REST_Response( [ 'result' => 'Not the default branch' ] );
$params = $this->request->get_params();
$default_branch = (string) $params['project']['default_branch'];
$homepage = (string) $params['project']['homepage'];
$ref = (string) $params['ref'];

if ( '' === $default_branch
| '' === $homepage
| '' === $ref
) {
return new \WP_Error( '400', 'Request incomplete', [ 'status' => 400 ] );
}

$locator = new ProjectLocator( $params['project']['homepage'] );
$project = $locator->get_project();
$project = $this->resolve_project( $homepage, $default_branch, $ref );

if ( ! $project ) {
return new \WP_Error( '404', 'Could not find project for this repository' );
if ( ! $project instanceof Project ) {
return $project;
}

$project->set_repository_name( $params['project']['path_with_namespace'] );
$project->set_repository_url( $params['project']['homepage'] );
$project->set_repository_url( $homepage );
$project->set_repository_ssh_url( $params['project']['ssh_url'] );
$project->set_repository_https_url( $params['project']['http_url'] );
$project->set_repository_visibility( 20 === $params['project']['visibility_level'] ? 'public' : 'private' );
Expand Down
2 changes: 1 addition & 1 deletion tests/phpunit/tests/WebhookHandler/GitHub.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public function test_invalid_branch(): void {
$response = rest_get_server()->dispatch( $request );

$this->assertSame( 200, $response->get_status() );
$this->assertSame( [ 'result' => 'Not the default branch' ], $response->get_data() );
$this->assertSame( [ 'result' => 'Not the default or custom branch' ], $response->get_data() );
}

public function test_invalid_project(): void {
Expand Down
24 changes: 23 additions & 1 deletion tests/phpunit/tests/WebhookHandler/GitLab.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function test_invalid_branch(): void {
$response = rest_get_server()->dispatch( $request );

$this->assertSame( 200, $response->get_status() );
$this->assertSame( [ 'result' => 'Not the default branch' ], $response->get_data() );
$this->assertSame( [ 'result' => 'Not the default or custom branch' ], $response->get_data() );
}

public function test_invalid_project(): void {
Expand All @@ -106,6 +106,28 @@ public function test_invalid_project(): void {
$this->assertErrorResponse( 404, $response );
}

public function test_request_incomplete(): void {
$request = new WP_REST_Request( 'POST', '/traduttore/v1/incoming-webhook' );
$request->set_body_params(
[
'ref' => '',
'project' => [
'default_branch' => 'master',
'path_with_namespace' => 'wearerequired/traduttore',
'homepage' => 'https://gitlab.com/wearerequired/traduttore',
'http_url' => 'https://gitlab.com/wearerequired/traduttore.git',
'ssh_url' => 'git@gitlab.com/wearerequired/traduttore.git',
'visibility_level' => 20,
],
]
);
$request->add_header( 'x-gitlab-event', 'Push Hook' );
$request->add_header( 'x-gitlab-token', 'traduttore-test' );
$response = rest_get_server()->dispatch( $request );

$this->assertErrorResponse( 400, $response );
}

public function test_valid_project(): void {
$request = new WP_REST_Request( 'POST', '/traduttore/v1/incoming-webhook' );
$request->set_body_params(
Expand Down
2 changes: 1 addition & 1 deletion tests/phpunit/tests/WebhookHandler/LegacyGitHub.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function test_invalid_branch(): void {
$response = rest_get_server()->dispatch( $request );

$this->assertSame( 200, $response->get_status() );
$this->assertSame( [ 'result' => 'Not the default branch' ], $response->get_data() );
$this->assertSame( [ 'result' => 'Not the default or custom branch' ], $response->get_data() );
}

public function test_invalid_project(): void {
Expand Down