Skip to content

Commit cf5cd90

Browse files
committed
Improve support for composer authenticating private respositories
1 parent cdb037c commit cf5cd90

6 files changed

Lines changed: 115 additions & 17 deletions

File tree

README.md

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ Setup PHP with required extensions, php.ini configuration, code-coverage support
5151
- [JIT Configuration](#jit-configuration)
5252
- [Cache Extensions](#cache-extensions)
5353
- [Cache Composer Dependencies](#cache-composer-dependencies)
54-
- [Composer GitHub OAuth](#composer-github-oauth)
54+
- [GitHub Composer Authentication](#github-composer-authentication)
55+
- [Private Packagist Authentication](#private-packagist-authentication)
56+
- [Manual Composer Authentication](#manual-composer-authentication)
5557
- [Inline PHP Scripts](#inline-php-scripts)
5658
- [Problem Matchers](#problem-matchers)
5759
- [Examples](#examples)
@@ -252,7 +254,7 @@ These tools can be set up globally using the `tools` input. It accepts a string
252254

253255
When you specify just the major version or the version in `major.minor` format, the latest patch version matching the input will be setup.
254256

255-
Except for major versions of `composer`, For other tools when you specify only the `major` version or the version in `major.minor` format for any tool you can get rate limited by GitHub's API. To avoid this, it is recommended to provide a [`GitHub` OAuth token](https://github.com/shivammathur/setup-php#composer-github-oauth "Composer GitHub OAuth"). You can do that by setting `COMPOSER_TOKEN` environment variable.
257+
Except for major versions of `composer`, For other tools when you specify only the `major` version or the version in `major.minor` format for any tool you can get rate limited by GitHub's API. To avoid this, it is recommended to provide a [`GitHub` OAuth token](https://github.com/shivammathur/setup-php#composer-github-oauth "Composer GitHub OAuth"). You can do that by setting `GITHUB_TOKEN` environment variable. The `COMPOSER_TOKEN` environment variable has been deprecated in favor of `GITHUB_TOKEN` and will be removed in a future release.
256258

257259
```yaml
258260
- name: Setup PHP with tools
@@ -261,7 +263,7 @@ These tools can be set up globally using the `tools` input. It accepts a string
261263
php-version: '8.1'
262264
tools: php-cs-fixer:3.5, phpunit:9.5
263265
env:
264-
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
266+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
265267
```
266268

267269
- The latest stable version of `composer` is set up by default. You can set up the required `composer` version by specifying the major version `v1` or `v2`, or the version in `major.minor` or `semver` format. Additionally for composer `snapshot` and `preview` can also be specified to set up the respective releases.
@@ -736,17 +738,53 @@ key: ${{ runner.os }}-composer-${{ matrix.prefer }}-${{ hashFiles('**/composer.l
736738
restore-keys: ${{ runner.os }}-composer-${{ matrix.prefer }}-
737739
```
738740

739-
### Composer GitHub OAuth
741+
### GitHub Composer Authentication
740742

741-
If you have a number of workflows which set up multiple tools or have many composer dependencies, you might hit the GitHub's rate limit for composer. Also, if you specify only the major version or the version in `major.minor` format, you can hit the rate limit. To avoid this you can specify an `OAuth` token by setting `COMPOSER_TOKEN` environment variable. You can use [`GITHUB_TOKEN`](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token "GITHUB_TOKEN documentation") secret for this purpose.
743+
If you have a number of workflows which set up multiple tools or have many composer dependencies, you might hit the GitHub's rate limit for composer. Also, if you specify only the major version or the version in `major.minor` format, you can hit the rate limit. To avoid this you can specify an `OAuth` token by setting `GITHUB_TOKEN` environment variable. You can use [`GITHUB_TOKEN`](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token "GITHUB_TOKEN documentation") secret for this purpose.
744+
The `COMPOSER_TOKEN` key has been deprecated in favor of `GITHUB_TOKEN` and will be removed in the next major version.
742745

743746
```yaml
744747
- name: Setup PHP
745748
uses: shivammathur/setup-php@v2
746749
with:
747750
php-version: '8.1'
748751
env:
749-
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
752+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
753+
```
754+
755+
### Private Packagist Authentication
756+
757+
If you use Private Packagist for your private composer dependencies, you can set the `PACKAGIST_TOKEN` environment variable to authenticate.
758+
759+
```yaml
760+
- name: Setup PHP
761+
uses: shivammathur/setup-php@v2
762+
with:
763+
php-version: '8.1'
764+
env:
765+
PACKAGIST_TOKEN: ${{ secrets.PACKAGIST_TOKEN }}
766+
```
767+
768+
### Manual Composer Authentication
769+
770+
In addition to GitHub or Private Packagist, if you want to authenticate private repositories hosted elsewhere, you can set the `COMPOSER_AUTH_JSON` environment variable with the authentication methods and the credentials in json format.
771+
Please refer to the authentication section in [`composer documentation`](https://getcomposer.org/doc/articles/authentication-for-private-packages.md "composer documentation") for more details.
772+
773+
```yaml
774+
- name: Setup PHP
775+
uses: shivammathur/setup-php@v2
776+
with:
777+
php-version: '8.1'
778+
env:
779+
COMPOSER_AUTH_JSON: |
780+
{
781+
"http-basic": {
782+
"example.org": {
783+
"username": "${{ secrets.EXAMPLE_ORG_USERNAME }}",
784+
"password": "${{ secrets.EXAMPLE_ORG_PASSWORD }}"
785+
}
786+
}
787+
}
750788
```
751789

752790
### Inline PHP Scripts

__tests__/tools.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,4 +527,14 @@ describe('Tools tests', () => {
527527
process.env['COMPOSER_TOKEN'] = token;
528528
expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script);
529529
});
530+
531+
it.each`
532+
tools_csv | token | script
533+
${'cs2pr:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "cs2pr" "Invalid token"'}
534+
${'phpunit:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "phpunit" "Invalid token"'}
535+
${'phpunit:0.1'} | ${'no_data'} | ${'add_log "$cross" "phpunit" "No version found with prefix 0.1."'}
536+
`('checking error: $tools_csv', async ({tools_csv, token, script}) => {
537+
process.env['GITHUB_TOKEN'] = token;
538+
expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script);
539+
});
530540
});

dist/index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,8 +622,12 @@ const utils = __importStar(__nccwpck_require__(918));
622622
async function getSemverVersion(data) {
623623
const search = data['version_prefix'] + data['version'];
624624
const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`;
625-
const token = await utils.readEnv('COMPOSER_TOKEN');
626-
const response = await fetch.fetch(url, token);
625+
let github_token = await utils.readEnv('GITHUB_TOKEN');
626+
const composer_token = await utils.readEnv('COMPOSER_TOKEN');
627+
if (composer_token && !github_token) {
628+
github_token = composer_token;
629+
}
630+
const response = await fetch.fetch(url, github_token);
627631
if (response.error || response.data === '[]') {
628632
data['error'] = response.error ?? `No version found with prefix ${search}.`;
629633
return data['version'];

src/scripts/tools/add_tools.ps1

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Variables
2-
$composer_bin = "$env:APPDATA\Composer\vendor\bin"
3-
$composer_json = "$env:APPDATA\Composer\composer.json"
4-
$composer_lock = "$env:APPDATA\Composer\composer.lock"
2+
$composer_home = "$env:APPDATA\Composer"
3+
$composer_bin = "$composer_home\vendor\bin"
4+
$composer_json = "$composer_home\composer.json"
5+
$composer_lock = "$composer_home\composer.lock"
56

67
# Function to configure composer.
78
Function Edit-ComposerConfig() {
@@ -24,8 +25,30 @@ Function Edit-ComposerConfig() {
2425
}
2526
Add-EnvPATH $src\configs\composer.env
2627
Add-Path $composer_bin
27-
if (Test-Path env:COMPOSER_TOKEN) {
28-
Add-Env COMPOSER_AUTH ('{"github-oauth": {"github.com": "' + $env:COMPOSER_TOKEN + '"}}')
28+
Set-ComposerAuth
29+
}
30+
31+
# Function to setup authentication in composer.
32+
Function Set-ComposerAuth() {
33+
if(Test-Path env:COMPOSER_AUTH_JSON) {
34+
if(Test-Json -JSON $env:COMPOSER_AUTH_JSON) {
35+
Set-Content -Path $composer_home\auth.json -Value $env:COMPOSER_AUTH_JSON
36+
} else {
37+
Add-Log "$cross" "composer" "Could not parse COMPOSER_AUTH_JSON as valid JSON"
38+
}
39+
}
40+
$composer_auth = @()
41+
if(Test-Path env:PACKAGIST_TOKEN) {
42+
$composer_auth += '"http-basic": {"repo.packagist.com": { "username": "token", "password": "' + $env:PACKAGIST_TOKEN + '"}}'
43+
}
44+
if(-not(Test-Path env:GITHUB_TOKEN) -and (Test-Path env:COMPOSER_TOKEN)) {
45+
$env:GITHUB_TOKEN = $env:COMPOSER_TOKEN
46+
}
47+
if (Test-Path env:GITHUB_TOKEN) {
48+
$composer_auth += '"github-oauth": {"github.com": "' + $env:GITHUB_TOKEN + '"}'
49+
}
50+
if($composer_auth.length) {
51+
Add-Env COMPOSER_AUTH ('{' + ($composer_auth -join ',') + '}')
2952
}
3053
}
3154

src/scripts/tools/add_tools.sh

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,27 @@ configure_composer() {
4444
fi
4545
add_env_path "${src:?}"/configs/composer.env
4646
add_path "$composer_bin"
47-
if [ -n "$COMPOSER_TOKEN" ]; then
48-
add_env COMPOSER_AUTH '{"github-oauth": {"github.com": "'"$COMPOSER_TOKEN"'"}}'
47+
set_composer_auth
48+
}
49+
50+
# Function to setup authentication in composer.
51+
set_composer_auth() {
52+
if [ -n "$COMPOSER_AUTH_JSON" ]; then
53+
if php -r "json_decode('$COMPOSER_AUTH_JSON'); if(json_last_error() !== JSON_ERROR_NONE) { throw new Exception('invalid json'); }"; then
54+
echo "$COMPOSER_AUTH_JSON" | tee "$composer_home/auth.json" >/dev/null
55+
else
56+
add_log "${cross:?}" "composer" "Could not parse COMPOSER_AUTH_JSON as valid JSON"
57+
fi
58+
fi
59+
composer_auth=()
60+
if [ -n "$PACKAGIST_TOKEN" ]; then
61+
composer_auth+=( '"http-basic": {"repo.packagist.com": { "username": "token", "password": "'"$PACKAGIST_TOKEN"'"}}' )
62+
fi
63+
if [ -n "${GITHUB_TOKEN:-$COMPOSER_TOKEN}" ]; then
64+
composer_auth+=( '"github-oauth": {"github.com": "'"${GITHUB_TOKEN:-$COMPOSER_TOKEN}"'"}' )
65+
fi
66+
if ((${#composer_auth[@]})); then
67+
add_env COMPOSER_AUTH "{$(IFS=$','; echo "${composer_auth[*]}")}"
4968
fi
5069
}
5170

src/tools.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ interface IRef {
2121
export async function getSemverVersion(data: RS): Promise<string> {
2222
const search: string = data['version_prefix'] + data['version'];
2323
const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`;
24-
const token: string = await utils.readEnv('COMPOSER_TOKEN');
25-
const response: RS = await fetch.fetch(url, token);
24+
let github_token: string = await utils.readEnv('GITHUB_TOKEN');
25+
const composer_token: string = await utils.readEnv('COMPOSER_TOKEN');
26+
if (composer_token && !github_token) {
27+
github_token = composer_token;
28+
}
29+
const response: RS = await fetch.fetch(url, github_token);
2630
if (response.error || response.data === '[]') {
2731
data['error'] = response.error ?? `No version found with prefix ${search}.`;
2832
return data['version'];

0 commit comments

Comments
 (0)