Skip to content

Commit f295538

Browse files
author
Raphaël Droz
authored
Use auth for GitLab private repos, and fix GitLab failover behavior (#157)
* - When retrieving a ZIP from a private repository, use authentication, if provided - Fix the GitLab failover behavior (used to bail-out on private GitLab repositories without trying to use a token if one was provided) * "fix" a phpcs warning * handle GitLab subgroup * use GitLab as a Github fall-back when requesting package-name without precision about Git hosting * phpcs fixes
1 parent 1e9b181 commit f295538

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

src/Package_Command.php

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,15 @@ public function install( $args, $assoc_args ) {
244244
// Download the remote ZIP file to a temp directory
245245
$temp = false;
246246
if ( false !== strpos( $package_name, '://' ) ) {
247-
$temp = Utils\get_temp_dir() . uniqid( 'wp-cli-package_', true /*more_entropy*/ ) . '.zip';
248-
$options = [
247+
$temp = Utils\get_temp_dir() . uniqid( 'wp-cli-package_', true /*more_entropy*/ ) . '.zip';
248+
$options = [
249249
'timeout' => 600,
250250
'filename' => $temp,
251251
'insecure' => $insecure,
252252
];
253-
$response = Utils\http_request( 'GET', $package_name, null, [], $options );
253+
$gitlab_token = getenv( 'GITLAB_TOKEN' ); // Use GITLAB_TOKEN if available to avoid authorization failures or rate-limiting.
254+
$headers = $gitlab_token && strpos( $package_name, '://gitlab.com/' ) !== false ? [ 'PRIVATE-TOKEN' => $gitlab_token ] : [];
255+
$response = Utils\http_request( 'GET', $package_name, null, $headers, $options );
254256
if ( 20 !== (int) substr( $response->status_code, 0, 2 ) ) {
255257
@unlink( $temp ); // @codingStandardsIgnoreLine
256258
WP_CLI::error( sprintf( "Couldn't download package from '%s' (HTTP code %d).", $package_name, $response->status_code ) );
@@ -847,6 +849,16 @@ private function get_package_by_shortened_identifier( $package_name, $insecure =
847849
return $url;
848850
}
849851

852+
// Fall back to GitLab URL if we had no match yet.
853+
$url = "https://gitlab.com/{$package_name}.git";
854+
$gitlab_token = getenv( 'GITLAB_TOKEN' ); // Use GITLAB_TOKEN if available to avoid authorization failures or rate-limiting.
855+
$headers = $github_token ? [ 'Authorization' => 'token ' . $github_token ] : [];
856+
$headers = $gitlab_token && strpos( $package_name, '://gitlab.com/' ) !== false ? [ 'PRIVATE-TOKEN' => $gitlab_token ] : [];
857+
$response = Utils\http_request( 'GET', $url, null /*data*/, $headers, $options );
858+
if ( 20 === (int) substr( $response->status_code, 0, 2 ) ) {
859+
return $url;
860+
}
861+
850862
return false;
851863
}
852864

@@ -1161,7 +1173,9 @@ private function check_github_package_name( $package_name, $version = '', $insec
11611173
*/
11621174
private function check_git_package_name( $package_name, $url = '', $version = '', $insecure = false ) {
11631175
if ( $url && ( strpos( $url, '://gitlab.com/' ) !== false ) || ( strpos( $url, '[email protected]:' ) !== false ) ) {
1164-
return $this->check_gitlab_package_name( $package_name, $version, $insecure );
1176+
$matches = [];
1177+
preg_match( '#gitlab.com[:/](.*?)\.git#', $url, $matches );
1178+
return $this->check_gitlab_package_name( $matches[1], $version, $insecure );
11651179
}
11661180

11671181
return $this->check_github_package_name( $package_name, $version, $insecure );
@@ -1175,24 +1189,27 @@ private function check_git_package_name( $package_name, $url = '', $version = ''
11751189
* @param bool $insecure Optional. Whether to insecurely retry downloads that failed TLS handshake. Defaults
11761190
* to false.
11771191
*/
1178-
private function check_gitlab_package_name( $package_name, $version = '', $insecure = false ) {
1192+
private function check_gitlab_package_name( $project_name, $version = '', $insecure = false ) {
1193+
$options = [ 'insecure' => $insecure ];
11791194
// Generate raw git URL of composer.json file.
1180-
$raw_content_public_url = 'https://gitlab.com/' . $package_name . '/-/raw/' . $this->get_raw_git_version( $version ) . '/composer.json';
1181-
$raw_content_private_url = 'https://gitlab.com/api/v4/projects/' . rawurlencode( $package_name ) . '/repository/files/composer.json/raw?ref=' . $this->get_raw_git_version( $version );
1195+
$raw_content_public_url = 'https://gitlab.com/' . $project_name . '/-/raw/' . $this->get_raw_git_version( $version ) . '/composer.json';
1196+
$raw_content_private_url = 'https://gitlab.com/api/v4/projects/' . rawurlencode( $project_name ) . '/repository/files/composer.json/raw?ref=' . $this->get_raw_git_version( $version );
11821197

1183-
$options = [ 'insecure' => $insecure ];
1198+
$matches = [];
1199+
preg_match( '#([^:\/]+\/[^\/]+$)#', $project_name, $matches );
1200+
$package_name = $matches[1];
11841201

1185-
$response = Utils\http_request( 'GET', $raw_content_public_url, null /*data*/, [], $options );
1186-
if ( $response->status_code < 200 || $response->status_code >= 300 ) {
1202+
$gitlab_token = getenv( 'GITLAB_TOKEN' ); // Use GITLAB_TOKEN if available to avoid authorization failures or rate-limiting.
1203+
$response = Utils\http_request( 'GET', $raw_content_public_url, null /*data*/, [], $options );
1204+
if ( ! $gitlab_token && ( $response->status_code < 200 || $response->status_code >= 300 ) ) {
11871205
// Could not get composer.json. Possibly private so warn and return best guess from input (always xxx/xxx).
11881206
WP_CLI::warning( sprintf( "Couldn't download composer.json file from '%s' (HTTP code %d). Presuming package name is '%s'.", $raw_content_public_url, $response->status_code, $package_name ) );
11891207
return $package_name;
11901208
}
11911209

11921210
if ( strpos( $response->headers['content-type'], 'text/html' ) === 0 ) {
1193-
$gitlab_token = getenv( 'GITLAB_TOKEN' ); // Use GITLAB_TOKEN if available to avoid authorization failures or rate-limiting.
1194-
$headers = $gitlab_token ? [ 'PRIVATE-TOKEN' => $gitlab_token ] : [];
1195-
$response = Utils\http_request( 'GET', $raw_content_private_url, null /*data*/, $headers, $options );
1211+
$headers = $gitlab_token ? [ 'PRIVATE-TOKEN' => $gitlab_token ] : [];
1212+
$response = Utils\http_request( 'GET', $raw_content_private_url, null /*data*/, $headers, $options );
11961213

11971214
if ( $response->status_code < 200 || $response->status_code >= 300 ) {
11981215
// Could not get composer.json. Possibly private so warn and return best guess from input (always xxx/xxx).

0 commit comments

Comments
 (0)