-
Notifications
You must be signed in to change notification settings - Fork 19
Handle additional git providers in set_composer_auth_env_var() #218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Copilot
wants to merge
6
commits into
main
Choose a base branch
from
copilot/handle-more-git-providers
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
2fbba68
Initial plan
Copilot 6d5b7e4
Add support for additional git providers in set_composer_auth_env_var()
Copilot a98bb8c
Refactor tests to reduce duplication with helper method
Copilot 17ce3e4
Update src/Package_Command.php
swissspidy d14a28e
Update src/Package_Command.php
swissspidy 3715993
Update src/Package_Command.php
swissspidy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| Feature: Composer authentication for various git providers | ||
|
|
||
| Scenario: GitHub OAuth token is set in COMPOSER_AUTH | ||
| Given an empty directory | ||
| When I run `GITHUB_TOKEN=ghp_test123456789 wp package path` | ||
| Then STDOUT should not be empty | ||
| And the return code should be 0 | ||
|
|
||
| Scenario: GitLab OAuth token is set in COMPOSER_AUTH | ||
| Given an empty directory | ||
| When I run `GITLAB_OAUTH_TOKEN=glpat_test123456789 wp package path` | ||
| Then STDOUT should not be empty | ||
| And the return code should be 0 | ||
|
|
||
| Scenario: GitLab personal access token is set in COMPOSER_AUTH | ||
| Given an empty directory | ||
| When I run `GITLAB_TOKEN=glpat_test123456789 wp package path` | ||
| Then STDOUT should not be empty | ||
| And the return code should be 0 | ||
|
|
||
| Scenario: Bitbucket OAuth consumer is set in COMPOSER_AUTH | ||
| Given an empty directory | ||
| When I run `BITBUCKET_CONSUMER_KEY=test_key BITBUCKET_CONSUMER_SECRET=test_secret wp package path` | ||
| Then STDOUT should not be empty | ||
| And the return code should be 0 | ||
|
|
||
| Scenario: HTTP Basic Auth is set in COMPOSER_AUTH | ||
| Given an empty directory | ||
| When I run `HTTP_BASIC_AUTH='{"repo.example.com":{"username":"user","password":"pass"}}' wp package path` | ||
| Then STDOUT should not be empty | ||
| And the return code should be 0 | ||
|
|
||
| Scenario: Multiple auth providers can be used together | ||
| Given an empty directory | ||
| When I run `GITHUB_TOKEN=ghp_test123 GITLAB_TOKEN=glpat_test456 wp package path` | ||
| Then STDOUT should not be empty | ||
| And the return code should be 0 | ||
|
|
||
| Scenario: Invalid HTTP_BASIC_AUTH JSON is ignored | ||
| Given an empty directory | ||
| When I run `HTTP_BASIC_AUTH='not-valid-json' wp package path` | ||
| Then STDOUT should not be empty | ||
| And the return code should be 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1409,11 +1409,54 @@ private function set_composer_auth_env_var() { | |
| if ( empty( $composer_auth ) || ! is_array( $composer_auth ) ) { | ||
| $composer_auth = []; | ||
| } | ||
|
|
||
| // GitHub OAuth token. | ||
| $github_token = getenv( 'GITHUB_TOKEN' ); | ||
| if ( ! isset( $composer_auth['github-oauth'] ) && is_string( $github_token ) ) { | ||
| $composer_auth['github-oauth'] = [ 'github.com' => $github_token ]; | ||
| $changed = true; | ||
| } | ||
|
|
||
| // GitLab OAuth token. | ||
| $gitlab_oauth_token = getenv( 'GITLAB_OAUTH_TOKEN' ); | ||
| if ( ! isset( $composer_auth['gitlab-oauth'] ) && is_string( $gitlab_oauth_token ) && '' !== $gitlab_oauth_token ) { | ||
| $composer_auth['gitlab-oauth'] = [ 'gitlab.com' => $gitlab_oauth_token ]; | ||
| $changed = true; | ||
| } | ||
|
|
||
| // GitLab personal access token. | ||
| $gitlab_token = getenv( 'GITLAB_TOKEN' ); | ||
| if ( ! isset( $composer_auth['gitlab-token'] ) && is_string( $gitlab_token ) ) { | ||
|
||
| $composer_auth['gitlab-token'] = [ 'gitlab.com' => $gitlab_token ]; | ||
| $changed = true; | ||
| } | ||
|
|
||
| // Bitbucket OAuth consumer. | ||
| $bitbucket_key = getenv( 'BITBUCKET_CONSUMER_KEY' ); | ||
| $bitbucket_secret = getenv( 'BITBUCKET_CONSUMER_SECRET' ); | ||
| if ( ! isset( $composer_auth['bitbucket-oauth'] ) | ||
| && is_string( $bitbucket_key ) && '' !== $bitbucket_key | ||
| && is_string( $bitbucket_secret ) && '' !== $bitbucket_secret | ||
| ) { | ||
| $composer_auth['bitbucket-oauth'] = [ | ||
| 'bitbucket.org' => [ | ||
| 'consumer-key' => $bitbucket_key, | ||
| 'consumer-secret' => $bitbucket_secret, | ||
| ], | ||
| ]; | ||
| $changed = true; | ||
| } | ||
|
|
||
| // HTTP Basic Authentication. | ||
| $http_basic_auth = getenv( 'HTTP_BASIC_AUTH' ); | ||
| if ( ! isset( $composer_auth['http-basic'] ) && is_string( $http_basic_auth ) && '' !== $http_basic_auth ) { | ||
| $http_basic_auth_decoded = json_decode( $http_basic_auth, true /*assoc*/ ); | ||
| if ( is_array( $http_basic_auth_decoded ) ) { | ||
| $composer_auth['http-basic'] = $http_basic_auth_decoded; | ||
| $changed = true; | ||
| } | ||
| } | ||
|
|
||
| if ( $changed ) { | ||
| putenv( 'COMPOSER_AUTH=' . json_encode( $composer_auth ) ); | ||
| } | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,260 @@ | ||
| <?php | ||
|
|
||
| use WP_CLI\Tests\TestCase; | ||
|
|
||
| class PackageAuthTest extends TestCase { | ||
|
|
||
| private $env_vars_to_restore = []; | ||
|
|
||
| public function set_up() { | ||
| parent::set_up(); | ||
|
|
||
| // Save current environment variables | ||
| $this->env_vars_to_restore = [ | ||
| 'COMPOSER_AUTH' => getenv( 'COMPOSER_AUTH' ), | ||
| 'GITHUB_TOKEN' => getenv( 'GITHUB_TOKEN' ), | ||
| 'GITLAB_OAUTH_TOKEN' => getenv( 'GITLAB_OAUTH_TOKEN' ), | ||
| 'GITLAB_TOKEN' => getenv( 'GITLAB_TOKEN' ), | ||
| 'BITBUCKET_CONSUMER_KEY' => getenv( 'BITBUCKET_CONSUMER_KEY' ), | ||
| 'BITBUCKET_CONSUMER_SECRET' => getenv( 'BITBUCKET_CONSUMER_SECRET' ), | ||
| 'HTTP_BASIC_AUTH' => getenv( 'HTTP_BASIC_AUTH' ), | ||
| ]; | ||
|
|
||
| // Clear all auth-related environment variables | ||
| foreach ( array_keys( $this->env_vars_to_restore ) as $var ) { | ||
| putenv( $var ); | ||
| } | ||
| } | ||
|
|
||
| public function tear_down() { | ||
| // Restore environment variables | ||
| foreach ( $this->env_vars_to_restore as $var => $value ) { | ||
| if ( false !== $value ) { | ||
| putenv( "$var=$value" ); | ||
| } else { | ||
| putenv( $var ); | ||
| } | ||
| } | ||
|
|
||
| parent::tear_down(); | ||
| } | ||
|
|
||
| /** | ||
| * Helper method to invoke the set_composer_auth_env_var method. | ||
| */ | ||
| private function invoke_set_composer_auth() { | ||
| $package = new Package_Command(); | ||
| $method = new \ReflectionMethod( 'Package_Command', 'set_composer_auth_env_var' ); | ||
| if ( PHP_VERSION_ID < 80100 ) { | ||
| $method->setAccessible( true ); | ||
| } | ||
| $method->invoke( $package ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that GITHUB_TOKEN is added to COMPOSER_AUTH. | ||
| */ | ||
| public function test_github_token_added_to_composer_auth() { | ||
| putenv( 'GITHUB_TOKEN=ghp_test123456789' ); | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| $this->assertNotFalse( $composer_auth ); | ||
|
|
||
| $auth_array = json_decode( $composer_auth, true ); | ||
| $this->assertIsArray( $auth_array ); | ||
| $this->assertArrayHasKey( 'github-oauth', $auth_array ); | ||
| $this->assertArrayHasKey( 'github.com', $auth_array['github-oauth'] ); | ||
| $this->assertSame( 'ghp_test123456789', $auth_array['github-oauth']['github.com'] ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that GITLAB_OAUTH_TOKEN is added to COMPOSER_AUTH. | ||
| */ | ||
| public function test_gitlab_oauth_token_added_to_composer_auth() { | ||
| putenv( 'GITLAB_OAUTH_TOKEN=glpat_test123456789' ); | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| $this->assertNotFalse( $composer_auth ); | ||
|
|
||
| $auth_array = json_decode( $composer_auth, true ); | ||
| $this->assertIsArray( $auth_array ); | ||
| $this->assertArrayHasKey( 'gitlab-oauth', $auth_array ); | ||
| $this->assertArrayHasKey( 'gitlab.com', $auth_array['gitlab-oauth'] ); | ||
| $this->assertSame( 'glpat_test123456789', $auth_array['gitlab-oauth']['gitlab.com'] ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that GITLAB_TOKEN is added to COMPOSER_AUTH. | ||
| */ | ||
| public function test_gitlab_token_added_to_composer_auth() { | ||
| putenv( 'GITLAB_TOKEN=glpat_test123456789' ); | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| $this->assertNotFalse( $composer_auth ); | ||
|
|
||
| $auth_array = json_decode( $composer_auth, true ); | ||
| $this->assertIsArray( $auth_array ); | ||
| $this->assertArrayHasKey( 'gitlab-token', $auth_array ); | ||
| $this->assertArrayHasKey( 'gitlab.com', $auth_array['gitlab-token'] ); | ||
| $this->assertSame( 'glpat_test123456789', $auth_array['gitlab-token']['gitlab.com'] ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that BITBUCKET_CONSUMER_KEY and BITBUCKET_CONSUMER_SECRET are added to COMPOSER_AUTH. | ||
| */ | ||
| public function test_bitbucket_oauth_added_to_composer_auth() { | ||
| putenv( 'BITBUCKET_CONSUMER_KEY=test_key' ); | ||
| putenv( 'BITBUCKET_CONSUMER_SECRET=test_secret' ); | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| $this->assertNotFalse( $composer_auth ); | ||
|
|
||
| $auth_array = json_decode( $composer_auth, true ); | ||
| $this->assertIsArray( $auth_array ); | ||
| $this->assertArrayHasKey( 'bitbucket-oauth', $auth_array ); | ||
| $this->assertArrayHasKey( 'bitbucket.org', $auth_array['bitbucket-oauth'] ); | ||
| $this->assertArrayHasKey( 'consumer-key', $auth_array['bitbucket-oauth']['bitbucket.org'] ); | ||
| $this->assertArrayHasKey( 'consumer-secret', $auth_array['bitbucket-oauth']['bitbucket.org'] ); | ||
| $this->assertSame( 'test_key', $auth_array['bitbucket-oauth']['bitbucket.org']['consumer-key'] ); | ||
| $this->assertSame( 'test_secret', $auth_array['bitbucket-oauth']['bitbucket.org']['consumer-secret'] ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that Bitbucket OAuth is not added if only one credential is provided. | ||
| */ | ||
| public function test_bitbucket_oauth_requires_both_credentials() { | ||
| putenv( 'BITBUCKET_CONSUMER_KEY=test_key' ); | ||
| // BITBUCKET_CONSUMER_SECRET is not set | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| // No auth should be set because only one credential was provided | ||
| $this->assertFalse( $composer_auth ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that HTTP_BASIC_AUTH is added to COMPOSER_AUTH. | ||
| */ | ||
| public function test_http_basic_auth_added_to_composer_auth() { | ||
| $http_basic = json_encode( | ||
| [ | ||
| 'repo.example.com' => [ | ||
| 'username' => 'user', | ||
| 'password' => 'pass', | ||
| ], | ||
| ] | ||
| ); | ||
| putenv( "HTTP_BASIC_AUTH=$http_basic" ); | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| $this->assertNotFalse( $composer_auth ); | ||
|
|
||
| $auth_array = json_decode( $composer_auth, true ); | ||
| $this->assertIsArray( $auth_array ); | ||
| $this->assertArrayHasKey( 'http-basic', $auth_array ); | ||
| $this->assertArrayHasKey( 'repo.example.com', $auth_array['http-basic'] ); | ||
| $this->assertArrayHasKey( 'username', $auth_array['http-basic']['repo.example.com'] ); | ||
| $this->assertArrayHasKey( 'password', $auth_array['http-basic']['repo.example.com'] ); | ||
| $this->assertSame( 'user', $auth_array['http-basic']['repo.example.com']['username'] ); | ||
| $this->assertSame( 'pass', $auth_array['http-basic']['repo.example.com']['password'] ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that invalid HTTP_BASIC_AUTH JSON is ignored. | ||
| */ | ||
| public function test_invalid_http_basic_auth_json_ignored() { | ||
| putenv( 'HTTP_BASIC_AUTH=not-valid-json' ); | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| // No auth should be set because the JSON was invalid | ||
| $this->assertFalse( $composer_auth ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that multiple auth providers can be used together. | ||
| */ | ||
| public function test_multiple_auth_providers() { | ||
| putenv( 'GITHUB_TOKEN=ghp_test123' ); | ||
| putenv( 'GITLAB_TOKEN=glpat_test456' ); | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| $this->assertNotFalse( $composer_auth ); | ||
|
|
||
| $auth_array = json_decode( $composer_auth, true ); | ||
| $this->assertIsArray( $auth_array ); | ||
| $this->assertArrayHasKey( 'github-oauth', $auth_array ); | ||
| $this->assertArrayHasKey( 'gitlab-token', $auth_array ); | ||
| $this->assertSame( 'ghp_test123', $auth_array['github-oauth']['github.com'] ); | ||
| $this->assertSame( 'glpat_test456', $auth_array['gitlab-token']['gitlab.com'] ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that existing COMPOSER_AUTH is preserved. | ||
| */ | ||
| public function test_existing_composer_auth_preserved() { | ||
| $existing_auth = json_encode( | ||
| [ | ||
| 'github-oauth' => [ | ||
| 'github.com' => 'existing_token', | ||
| ], | ||
| ] | ||
| ); | ||
| putenv( "COMPOSER_AUTH=$existing_auth" ); | ||
| putenv( 'GITLAB_TOKEN=glpat_new_token' ); | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| $this->assertNotFalse( $composer_auth ); | ||
|
|
||
| $auth_array = json_decode( $composer_auth, true ); | ||
| $this->assertIsArray( $auth_array ); | ||
| // Existing github-oauth should be preserved | ||
| $this->assertArrayHasKey( 'github-oauth', $auth_array ); | ||
| $this->assertSame( 'existing_token', $auth_array['github-oauth']['github.com'] ); | ||
| // New gitlab-token should be added | ||
| $this->assertArrayHasKey( 'gitlab-token', $auth_array ); | ||
| $this->assertSame( 'glpat_new_token', $auth_array['gitlab-token']['gitlab.com'] ); | ||
| } | ||
|
|
||
| /** | ||
| * Test that environment variable tokens don't override existing COMPOSER_AUTH values. | ||
| */ | ||
| public function test_env_tokens_dont_override_composer_auth() { | ||
| $existing_auth = json_encode( | ||
| [ | ||
| 'github-oauth' => [ | ||
| 'github.com' => 'existing_token', | ||
| ], | ||
| ] | ||
| ); | ||
| putenv( "COMPOSER_AUTH=$existing_auth" ); | ||
| putenv( 'GITHUB_TOKEN=new_token' ); | ||
|
|
||
| $this->invoke_set_composer_auth(); | ||
|
|
||
| $composer_auth = getenv( 'COMPOSER_AUTH' ); | ||
| $this->assertNotFalse( $composer_auth ); | ||
|
|
||
| $auth_array = json_decode( $composer_auth, true ); | ||
| $this->assertIsArray( $auth_array ); | ||
| // Existing github-oauth should be preserved, not overridden by GITHUB_TOKEN | ||
| $this->assertArrayHasKey( 'github-oauth', $auth_array ); | ||
| $this->assertSame( 'existing_token', $auth_array['github-oauth']['github.com'] ); | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The condition
is_string( $github_token )will accept empty strings, which could result in empty authentication tokens being added to COMPOSER_AUTH. Consider adding an additional check to ensure the token is not empty, such asis_string( $github_token ) && '' !== $github_token, which would be more consistent with the truthy check pattern used elsewhere in this file (e.g., line 939:$github_token ? [ 'Authorization' => 'token ' . $github_token ] : []).