diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..6d2d16a545f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/backwards-compatibility.yml b/.github/workflows/backwards-compatibility.yml new file mode 100644 index 00000000000..8d13b2d512e --- /dev/null +++ b/.github/workflows/backwards-compatibility.yml @@ -0,0 +1,24 @@ +name: "BC check" + +on: + pull_request: + +jobs: + roave_bc_check: + name: "Roave BC check" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + + - name: Install roave/backward-compatibility-check + run: composer require --dev roave/backward-compatibility-check + + - name: Run roave/backward-compatibility-check + run: vendor/bin/roave-backward-compatibility-check --from=${{ github.event.pull_request.base.sha }} --format=github-actions diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3fbe6bd1c5c..26fa98818e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,10 +11,10 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['7.2', '7.3', '7.4', '8.0'] + php-versions: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -23,27 +23,19 @@ jobs: coverage: none - name: Install Composer Dependencies - uses: ramsey/composer-install@v1 + uses: ramsey/composer-install@v3 - name: Run phpunit run: vendor/bin/phpunit --verbose - - roave_bc_check: - name: Roave BC Check - runs-on: ubuntu-latest - steps: - - run: echo true - - uses: actions/checkout@v2 - - - name: Roave BC Check - uses: docker://nyholm/roave-bc-check-ga + env: + SYMFONY_DEPRECATIONS_HELPER: 'max[self]=0' phpstan: name: PHPStan runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: shivammathur/setup-php@v2 with: @@ -51,7 +43,7 @@ jobs: coverage: none - name: Install Composer Dependencies - uses: ramsey/composer-install@v1 + uses: ramsey/composer-install@v3 - name: Run phpstan run: vendor/bin/phpstan analyse --no-progress diff --git a/CHANGELOG-3.X.md b/CHANGELOG-3.X.md index 544e4e8ba59..f26bcc96430 100644 --- a/CHANGELOG-3.X.md +++ b/CHANGELOG-3.X.md @@ -1,5 +1,219 @@ # Changelog +## 3.16.0 + +### Added +- Add API to rerequest a check run ([Spea](https://github.com/Spea)) [#1141](https://github.com/KnpLabs/php-github-api/issues/1141) +- List pull requests associated with a commit ([lmjhs](https://github.com/lmjhs)) [#1146](https://github.com/KnpLabs/php-github-api/issues/1146) + +## 3.15.0 + +### Added +- Fix implicit nullable types to avoid PHP 8.4 warnings ([eiriksm](https://github.com/eiriksm), [acrobat](https://github.com/acrobat)) [#1144](https://github.com/KnpLabs/php-github-api/issues/1144) +- Add API endpoints to interact with organization roles ([glaubinix](https://github.com/glaubinix)) [#1143](https://github.com/KnpLabs/php-github-api/issues/1143) +- Copilot Usage Endpoints ([anthony-webart](https://github.com/anthony-webart)) [#1142](https://github.com/KnpLabs/php-github-api/issues/1142) +- Fix type error in ResultPager::fetch ([nunoplopes](https://github.com/nunoplopes)) [#1132](https://github.com/KnpLabs/php-github-api/issues/1132) + +## 3.14.1 + +### Fixed +- Handle case of GitHub returning 204 No Content in some scenarios ([tomcorbett](https://github.com/tomcorbett)) [#1135](https://github.com/KnpLabs/php-github-api/issues/1135) + +## 3.14.0 + +### Added +- Allow php-http/cache-plugin v2 ([GrahamCampbell](https://github.com/GrahamCampbell)) [#1134](https://github.com/KnpLabs/php-github-api/issues/1134) + +## 3.13.0 + +### Added +- Test against php 8.3 ([sergiy-petrov](https://github.com/sergiy-petrov)) [#1124](https://github.com/KnpLabs/php-github-api/issues/1124) +- feat: Secret Scanning Alerts ([haridarshan](https://github.com/haridarshan)) [#1114](https://github.com/KnpLabs/php-github-api/issues/1114) +- feat: User Migration ([haridarshan](https://github.com/haridarshan)) [#1115](https://github.com/KnpLabs/php-github-api/issues/1115) + +### Changed +- General chores ([acrobat](https://github.com/acrobat)) [#1125](https://github.com/KnpLabs/php-github-api/issues/1125) + +### Fixed +- Fix detection of secondary rate limit ([mathieudz](https://github.com/mathieudz)) [#1126](https://github.com/KnpLabs/php-github-api/issues/1126) + +## 3.12.0 + +### Added +- feat: Support for Organization Runners ([haridarshan](https://github.com/haridarshan), [renovate](https://github.com/renovate)[[bot](https://github.com/bot)]) [#1101](https://github.com/KnpLabs/php-github-api/issues/1101) +- allow psr/http-message v2 ([LordSimal](https://github.com/LordSimal)) [#1122](https://github.com/KnpLabs/php-github-api/issues/1122) + +### Changed +- Fixed branch alias ([GrahamCampbell](https://github.com/GrahamCampbell)) [#1109](https://github.com/KnpLabs/php-github-api/issues/1109) + +## 3.11.0 + +### Added +- Added environment variables & secrets ([Froxz](https://github.com/Froxz)) [#1104](https://github.com/KnpLabs/php-github-api/issues/1104) +- Added Org & Repository variables ([Froxz](https://github.com/Froxz)) [#1106](https://github.com/KnpLabs/php-github-api/issues/1106) +- Deployment branch policies ([Froxz](https://github.com/Froxz)) [#1108](https://github.com/KnpLabs/php-github-api/issues/1108) + +### Changed +- Test on PHP 8.2 ([GrahamCampbell](https://github.com/GrahamCampbell)) [#1105](https://github.com/KnpLabs/php-github-api/issues/1105) + +### Fixed +- Bugfix creating env ([Froxz](https://github.com/Froxz)) [#1107](https://github.com/KnpLabs/php-github-api/issues/1107) + +## 3.10.0 + +### Added +- Add vulnerability alerts endpoints ([andreia](https://github.com/andreia)) [#1096](https://github.com/KnpLabs/php-github-api/issues/1096) +- Added environments ([Froxz](https://github.com/Froxz)) [#1103](https://github.com/KnpLabs/php-github-api/issues/1103) + +### Changed +- Create authorization removed from docs ([rafasashi](https://github.com/rafasashi)) [#1090](https://github.com/KnpLabs/php-github-api/issues/1090) +- Setup dependabot for github action workflows ([acrobat](https://github.com/acrobat)) [#1098](https://github.com/KnpLabs/php-github-api/issues/1098) +- Bump actions/checkout from 2 to 3 ([dependabot](https://github.com/dependabot)[[bot](https://github.com/bot)]) [#1099](https://github.com/KnpLabs/php-github-api/issues/1099) +- Bump ramsey/composer-install from 1 to 2 ([dependabot](https://github.com/dependabot)[[bot](https://github.com/bot)]) [#1100](https://github.com/KnpLabs/php-github-api/issues/1100) + +## 3.9.0 + +### Added +- Add the ability to download raw file, needed when size > 1MB ([genintho](https://github.com/genintho)) [#1075](https://github.com/KnpLabs/php-github-api/issues/1075) +- Feat: Support new Team Repositories Endpoint ([iBotPeaches](https://github.com/iBotPeaches)) [#1082](https://github.com/KnpLabs/php-github-api/issues/1082) +- App: add hook endpoints ([glaubinix](https://github.com/glaubinix)) [#1086](https://github.com/KnpLabs/php-github-api/issues/1086) +- Add sync a fork branch with the upstream repository ([DAGpro](https://github.com/DAGpro)) [#1084](https://github.com/KnpLabs/php-github-api/issues/1084) + +### Changed +- Fix return types in phpdoc for `Assignees` and `ReviewRequest` ([rob006](https://github.com/rob006)) [#1078](https://github.com/KnpLabs/php-github-api/issues/1078) +- Fixed several typos and grammar errors ([AndrewDawes](https://github.com/AndrewDawes)) [#1088](https://github.com/KnpLabs/php-github-api/issues/1088) + +## 3.8.0 + +### Added +- API rate limit error status can be 403 ([matthewnessworthy](https://github.com/matthewnessworthy)) [#1072](https://github.com/KnpLabs/php-github-api/issues/1072) +- Add method to use generate release notes endpoint ([GuySartorelli](https://github.com/GuySartorelli)) [#1074](https://github.com/KnpLabs/php-github-api/issues/1074) +- Fix typehint for repository dispatch method ([cweagans](https://github.com/cweagans)) [#1066](https://github.com/KnpLabs/php-github-api/issues/1066) + +### Changed +- Update security.md ([secalith-code](https://github.com/secalith-code)) [#1076](https://github.com/KnpLabs/php-github-api/issues/1076) + +### Fixed +- dont require encoding ([gemal](https://github.com/gemal)) [#1071](https://github.com/KnpLabs/php-github-api/issues/1071) + +## 3.7.0 + +### Added +- added phpdocs ([staabm](https://github.com/staabm)) [#1068](https://github.com/KnpLabs/php-github-api/issues/1068) +- added missing magic method phpdocs for deployments ([staabm](https://github.com/staabm)) [#1069](https://github.com/KnpLabs/php-github-api/issues/1069) +- Fix issue https://github.com/KnpLabs/php-github-api/issues/1061 ([mruell](https://github.com/mruell)) [#1062](https://github.com/KnpLabs/php-github-api/issues/1062) + +### Changed +- Updates ReviewRequest Create method to return type Array ([ejntaylor](https://github.com/ejntaylor)) [#1060](https://github.com/KnpLabs/php-github-api/issues/1060) + +## 3.6.0 + +### Added +- Include optional params parameter for Commits compare method ([mountiny](https://github.com/mountiny)) [#1053](https://github.com/KnpLabs/php-github-api/issues/1053) + +### Changed +- Update incorrect documentation ([pheeque1](https://github.com/pheeque1)) [#1058](https://github.com/KnpLabs/php-github-api/issues/1058) + +### Fixed +- fix(Apps): use /orgs/ORG/installation ([ellisio](https://github.com/ellisio)) [#1056](https://github.com/KnpLabs/php-github-api/issues/1056) + +## 3.5.1 + +### Fixed +- Boolean private needed to create private repo! ([mruell](https://github.com/mruell)) [#1051](https://github.com/KnpLabs/php-github-api/issues/1051) + +## 3.5.0 + +### Added +- added support for psr\cache 3.0 ([rconfig](https://github.com/rconfig)) [#1046](https://github.com/KnpLabs/php-github-api/issues/1046) +- Symfony: allow deprecation-contracts version 3 ([glaubinix](https://github.com/glaubinix)) [#1049](https://github.com/KnpLabs/php-github-api/issues/1049) + +### Changed +- Fix internal doc link ([staudenmeir](https://github.com/staudenmeir)) [#1044](https://github.com/KnpLabs/php-github-api/issues/1044) + +### Fixed +- Fix Client URL Prepending For GraphQL Endpoint on Enterprise ([asher-goldberg](https://github.com/asher-goldberg), [acrobat](https://github.com/acrobat)) [#1048](https://github.com/KnpLabs/php-github-api/issues/1048) + +## 3.4.0 + +### Added +- Add create a repository using a template endpoint ([martinbean](https://github.com/martinbean)) [#994](https://github.com/KnpLabs/php-github-api/issues/994) +- Allow fetching repo readme for a specific ref ([bery](https://github.com/bery)) [#1019](https://github.com/KnpLabs/php-github-api/issues/1019) +- allow assigning role to organisation members ([luceos](https://github.com/luceos)) [#1018](https://github.com/KnpLabs/php-github-api/issues/1018) +- Branch lists . ( ? query per_page) ([pitonic](https://github.com/pitonic)) [#1020](https://github.com/KnpLabs/php-github-api/issues/1020) +- Php8.1 support ([acrobat](https://github.com/acrobat)) [#1025](https://github.com/KnpLabs/php-github-api/issues/1025) +- Allow psr/cache 2.0 as well as 1.0 ([johnnoel](https://github.com/johnnoel)) [#1029](https://github.com/KnpLabs/php-github-api/issues/1029) +- adding code_with_match (#1024) ([QuentinRa](https://github.com/QuentinRa)) [#1031](https://github.com/KnpLabs/php-github-api/issues/1031) +- Added dir parameter for Repo readme ([AlexandrePavy](https://github.com/AlexandrePavy)) [#1032](https://github.com/KnpLabs/php-github-api/issues/1032) +- refs #955: deprecate Client::AUTH_* constants and replace them with AuthMethod::AUTH_* const ([ipalo](https://github.com/ipalo)) [#1036](https://github.com/KnpLabs/php-github-api/issues/1036) +- feat: Add `visibility` option to repo create ([gerdemann](https://github.com/gerdemann)) [#1038](https://github.com/KnpLabs/php-github-api/issues/1038) +- Feature get authenticated app ([kdaniel95](https://github.com/kdaniel95)) [#1041](https://github.com/KnpLabs/php-github-api/issues/1041) + +### Changed +- Fix up typos ([dereuromark](https://github.com/dereuromark)) [#1011](https://github.com/KnpLabs/php-github-api/issues/1011) +- Update integration authentication documentation for usage with lcobucci/jwt ^4 ([glaubinix](https://github.com/glaubinix)) [#1017](https://github.com/KnpLabs/php-github-api/issues/1017) +- Update result_pager.md ([tomsowerby](https://github.com/tomsowerby)) [#1023](https://github.com/KnpLabs/php-github-api/issues/1023) +- fix(doc): links to doc in CurrentUser class ([Nek-](https://github.com/Nek-)) [#1026](https://github.com/KnpLabs/php-github-api/issues/1026) +- Fix incorrect phpdoc ([gemal](https://github.com/gemal)) [#1034](https://github.com/KnpLabs/php-github-api/issues/1034) + +### Fixed +- Add accept header for creating repo from template ([davidpeach](https://github.com/davidpeach)) [#1030](https://github.com/KnpLabs/php-github-api/issues/1030) + +## 3.3.0 + +### Added +- Allow costume accept headers for GraphQL Endpoint. ([Necmttn](https://github.com/Necmttn)) [#1001](https://github.com/KnpLabs/php-github-api/issues/1001) +- Add endpoint for approve workflow run ([Nyholm](https://github.com/Nyholm)) [#1006](https://github.com/KnpLabs/php-github-api/issues/1006) + +### Changed +- Update readme and add example for different http client usage ([acrobat](https://github.com/acrobat)) [#1002](https://github.com/KnpLabs/php-github-api/issues/1002) +- Bumped branch alias after new feature merged ([GrahamCampbell](https://github.com/GrahamCampbell)) [#1004](https://github.com/KnpLabs/php-github-api/issues/1004) +- Add comment on AbstractApi::$perPage() ([Nyholm](https://github.com/Nyholm)) [#1007](https://github.com/KnpLabs/php-github-api/issues/1007) + +### Fixed +- Fix publicKey ([Yurunsoft](https://github.com/Yurunsoft)) [#1005](https://github.com/KnpLabs/php-github-api/issues/1005) + +## 3.2.0 + +### Added +- Deprecate ResultPager::postFetch method ([acrobat](https://github.com/acrobat)) [#986](https://github.com/KnpLabs/php-github-api/issues/986) +- Add deprecations to the PR review methods to allow cleanup ([acrobat](https://github.com/acrobat)) [#984](https://github.com/KnpLabs/php-github-api/issues/984) +- Allow binary content downloads of assets ([acrobat](https://github.com/acrobat)) [#990](https://github.com/KnpLabs/php-github-api/issues/990) +- Deployments: added missing 'delete deployment' endpoint ([clxmstaab](https://github.com/clxmstaab)) [#991](https://github.com/KnpLabs/php-github-api/issues/991) +- Events list per authenticated user for all repos ([richard015ar](https://github.com/richard015ar)) [#1000](https://github.com/KnpLabs/php-github-api/issues/1000) + +### Changed +- Fixed branch alias ([GrahamCampbell](https://github.com/GrahamCampbell)) [#975](https://github.com/KnpLabs/php-github-api/issues/975) +- fix typo ([staabm](https://github.com/staabm)) [#977](https://github.com/KnpLabs/php-github-api/issues/977) +- Improved bc check ([acrobat](https://github.com/acrobat)) [#982](https://github.com/KnpLabs/php-github-api/issues/982) +- Correctly link to github actions docs and fix backlinks ([acrobat](https://github.com/acrobat)) [#983](https://github.com/KnpLabs/php-github-api/issues/983) +- Add missing repo hooks documentation ([acrobat](https://github.com/acrobat)) [#987](https://github.com/KnpLabs/php-github-api/issues/987) +- Fix incorrect public key documentation ([acrobat](https://github.com/acrobat)) [#988](https://github.com/KnpLabs/php-github-api/issues/988) +- Fixed incorrect parameters in apps docs ([acrobat](https://github.com/acrobat)) [#989](https://github.com/KnpLabs/php-github-api/issues/989) +- phpdoc: fix typo ([clxmstaab](https://github.com/clxmstaab)) [#993](https://github.com/KnpLabs/php-github-api/issues/993) +- Fix upmerged usage of deprecated phpunit assert ([acrobat](https://github.com/acrobat)) [#995](https://github.com/KnpLabs/php-github-api/issues/995) +- Fix typo ([romainneutron](https://github.com/romainneutron)) [#997](https://github.com/KnpLabs/php-github-api/issues/997) + +### Fixed +- Deployments: use proper media-type for in_progress/queued, inactive state ([staabm](https://github.com/staabm)) [#979](https://github.com/KnpLabs/php-github-api/issues/979) +- [952] doc - Specify lcobucci/jwt version, fix deprecation ([amacrobert-meq](https://github.com/amacrobert-meq), [acrobat](https://github.com/acrobat)) [#953](https://github.com/KnpLabs/php-github-api/issues/953) +- Replace deprecated organization team repository add/remove urls ([acrobat](https://github.com/acrobat)) [#985](https://github.com/KnpLabs/php-github-api/issues/985) +- fixed php warning in GithubExceptionThrower ([clxmstaab](https://github.com/clxmstaab), [acrobat](https://github.com/acrobat)) [#992](https://github.com/KnpLabs/php-github-api/issues/992) + +## 3.1.0 + +### Added +- Add workflow dispatch and allow workflow names. ([fodinabor](https://github.com/fodinabor)) [#969](https://github.com/KnpLabs/php-github-api/issues/969) + +### Changed +- Re-enable roave bc check for 3.x ([acrobat](https://github.com/acrobat)) [#958](https://github.com/KnpLabs/php-github-api/issues/958) +- Cleanup 3.0.0 changelog ([acrobat](https://github.com/acrobat)) [#957](https://github.com/KnpLabs/php-github-api/issues/957) +- Update new GitHub doc links in repo. ([fodinabor](https://github.com/fodinabor)) [#974](https://github.com/KnpLabs/php-github-api/issues/974) + +### Fixed +- Add accept header for the checks API ([Agares](https://github.com/Agares)) [#968](https://github.com/KnpLabs/php-github-api/issues/968) +- ExceptionThrower: adjust rate limit detection ([glaubinix](https://github.com/glaubinix)) [#959](https://github.com/KnpLabs/php-github-api/issues/959) + ## 3.0.0 ### Added diff --git a/CHANGELOG.md b/CHANGELOG.md index a5728ab245b..47980eff62f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## 2.20.0 + +### Added +- Deployments: added missing 'delete deployment' endpoint ([clxmstaab](https://github.com/clxmstaab)) [#991](https://github.com/KnpLabs/php-github-api/issues/991) + +### Changed +- phpdoc: fix typo ([clxmstaab](https://github.com/clxmstaab)) [#993](https://github.com/KnpLabs/php-github-api/issues/993) + +### Fixed +- fixed php warning in GithubExceptionThrower ([clxmstaab](https://github.com/clxmstaab), [acrobat](https://github.com/acrobat)) [#992](https://github.com/KnpLabs/php-github-api/issues/992) + +## 2.19.2 + +### Changed +- Improved bc check ([acrobat](https://github.com/acrobat)) [#982](https://github.com/KnpLabs/php-github-api/issues/982) +- Correctly link to github actions docs and fix backlinks ([acrobat](https://github.com/acrobat)) [#983](https://github.com/KnpLabs/php-github-api/issues/983) +- Add missing repo hooks documentation ([acrobat](https://github.com/acrobat)) [#987](https://github.com/KnpLabs/php-github-api/issues/987) +- Fix incorrect public key documentation ([acrobat](https://github.com/acrobat)) [#988](https://github.com/KnpLabs/php-github-api/issues/988) +- Fixed incorrect parameters in apps docs ([acrobat](https://github.com/acrobat)) [#989](https://github.com/KnpLabs/php-github-api/issues/989) + +### Fixed +- Deployments: use proper media-type for in_progress/queued, inactive state ([staabm](https://github.com/staabm)) [#979](https://github.com/KnpLabs/php-github-api/issues/979) +- backported #979 into 2.x ([staabm](https://github.com/staabm)) [#981](https://github.com/KnpLabs/php-github-api/issues/981) +- [952] doc - Specify lcobucci/jwt version, fix deprecation ([amacrobert-meq](https://github.com/amacrobert-meq), [acrobat](https://github.com/acrobat)) [#953](https://github.com/KnpLabs/php-github-api/issues/953) +- Replace deprecated organization team repository add/remove urls ([acrobat](https://github.com/acrobat)) [#985](https://github.com/KnpLabs/php-github-api/issues/985) + +## 2.19.1 + +### Fixed +- ExceptionThrower: adjust rate limit detection ([glaubinix](https://github.com/glaubinix)) [#959](https://github.com/KnpLabs/php-github-api/issues/959) + ## 2.19.0 ### Added diff --git a/README.md b/README.md index 6c3609177fa..de79112b4f8 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # PHP GitHub API -[![Build Status](https://travis-ci.org/KnpLabs/php-github-api.svg?branch=master)](https://travis-ci.org/KnpLabs/php-github-api) +![Build Status](https://github.com/KnpLabs/php-github-api/actions/workflows/ci.yml/badge.svg) [![StyleCI](https://styleci.io/repos/3948501/shield?style=flat)](https://styleci.io/repos/3948501) [![Latest Stable Version](https://poser.pugx.org/knplabs/github-api/v/stable)](https://packagist.org/packages/knplabs/github-api) [![Total Downloads](https://poser.pugx.org/knplabs/github-api/downloads)](https://packagist.org/packages/knplabs/github-api) -[![Latest Unstable Version](https://poser.pugx.org/knplabs/github-api/v/unstable)](https://packagist.org/packages/knplabs/github-api) [![Monthly Downloads](https://poser.pugx.org/knplabs/github-api/d/monthly)](https://packagist.org/packages/knplabs/github-api) [![Daily Downloads](https://poser.pugx.org/knplabs/github-api/d/daily)](https://packagist.org/packages/knplabs/github-api) @@ -19,34 +18,46 @@ Uses [GitHub API v3](http://developer.github.com/v3/) & supports [GitHub API v4] ## Requirements -* PHP >= 7.1 +* PHP >= 7.2 * A [PSR-17 implementation](https://packagist.org/providers/psr/http-factory-implementation) * A [PSR-18 implementation](https://packagist.org/providers/psr/http-client-implementation) -## Install +## Quick install Via [Composer](https://getcomposer.org). -### PHP 7.1+: +This command will get you up and running quickly with a Guzzle HTTP client. ```bash -composer require knplabs/github-api:^3.0 php-http/guzzle6-adapter:^2.0.1 http-interop/http-factory-guzzle:^1.0 +composer require knplabs/github-api:^3.0 guzzlehttp/guzzle:^7.0.1 http-interop/http-factory-guzzle:^1.0 ``` -### PHP 7.2+: +## Advanced install + +We are decoupled from any HTTP messaging client with help by [HTTPlug](https://httplug.io). + +### Using a different http client ```bash -composer require knplabs/github-api:^3.0 guzzlehttp/guzzle:^7.0.1 http-interop/http-factory-guzzle:^1.0 +composer require knplabs/github-api:^3.0 symfony/http-client nyholm/psr7 ``` -### Laravel 6+: +To set up the Github client with this HTTP client -```bash -composer require graham-campbell/github:^10.0 guzzlehttp/guzzle:^7.0.1 http-interop/http-factory-guzzle:^1.0 +```php +use Github\Client; +use Symfony\Component\HttpClient\HttplugClient; + +$client = Client::createWithHttpClient(new HttplugClient()); ``` -We are decoupled from any HTTP messaging client with help by [HTTPlug](http://httplug.io). Read about clients in our [docs](doc/customize.md). [graham-campbell/github](https://github.com/GrahamCampbell/Laravel-GitHub) is by [Graham Campbell](https://github.com/GrahamCampbell). +Read more about [using different clients in our docs](doc/customize.md). + +## Framework integrations + +### Laravel +To integrate this library in laravel [Graham Campbell](https://github.com/GrahamCampbell) created [graham-campbell/github](https://github.com/GrahamCampbell/Laravel-GitHub). See the [installation instructions](https://github.com/GrahamCampbell/Laravel-GitHub#installation) to get started in laravel. ## Basic usage of `php-github-api` client @@ -60,7 +71,7 @@ $client = new \Github\Client(); $repositories = $client->api('user')->repositories('ornicar'); ``` -From `$client` object, you can access to all GitHub. +From `$client` object, you have access to all available GitHub api endpoints. ## Cache usage @@ -105,18 +116,18 @@ See the [`doc` directory](doc/) for more detailed documentation. Please read [this post](https://knplabs.com/en/blog/news-for-our-foss-projects-maintenance) first. This library is maintained by the following people (alphabetically sorted) : -- @acrobat -- @Nyholm +- [@acrobat](https://github.com/acrobat) +- [@Nyholm](https://github.com/Nyholm) ## Contributors -- Thanks to [Thibault Duplessis aka. ornicar](http://github.com/ornicar) for his first version of this library. -- Thanks to [Joseph Bielawski aka. stloyd](http://github.com/stloyd) for his contributions and support. -- Thanks to [noloh](http://github.com/noloh) for his contribution on the Object API. -- Thanks to [bshaffer](http://github.com/bshaffer) for his contribution on the Repo API. -- Thanks to [Rolf van de Krol](http://github.com/rolfvandekrol) for his countless contributions. -- Thanks to [Nicolas Pastorino](http://github.com/jeanvoye) for his contribution on the Pull Request API. -- Thanks to [Edoardo Rivello](http://github.com/erivello) for his contribution on the Gists API. +- Thanks to [Thibault Duplessis aka. ornicar](https://github.com/ornicar) for his first version of this library. +- Thanks to [Joseph Bielawski aka. stloyd](https://github.com/stloyd) for his contributions and support. +- Thanks to [noloh](https://github.com/noloh) for his contribution on the Object API. +- Thanks to [bshaffer](https://github.com/bshaffer) for his contribution on the Repo API. +- Thanks to [Rolf van de Krol](https://github.com/rolfvandekrol) for his countless contributions. +- Thanks to [Nicolas Pastorino](https://github.com/jeanvoye) for his contribution on the Pull Request API. +- Thanks to [Edoardo Rivello](https://github.com/erivello) for his contribution on the Gists API. - Thanks to [Miguel Piedrafita](https://github.com/m1guelpf) for his contribution to the v4 & Apps API. - Thanks to [Emre DEGER](https://github.com/lexor) for his contribution to the Actions API. diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md index 8e0e3f5fa59..738343d6c37 100644 --- a/UPGRADE-3.0.md +++ b/UPGRADE-3.0.md @@ -13,7 +13,7 @@ * `Github\HttpClient\Plugin\History` * `Github\HttpClient\Plugin\PathPrepend` -### Authetication methods +### Authentication methods * `Github\Client::AUTH_URL_TOKEN` use `Github\Client::AUTH_ACCESS_TOKEN` instead. * `Github\Client::AUTH_URL_CLIENT_ID` use `Github\Client::AUTH_CLIENT_ID` instead. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md new file mode 100644 index 00000000000..6ede78deb51 --- /dev/null +++ b/UPGRADE-4.0.md @@ -0,0 +1,11 @@ +## UPGRADE from 3.x to 4.0 + +### ResultPager + +* `\Github\ResultPagerInterface::postFetch` is deprecated, and the method will be removed from the ResultPager interface/class. + +### Authentication methods + +* `Github\Client::AUTH_CLIENT_ID` is deprecated, use `Github\AuthMethod::CLIENT_ID` instead. +* `Github\Client::AUTH_ACCESS_TOKEN` is deprecated, use `Github\AuthMethod::ACCESS_TOKEN` instead. +* `Github\Client::AUTH_JWT` is deprecated, use `Github\AuthMethod::JWT` instead. diff --git a/composer.json b/composer.json index c6e2a7a476a..da450bc019d 100644 --- a/composer.json +++ b/composer.json @@ -19,27 +19,29 @@ "require": { "php": "^7.2.5 || ^8.0", "ext-json": "*", - "php-http/cache-plugin": "^1.7.1", + "php-http/cache-plugin": "^1.7.1|^2.0", "php-http/client-common": "^2.3", "php-http/discovery": "^1.12", "php-http/httplug": "^2.2", "php-http/multipart-stream-builder": "^1.1.2", - "psr/cache": "^1.0", + "psr/cache": "^1.0|^2.0|^3.0", "psr/http-client-implementation": "^1.0", "psr/http-factory-implementation": "^1.0", - "psr/http-message": "^1.0", - "symfony/polyfill-php80": "^1.17" + "psr/http-message": "^1.0|^2.0", + "symfony/polyfill-php80": "^1.17", + "symfony/deprecation-contracts": "^2.2|^3.0" }, "require-dev": { "symfony/cache": "^5.1.8", - "guzzlehttp/psr7": "^1.7", + "guzzlehttp/psr7": "^2.7", "http-interop/http-factory-guzzle": "^1.0", "guzzlehttp/guzzle": "^7.2", "php-http/mock-client": "^1.4.1", "phpstan/phpstan": "^0.12.57", "phpstan/extension-installer": "^1.0.5", "phpstan/phpstan-deprecation-rules": "^0.12.5", - "phpunit/phpunit": "^8.5 || ^9.4" + "phpunit/phpunit": "^8.5 || ^9.4", + "symfony/phpunit-bridge": "^5.2" }, "autoload": { "psr-4": { "Github\\": "lib/Github/" } @@ -49,8 +51,15 @@ }, "extra": { "branch-alias": { - "dev-2.x": "2.19.x-dev", - "dev-master": "3.0.x-dev" + "dev-2.x": "2.20.x-dev", + "dev-master": "3.16-dev" + } + }, + "config": { + "allow-plugins": { + "phpstan/extension-installer": true, + "composer/package-versions-deprecated": true, + "php-http/discovery": true } } } diff --git a/doc/README.md b/doc/README.md index 361cdaaba8b..17c3604dc35 100644 --- a/doc/README.md +++ b/doc/README.md @@ -14,6 +14,7 @@ v3 APIs: * [Public keys](currentuser/publickeys.md) * [Memberships](currentuser/memberships.md) * [Enterprise](enterprise.md) + * [Secret Scanning Alert](enterprise/secret-scanning.md) * [Gists](gists.md) * [Comments](gists/comments.md) * GitData @@ -39,6 +40,11 @@ v3 APIs: * [Organization](organization.md) * [Members](organization/members.md) * [Teams](organization/teams.md) + * [Self hosted runners](organization/actions/self_hosted_runners.md) + * [Secrets](organization/actions/secrets.md) + * [Variables](organization/actions/variables.md) + * [Secret Scanning Alert](organization/secret-scanning.md) + * [Organization Roles](organization/organization-roles.md) * [Projects](project/projects.md) * [Columns](project/columns.md) * [Cards](project/cards.md) @@ -48,10 +54,22 @@ v3 APIs: * [Reviews](pull_request/reviews.md) * [Rate Limits](rate_limits.md) * [Repositories](repos.md) + * Actions + * [Artifacts](repo/actions/artifacts.md) + * [Secrets](repo/actions/secrets.md) + * [Variables](repo/actions/variables.md) + * [Self hosted runners](repo/actions/self_hosted_runners.md) + * [Workflow jobs](repo/actions/workflow_jobs.md) + * [Workflow runs](repo/actions/workflow_runs.md) + * [Workflows](repo/actions/workflows.md) * [Check Runs](repo/check_runs.md) * [Check Suites](repo/check_suites.md) * [Contents](repo/contents.md) * [Deployments](repo/deployments.md) + * [Policies](repo/deployments/policies.md) + * [Environments](repo/deployments/environments.md) + * [Secrets](repo/deployments/environment/secrets.md) + * [Variables](repo/deployments/environment/variables.md) * [Labels](repo/labels.md) * [Protection](repo/protection.md) * [Releases](repo/releases.md) @@ -59,8 +77,10 @@ v3 APIs: * [Stargazers](repo/stargazers.md) * [Statuses](repo/statuses.md) * [Tags](repo/tags.md) + * [Secret Scanning Alert](repo/secret-scanning.md) * [Search](search.md) * [Users](users.md) + * [Migrations](user/migration.md) Additional features: diff --git a/doc/activity.md b/doc/activity.md index 7cad30ef5f7..48d7cfb423d 100644 --- a/doc/activity.md +++ b/doc/activity.md @@ -24,14 +24,21 @@ Returns an array of watched repos. > *** Requires [authentication](security.md). *** -### Get repos that a authenticated user has starred +### Get repos that an authenticated user has starred ```php $activity = $client->api('current_user')->starring()->all(); ``` Returns an array of starred repos. -### Get repos that a authenticated user has starred with creation date +### Get list of private and public events for an authenticated user for all repos + +```php +$activity = $client->api('user')->events('ornicar'); +``` +Returns an array of private and public events created for all repos related to the user. + +### Get repos that an authenticated user has starred with creation date Support for getting the star creation timestamp in the response, using the custom `Accept: application/vnd.github.v3.star+json` header. @@ -68,7 +75,7 @@ $activity = $client->api('current_user')->starring()->unstar($owner, $repo); Throws an Exception in case of failure or NULL in case of success. -### Get repos that a authenticated user is watching +### Get repos that an authenticated user is watching ```php $activity = $client->api('current_user')->watchers()->all(); @@ -100,4 +107,4 @@ $owner = "KnpLabs"; $repo = "php-github-api"; $activity = $client->api('current_user')->watchers()->unwatch($owner, $repo); ``` -Throws an Exception in case of failure or NULL in case of success. \ No newline at end of file +Throws an Exception in case of failure or NULL in case of success. diff --git a/doc/apps.md b/doc/apps.md index 7133ceb117a..14de9e4434d 100644 --- a/doc/apps.md +++ b/doc/apps.md @@ -31,23 +31,27 @@ $installations = $client->api('current_user')->installations(); List repositories that are accessible to the authenticated installation. ```php -$repositories = $client->api('apps')->listRepositories(456); +$repositories = $client->api('apps')->listRepositories($userId); ``` ### List repositories for a given installation and user ```php -$repositories = $client->api('current_user')->repositoriesByInstallation(456); +$repositories = $client->api('current_user')->repositoriesByInstallation($installationId, $parameters); ``` ### Add repository to installation -Add a single repository to an installation. ```php -$client->api('apps')->addRepository(123); +$client->api('apps')->addRepository($installationId, $repositoryId); ``` ### Remove repository from installation -Remove a single repository from an installation. ```php -$client->api('apps')->removeRepository(123); +$client->api('apps')->removeRepository($installationId, $repositoryId); +``` + +### Get authenticated app + +```php +$authenticatedApp = $client->api('apps')->getAuthenticatedApp(); ``` diff --git a/doc/authorizations.md b/doc/authorizations.md index 2865fd63e19..b037e402c27 100644 --- a/doc/authorizations.md +++ b/doc/authorizations.md @@ -15,18 +15,6 @@ $authorizations = $github->api('authorizations')->all(); $authorization = $github->api('authorizations')->show(1); ``` -#### Create an authorization - -```php -$data = array( - 'note' => 'This is an optional description' -); - -$authorization = $github->api('authorizations')->create($data); -``` - -Creates and returns an authorization. - #### Update an authorization You can update ``note``. diff --git a/doc/caching.md b/doc/caching.md index a95f92e9eea..1a004cc8781 100644 --- a/doc/caching.md +++ b/doc/caching.md @@ -26,5 +26,5 @@ $client->removeCache(); ``` Using cache, the client will get cached responses if resources haven't changed since last time, -**without** reaching the `X-Rate-Limit` [imposed by github](http://developer.github.com/v3/#rate-limiting). +**without** reaching the `X-Rate-Limit` [imposed by GitHub](http://developer.github.com/v3/#rate-limiting). diff --git a/doc/commits.md b/doc/commits.md index 741af0713a2..165d71ecae2 100644 --- a/doc/commits.md +++ b/doc/commits.md @@ -35,3 +35,11 @@ $commit = $client->api('repo')->commits()->compare('KnpLabs', 'php-github-api', ``` Returns an array of commits. + +### List pull requests associated with a commit + +```php +$commit = $client->api('repo')->commits()->pulls('KnpLabs', 'php-github-api', '839e5185da9434753db47959bee16642bb4f2ce4'); +``` + +Returns an array of pull requests. \ No newline at end of file diff --git a/doc/copilot/usage.md b/doc/copilot/usage.md new file mode 100644 index 00000000000..6005adc1600 --- /dev/null +++ b/doc/copilot/usage.md @@ -0,0 +1,80 @@ +# Copilot Usage API Documentation +[Back to the navigation](../README.md) + +## Overview + +The Copilot Usage API provides endpoints to retrieve usage summaries for organizations and enterprises. + +**Note**: This endpoint is in beta and is subject to change. + +## Endpoints + +### Organization Usage Summary + +Retrieve the usage summary for a specific organization. + +**Method:** `GET` + +**Endpoint:** `/orgs/{organization}/copilot/usage` + +**Parameters:** +- `organization` (string): The name of the organization. +- `params` (array, optional): Additional query parameters. + +**Example:** +```php +$usage = $client->api('copilotUsage')->orgUsageSummary('KnpLabs'); +``` + +### Organization Team Usage Summary + +Retrieve the usage summary for a specific team within an organization. + +**Method:** `GET` + +**Endpoint:** `/orgs/{organization}/team/{team}/copilot/usage` + +**Parameters:** +- `organization` (string): The name of the organization. +- `team` (string): The name of the team. +- `params` (array, optional): Additional query parameters. + +**Example:** +```php +$usage = $client->api('copilotUsage')->orgTeamUsageSummary('KnpLabs', 'developers'); +``` + +### Enterprise Usage Summary + +Retrieve the usage summary for a specific enterprise. + +**Method:** `GET` + +**Endpoint:** `/enterprises/{enterprise}/copilot/usage` + +**Parameters:** +- `enterprise` (string): The name of the enterprise. +- `params` (array, optional): Additional query parameters. + +**Example:** +```php +$usage = $client->api('copilotUsage')->enterpriseUsageSummary('KnpLabs'); +``` + +### Enterprise Team Usage Summary + +Retrieve the usage summary for a specific team within an enterprise. + +**Method:** `GET` + +**Endpoint:** `/enterprises/{enterprise}/team/{team}/copilot/usage` + +**Parameters:** +- `enterprise` (string): The name of the enterprise. +- `team` (string): The name of the team. +- `params` (array, optional): Additional query parameters. + +**Example:** +```php +$usage = $client->api('copilotUsage')->enterpriseTeamUsageSummary('KnpLabs', 'developers'); +``` diff --git a/doc/currentuser/publickeys.md b/doc/currentuser/publickeys.md index f0eb72ad421..444dd58fa0c 100644 --- a/doc/currentuser/publickeys.md +++ b/doc/currentuser/publickeys.md @@ -6,7 +6,7 @@ Wraps [GitHub User Public Keys API](https://developer.github.com/v3/users/keys/# ### List your public keys ```php -$keys = $client->user()->keys()->all(); +$keys = $client->me()->keys()->all(); ``` Returns a list of public keys for the authenticated user. @@ -14,7 +14,7 @@ Returns a list of public keys for the authenticated user. ### Shows a public key for the authenticated user. ```php -$key = $client->user()->keys()->show(1234); +$key = $client->me()->keys()->show(1234); ``` ### Add a public key to the authenticated user. @@ -22,15 +22,15 @@ $key = $client->user()->keys()->show(1234); > Requires [authentication](../security.md). ```php -$key = $client->user()->keys()->create(array('title' => 'key title', 'key' => 12345)); +$key = $client->me()->keys()->create(array('title' => 'key title', 'key' => 12345)); ``` -Adds a key with title 'key title' to the authenticated user and returns a the created key for the user. +Adds a key with title 'key title' to the authenticated user and returns the created key for the user. ### Remove a public key from the authenticated user. > Requires [authentication](../security.md). ```php -$client->user()->keys()->remove(12345); +$client->me()->keys()->remove(12345); ``` diff --git a/doc/currentuser/repositories.md b/doc/currentuser/repositories.md index a3e2922b20f..9b5e1d85e94 100644 --- a/doc/currentuser/repositories.md +++ b/doc/currentuser/repositories.md @@ -19,12 +19,12 @@ There are three values that can be passed into the `repositories` method: `type` | sort | `full_name` | `created`, `updated`, `pushed`, `full_name` | direction | `asc` | `asc`, `desc` -> See https://developer.github.com/v3/repos/#list-your-repositories for possible values and additional information +> See https://developer.github.com/v3/repos/#list-your-repositories for possible values and additional information #### Code Example: ```php -$client = new \Github\Client(); -$client->authenticate($github_token, null, \Github\Client::AUTH_ACCESS_TOKEN); +$client = new \Github\Client(); +$client->authenticate($github_token, null, \Github\AuthMethod::ACCESS_TOKEN); $client->currentUser()->repositories(); ``` diff --git a/doc/customize.md b/doc/customize.md index f25f4e40dc8..b475ee57322 100644 --- a/doc/customize.md +++ b/doc/customize.md @@ -4,16 +4,33 @@ ### Inject a new HTTP client instance -`php-github-api` relies on `php-http/discovery` to find an installed HTTP client. You may specify a HTTP client -yourself by calling `\Github\Client::setHttpClient`. A HTTP client must implement `Http\Client\HttpClient`. A list of +`php-github-api` relies on `php-http/discovery` to find an installed HTTP client. You may specify an HTTP client +yourself by calling `\Github\Client::setHttpClient`. An HTTP client must implement `Http\Client\HttpClient`. A list of community provided clients is found here: https://packagist.org/providers/php-http/client-implementation -You can inject a HTTP client through the `Github\Client` constructor: +You can inject an HTTP client through the `Github\Client` constructor: ```php $client = Github\Client::createWithHttpClient(new Http\Adapter\Guzzle6\Client()); ``` +#### Example + +To use the symfony http client + +```bash +composer require symfony/http-client nyholm/psr7 +``` + +To set up the GitHub client with this http client + +```php +use Github\Client; +use Symfony\Component\HttpClient\HttplugClient; + +$client = Client::createWithHttpClient(new HttplugClient()); +``` + ### Configure the HTTP client Wanna change, let's say, the HTTP client User Agent? You need to create a Plugin that modifies the diff --git a/doc/enterprise/secret-scanning.md b/doc/enterprise/secret-scanning.md new file mode 100644 index 00000000000..ad7626c4709 --- /dev/null +++ b/doc/enterprise/secret-scanning.md @@ -0,0 +1,10 @@ +## Enterprise / Secret Scanning API +[Back to the "Enterprise API"](../../enterprise.md) | [Back to the navigation](../../README.md) + +# List secret-scanning alerts for an Enterprise + +https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#list-secret-scanning-alerts-for-an-enterprise + +```php +$alerts = $client->api('enterprise')->secretScanning()->alerts('KnpLabs'); +``` diff --git a/doc/graphql.md b/doc/graphql.md index 4151012342c..dfe83639085 100644 --- a/doc/graphql.md +++ b/doc/graphql.md @@ -11,14 +11,27 @@ $rateLimits = $client->api('graphql')->execute($query); #### Authentication -To use [GitHub v4 API (GraphQL API)](http://developer.github.com/v4/) requests must [authenticated]((../security.md)). +To use [GitHub v4 API (GraphQL API)](http://developer.github.com/v4/) requests must [authenticate](security.md). ```php -$client->authenticate($token, null, Github\Client::AUTH_ACCESS_TOKEN); +$client->authenticate($token, null, Github\AuthMethod::ACCESS_TOKEN); $result = $client->api('graphql')->execute($query); ``` +#### Use different `Accept` Headers +You can preview upcoming features and changes to the GitHub GraphQL schema before they are added to the GitHub GraphQL API. +To access a schema preview, you'll need to provide a custom media type in the Accept header for your requests. Feature documentation for each preview specifies which custom media type to provide. More info about [Schema Previews](https://docs.github.com/en/graphql/overview/schema-previews). + +To use [GitHub v4 API (GraphQL API)](http://developer.github.com/v4/) with different `Accept` header you can pass third argument to execute method. + +```php +$result = $client->api('graphql')->execute($query, [], 'application/vnd.github.starfox-preview+json') +``` +> default accept header is `application/vnd.github.v4+json` + + + #### Use variables [Variables](https://developer.github.com/v4/guides/forming-calls/#working-with-variables) allow specifying of requested data without dynamical change of a query on a client side. @@ -38,7 +51,7 @@ $variables = [ 'organizationLogin' => 'KnpLabs' ]; -$client->authenticate('', null, Github\Client::AUTH_ACCESS_TOKEN); +$client->authenticate('', null, Github\AuthMethod::ACCESS_TOKEN); $orgInfo = $client->api('graphql')->execute($query, $variables); ``` diff --git a/doc/organization/actions/secrets.md b/doc/organization/actions/secrets.md index 113a37997ac..04b10877fa2 100644 --- a/doc/organization/actions/secrets.md +++ b/doc/organization/actions/secrets.md @@ -3,7 +3,7 @@ ### List organization secrets -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-organization-secrets +https://docs.github.com/en/rest/reference/actions#list-organization-secrets ```php $secrets = $client->organization()->secrets()->all('KnpLabs'); @@ -11,7 +11,7 @@ $secrets = $client->organization()->secrets()->all('KnpLabs'); ### Get an organization secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-an-organization-secret +https://docs.github.com/en/rest/reference/actions#get-an-organization-secret ```php $secret = $client->organization()->secrets()->show('KnpLabs', $secretName); @@ -19,7 +19,7 @@ $secret = $client->organization()->secrets()->show('KnpLabs', $secretName); ### Create an organization secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#create-or-update-an-organization-secret +https://docs.github.com/en/rest/reference/actions#create-or-update-an-organization-secret ```php $client->organization()->secrets()->create('KnpLabs', $secretName, [ @@ -31,7 +31,7 @@ $client->organization()->secrets()->create('KnpLabs', $secretName, [ ### Update an organization secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#create-or-update-an-organization-secret +https://docs.github.com/en/rest/reference/actions#create-or-update-an-organization-secret ```php $client->organization()->secrets()->update('KnpLabs', $secretName, [ @@ -43,7 +43,7 @@ $client->organization()->secrets()->update('KnpLabs', $secretName, [ ### Delete an organization secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-an-organization-secret +https://docs.github.com/en/rest/reference/actions#delete-an-organization-secret ```php $client->organization()->secrets()->remove('KnpLabs', $secretName); @@ -51,7 +51,7 @@ $client->organization()->secrets()->remove('KnpLabs', $secretName); ### List selected repositories for organization secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-selected-repositories-for-an-organization-secret +https://docs.github.com/en/rest/reference/actions#list-selected-repositories-for-an-organization-secret ```php $client->organization()->secrets()->selectedRepositories('KnpLabs', $secretName); @@ -59,7 +59,7 @@ $client->organization()->secrets()->selectedRepositories('KnpLabs', $secretName) ### Set selected repositories for an organization secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#set-selected-repositories-for-an-organization-secret +https://docs.github.com/en/rest/reference/actions#set-selected-repositories-for-an-organization-secret ```php $client->organization()->secrets()->setSelectedRepositories('KnpLabs', 'secretName', [ @@ -69,7 +69,7 @@ $client->organization()->secrets()->setSelectedRepositories('KnpLabs', 'secretNa ### Remove selected repository from an organization secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#remove-selected-repository-from-an-organization-secret +https://docs.github.com/en/rest/reference/actions#remove-selected-repository-from-an-organization-secret ```php $client->organization()->secrets()->addSecret('KnpLabs', $repositoryId, $secretName); @@ -77,7 +77,7 @@ $client->organization()->secrets()->addSecret('KnpLabs', $repositoryId, $secretN ### Get an organization public key -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-an-organization-public-key +https://docs.github.com/en/rest/reference/actions#get-an-organization-public-key ```php $client->organization()->secrets()->publicKey('KnpLabs'); diff --git a/doc/organization/actions/self_hosted_runners.md b/doc/organization/actions/self_hosted_runners.md new file mode 100644 index 00000000000..f6e915cdce5 --- /dev/null +++ b/doc/organization/actions/self_hosted_runners.md @@ -0,0 +1,51 @@ +## Organization / Actions / Self Hosted Runners API +[Back to the "Organization API"](../../organization.md) | [Back to the navigation](../../README.md) + +# List self-hosted runners for an Organization + +https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#list-self-hosted-runners-for-an-organization + +```php +$runners = $client->api('organization')->runners()->all('KnpLabs'); +``` + +# Get a self-hosted runner for an Organization + + https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#get-a-self-hosted-runner-for-an-organization + +```php +$runner = $client->api('organization')->runners()->show('KnpLabs', $runnerId); +``` + +# Delete a self-hosted runner from an Organization + +https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#delete-a-self-hosted-runner-from-an-organization + +```php +$client->api('organization')->runners()->remove('KnpLabs', $runnerId); +``` + +# List runner applications for an Organization + +https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#list-runner-applications-for-an-organization + +```php +$applications = $client->api('organization')->selfHostedRunners()->applications('KnpLabs'); +``` + +# List of all runners with Pagination + +```php +$api = $github->api('organization')->runners(); +$paginator = new Github\ResultPager($github); +$parameters = array('KnpLabs'); +$runners = $paginator->fetchAll($api, 'all', $parameters); + +do { + foreach ($runners['runners'] as $runner) { + // code + } + $runners = $paginator->fetchNext(); +} +while($paginator->hasNext()); +``` diff --git a/doc/organization/actions/variables.md b/doc/organization/actions/variables.md new file mode 100644 index 00000000000..89c641007f3 --- /dev/null +++ b/doc/organization/actions/variables.md @@ -0,0 +1,87 @@ +## Organization / Variables API +[Back to the "Organization API"](../organization.md) | [Back to the navigation](../README.md) + +### List organization variables + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#list-organization-variables + +```php +$variables = $client->organization()->variables()->all('KnpLabs'); +``` + +### Get an organization variable + +https://docs.github.com/en/rest/reference/actions#get-an-organization-secret + +```php +$variable = $client->organization()->variables()->show('KnpLabs', $variableName); +``` + +### Create an organization variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#create-an-organization-variable + +```php +$client->organization()->variables()->create('KnpLabs', [ + 'name' => $name, + 'value' => $value, + 'visibility' => $visibility, + 'selected_repository_ids' => $selectedRepositoryIds, +]); +``` + +### Update an organization variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#update-an-organization-variable + +```php +$client->organization()->variables()->update('KnpLabs', $variableName, [ + 'name' => $name, + 'value' => $value, + 'visibility' => $visibility, + 'selected_repository_ids' => $selectedRepositoryIds +]); +``` + +### Delete an organization variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#delete-an-organization-variable + +```php +$client->organization()->variables()->remove('KnpLabs', $variableName); +``` + +### List selected repositories for organization variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#list-selected-repositories-for-an-organization-variable + +```php +$client->organization()->variables()->selectedRepositories('KnpLabs', $variableName); +``` + +### Set selected repositories for an organization variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#set-selected-repositories-for-an-organization-variable + +```php +$client->organization()->variables()->setSelectedRepositories('KnpLabs', 'variableName', [ + 'selected_repository_ids' => [1, 2, 3], +]); +``` + +### Add selected repository to an organization variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#add-selected-repository-to-an-organization-variable + +```php +$client->organization()->variables()->addRepository('KnpLabs', $repositoryId, $variableName); +``` + +### Remove selected repository from an organization variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#remove-selected-repository-from-an-organization-variable + +```php +$client->organization()->variables()->removeRepository('KnpLabs', $repositoryId, $variableName); +``` + diff --git a/doc/organization/organization-roles.md b/doc/organization/organization-roles.md new file mode 100644 index 00000000000..a320b6eb047 --- /dev/null +++ b/doc/organization/organization-roles.md @@ -0,0 +1,108 @@ +## Organization / Webhooks API +[Back to the navigation](../README.md) + +Listing, showing, assigning, and removing orgniazationroles. +Wraps [GitHub Organization Roles API](https://docs.github.com/en/rest/orgs/organization-roles). + +Additional APIs: +* [Organization](../doc/organization) + +### List all organizaton roles in an organization + +> Requires [authentication](../security.md). + +```php +$roles = $client->organization()->organizationRoles()->all('acme'); +``` + +Returns a counter and a list of organization roles in the organization. + +### Get an organization role in an organization + +> Requires [authentication](../security.md). + +```php +$role = $client->organization()->organizationRoles()->show('acme', 123); +``` + +Returns a single organization role in the organization. + +### List all teams with role assigned in an organization + +> Requires [authentication](../security.md). + +```php +$users = $client->organization()->organizationRoles()->listTeamsWithRole('acme', 1); +``` + +Returns a list of teams with the role assigned to them. + +### Assign a single role to a team in an organization + +> Requires [authentication](../security.md). + +```php +$client->organization()->organizationRoles()->assignRoleToTeam('acme', 1, 'admin-user'); +``` + +No content is returned. + +### Remove a single role from a team in an organization + +> Requires [authentication](../security.md). + +```php +$client->organization()->organizationRoles()->removeRoleFromTeam('acme', 1, 'admin-team'); +``` + +No content is returned. + +### Remove all roles from a team in an organization + +> Requires [authentication](../security.md). + +```php +$client->organization()->organizationRoles()->removeAllRolesFromTeam('acme', 'admin-team'); +``` + +No content is returned. + +### List all users with role assigned in an organization + +> Requires [authentication](../security.md). + +```php +$users = $client->organization()->organizationRoles()->listUsersWithRole('acme', 1); +``` + +Returns a list of users with the role assigned to them. + +### Assign a single role to a user in an organization + +> Requires [authentication](../security.md). + +```php +$client->organization()->organizationRoles()->assignRoleToUser('acme', 1, 'admin-user'); +``` + +No content is returned. + +### Remove a single role from a user in an organization + +> Requires [authentication](../security.md). + +```php +$client->organization()->organizationRoles()->removeRoleFromUser('acme', 1, 'admin-user'); +``` + +No content is returned. + +### Remove all roles from a user in an organization + +> Requires [authentication](../security.md). + +```php +$client->organization()->organizationRoles()->removeAllRolesFromUser('acme', 'admin-user'); +``` + +No content is returned. diff --git a/doc/organization/secret-scanning.md b/doc/organization/secret-scanning.md new file mode 100644 index 00000000000..9ee5d4d972d --- /dev/null +++ b/doc/organization/secret-scanning.md @@ -0,0 +1,10 @@ +## Organization / Secret Scanning API +[Back to the "Organization API"](../../organization.md) | [Back to the navigation](../../README.md) + +# List secret-scanning alerts for an Organization + +https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#list-secret-scanning-alerts-for-an-organization + +```php +$alerts = $client->api('organization')->secretScanning()->alerts('KnpLabs'); +``` diff --git a/doc/project/projects.md b/doc/project/projects.md index 5763e0060e7..103bbe10c86 100644 --- a/doc/project/projects.md +++ b/doc/project/projects.md @@ -1,10 +1,10 @@ ## Repo / Projects API [Back to the "Repos API"](../) | [Back to the navigation](../README.md) -This api is currently only available to developers in Early Access. To access the API during the Early Access period, +This api is currently only available to developers in Early Access. To access the API during the Early Access period, you must provide a custom media type in the Accept header. -Both repositories and organisations have projects. The api is only different for gettings all or a single project. +Both repositories and organisations have projects. The api is only different for getting all or a single project. All the example use the repository projects api but this also works form the organization api (`$client->api('org_projects')`) ```php diff --git a/doc/pull_request/comments.md b/doc/pull_request/comments.md index 87ca5f8e443..e996f804989 100644 --- a/doc/pull_request/comments.md +++ b/doc/pull_request/comments.md @@ -67,7 +67,7 @@ $comment = $client->api('pull_request')->comments()->update('KnpLabs', 'php-gith This returns the details of the updated comment. -### Remove a review comment from an pull request +### Remove a review comment from a pull request > Requires [authentication](../security.md). diff --git a/doc/repo/actions/artifacts.md b/doc/repo/actions/artifacts.md index b457f12c806..58d68ff66e8 100644 --- a/doc/repo/actions/artifacts.md +++ b/doc/repo/actions/artifacts.md @@ -1,9 +1,9 @@ -## Repo / Artifacts API -[Back to the "Repos API"](../repos.md) | [Back to the navigation](../README.md) +## Repo / Actions / Artifacts API +[Back to the "Repos API"](../../repos.md) | [Back to the navigation](../../README.md) ### List artifacts for a repository -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-artifacts-for-a-repository +https://docs.github.com/en/rest/reference/actions#list-artifacts-for-a-repository ```php $artifacts = $client->api('repo')->artifacts()->all('KnpLabs'); @@ -11,7 +11,7 @@ $artifacts = $client->api('repo')->artifacts()->all('KnpLabs'); ### List workflow run artifacts -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-workflow-run-artifacts +https://docs.github.com/en/rest/reference/actions#list-workflow-run-artifacts ```php $runArtifacts = $client->api('repo')->artifacts()->runArtifacts('KnpLabs', 'php-github-api', $runId); @@ -19,7 +19,7 @@ $runArtifacts = $client->api('repo')->artifacts()->runArtifacts('KnpLabs', 'php- ### Get an artifact -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-an-artifact +https://docs.github.com/en/rest/reference/actions#get-an-artifact ```php $artifact = $client->api('repo')->artifacts()->show('KnpLabs', 'php-github-api', $artifactId); @@ -27,7 +27,7 @@ $artifact = $client->api('repo')->artifacts()->show('KnpLabs', 'php-github-api', ### Delete an artifact -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-an-artifact +https://docs.github.com/en/rest/reference/actions#delete-an-artifact ```php $client->api('repo')->artifacts()->delete('KnpLabs', 'php-github-api', $artifactId); @@ -36,7 +36,7 @@ $client->api('repo')->artifacts()->delete('KnpLabs', 'php-github-api', $artifact ### Download an artifact -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#download-an-artifact +https://docs.github.com/en/rest/reference/actions#download-an-artifact ```php $artifactFile = $client->api('repo')->artifacts()->download('KnpLabs', 'php-github-api', $artifactId, $format = 'zip'); diff --git a/doc/repo/actions/secrets.md b/doc/repo/actions/secrets.md index 037409fd53e..d4769639d37 100644 --- a/doc/repo/actions/secrets.md +++ b/doc/repo/actions/secrets.md @@ -1,9 +1,9 @@ -## Repo / Secrets API -[Back to the "Repos API"](../repos.md) | [Back to the navigation](../README.md) +## Repo / Actions / Secrets API +[Back to the "Repos API"](../../repos.md) | [Back to the navigation](../../README.md) ### List repository secrets -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-repository-secrets +https://docs.github.com/en/rest/reference/actions#list-repository-secrets ```php $secrets = $client->api('repo')->secrets()->all('KnpLabs', 'php-github-api'); @@ -11,7 +11,7 @@ $secrets = $client->api('repo')->secrets()->all('KnpLabs', 'php-github-api'); ### Get a repository secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-repository-secret +https://docs.github.com/en/rest/reference/actions#get-a-repository-secret ```php $secret = $client->api('repo')->secrets()->show('KnpLabs', 'php-github-api', $secretName); @@ -19,7 +19,7 @@ $secret = $client->api('repo')->secrets()->show('KnpLabs', 'php-github-api', $se ### Create a repository secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#create-or-update-a-repository-secret +https://docs.github.com/en/rest/reference/actions#create-or-update-a-repository-secret ```php $client->api('repo')->secrets()->create('KnpLabs', 'php-github-api', $secretName, [ @@ -29,7 +29,7 @@ $client->api('repo')->secrets()->create('KnpLabs', 'php-github-api', $secretName ### Update a repository secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#create-or-update-a-repository-secret +https://docs.github.com/en/rest/reference/actions#create-or-update-a-repository-secret ```php $client->api('repo')->secrets()->update('KnpLabs', 'php-github-api', $secretName, [ @@ -39,7 +39,7 @@ $client->api('repo')->secrets()->update('KnpLabs', 'php-github-api', $secretName ### Delete a repository secret -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-a-repository-secret +https://docs.github.com/en/rest/reference/actions#delete-a-repository-secret ```php $client->api('repo')->secrets()->remove('KnpLabs', 'php-github-api', $secretName); @@ -47,7 +47,7 @@ $client->api('repo')->secrets()->remove('KnpLabs', 'php-github-api', $secretName ### Get a repository public key -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-repository-public-key +https://docs.github.com/en/rest/reference/actions#get-a-repository-public-key ```php $publicKey = $client->api('repo')->secrets()->publicKey('KnpLabs', 'php-github-api'); diff --git a/doc/repo/actions/self_hosted_runners.md b/doc/repo/actions/self_hosted_runners.md index 1c09767d6cd..55a1ed0e420 100644 --- a/doc/repo/actions/self_hosted_runners.md +++ b/doc/repo/actions/self_hosted_runners.md @@ -1,9 +1,9 @@ -## Repo / Self Hosted Runners API -[Back to the "Repos API"](../repos.md) | [Back to the navigation](../README.md) +## Repo / Actions / Self Hosted Runners API +[Back to the "Repos API"](../../repos.md) | [Back to the navigation](../../README.md) # List self-hosted runners for a repository -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-self-hosted-runners-for-a-repository +https://docs.github.com/en/rest/reference/actions#list-self-hosted-runners-for-a-repository ```php $runners = $client->api('repo')->selfHostedRunners()->all('KnpLabs', 'php-github-api'); @@ -11,7 +11,7 @@ $runners = $client->api('repo')->selfHostedRunners()->all('KnpLabs', 'php-github # Get a self-hosted runner for a repository -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-self-hosted-runner-for-a-repository +https://docs.github.com/en/rest/reference/actions#get-a-self-hosted-runner-for-a-repository ```php $runner = $client->api('repo')->selfHostedRunners()->show('KnpLabs', 'php-github-api', $runnerId); @@ -19,7 +19,7 @@ $runner = $client->api('repo')->selfHostedRunners()->show('KnpLabs', 'php-github # Delete a self-hosted runner from a repository -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-a-self-hosted-runner-from-a-repository +https://docs.github.com/en/rest/reference/actions#delete-a-self-hosted-runner-from-a-repository ```php $client->api('repo')->selfHostedRunners()->remove('KnpLabs', 'php-github-api', $runnerId); @@ -27,7 +27,7 @@ $client->api('repo')->selfHostedRunners()->remove('KnpLabs', 'php-github-api', $ # List runner applications for a repository -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-runner-applications-for-a-repository +https://docs.github.com/en/rest/reference/actions#list-runner-applications-for-a-repository ```php $applications = $client->api('repo')->selfHostedRunners()->applications('KnpLabs', 'php-github-api'); diff --git a/doc/repo/actions/variables.md b/doc/repo/actions/variables.md new file mode 100644 index 00000000000..c6cc26ac1df --- /dev/null +++ b/doc/repo/actions/variables.md @@ -0,0 +1,48 @@ +## Repo / Actions / Variables API +[Back to the "Repos API"](../../repos.md) | [Back to the navigation](../../README.md) + +### List repository variables + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#list-repository-variables + +```php +$variables = $client->api('repo')->variables()->all('KnpLabs', 'php-github-api'); +``` + +### Get a repository variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#get-a-repository-variable + +```php +$variable = $client->api('repo')->variables()->show('KnpLabs', 'php-github-api', $variableName); +``` + +### Create a repository variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#create-a-repository-variable + +```php +$client->api('repo')->variables()->create('KnpLabs', 'php-github-api', [ + 'name' => $name, + 'value' => $value, +]); +``` + +### Update a repository variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#update-a-repository-variable + +```php +$client->api('repo')->variables()->update('KnpLabs', 'php-github-api', $variableName, [ + 'name' => $name, + 'value' => $value, +]); +``` + +### Delete a repository variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#delete-a-repository-variable + +```php +$client->api('repo')->variables()->remove('KnpLabs', 'php-github-api', $variableName); +``` diff --git a/doc/repo/actions/workflow_jobs.md b/doc/repo/actions/workflow_jobs.md index 151c59c5e95..62467353c53 100644 --- a/doc/repo/actions/workflow_jobs.md +++ b/doc/repo/actions/workflow_jobs.md @@ -1,9 +1,9 @@ -## Repo / Workflow Jobs API -[Back to the "Repos API"](../repos.md) | [Back to the navigation](../README.md) +## Repo / Actions / Workflow Jobs API +[Back to the "Repos API"](../../repos.md) | [Back to the navigation](../../README.md) ### List jobs for a workflow run -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-jobs-for-a-workflow-run +https://docs.github.com/en/rest/reference/actions#list-jobs-for-a-workflow-run ```php $client->api('repo')->workflowJobs()->all('KnpLabs', 'php-github-api', $runId); @@ -11,7 +11,7 @@ $client->api('repo')->workflowJobs()->all('KnpLabs', 'php-github-api', $runId); ### Get a job for a workflow run -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-job-for-a-workflow-run +https://docs.github.com/en/rest/reference/actions#get-a-job-for-a-workflow-run ```php $job = $client->api('repo')->workflowJobs()->all('KnpLabs', 'php-github-api', $jobId); @@ -19,7 +19,7 @@ $job = $client->api('repo')->workflowJobs()->all('KnpLabs', 'php-github-api', $j ### Download job logs for a workflow run -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#download-job-logs-for-a-workflow-run +https://docs.github.com/en/rest/reference/actions#download-job-logs-for-a-workflow-run ```php $jobLogs = $client->api('repo')->workflowJobs()->downloadLogs('KnpLabs', 'php-github-api', $jobId); diff --git a/doc/repo/actions/workflow_runs.md b/doc/repo/actions/workflow_runs.md index 88c6da7c621..4b879ca5b98 100644 --- a/doc/repo/actions/workflow_runs.md +++ b/doc/repo/actions/workflow_runs.md @@ -1,9 +1,9 @@ -## Repo / Workflow Runs API -[Back to the "Repos API"](../repos.md) | [Back to the navigation](../README.md) +## Repo / Actions / Workflow Runs API +[Back to the "Repos API"](../../repos.md) | [Back to the navigation](../../README.md) ### List workflow runs for a repository -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-workflow-runs-for-a-repository +https://docs.github.com/en/rest/reference/actions#list-workflow-runs-for-a-repository ```php $workflowRuns = $client->api('repo')->workflowRuns()->all('KnpLabs', 'php-github-api'); @@ -11,15 +11,15 @@ $workflowRuns = $client->api('repo')->workflowRuns()->all('KnpLabs', 'php-github ### List workflow runs -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-workflow-runs +https://docs.github.com/en/rest/reference/actions#list-workflow-runs ```php -$runs = $client->api('repo')->workflowRuns()->listRuns('KnpLabs', 'php-github-api', $workflowId); +$runs = $client->api('repo')->workflowRuns()->listRuns('KnpLabs', 'php-github-api', $workflow); ``` ### Get a workflow run -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-workflow-run +https://docs.github.com/en/rest/reference/actions#get-a-workflow-run ```php $workflowRun = $client->api('repo')->workflowRuns()->show('KnpLabs', 'php-github-api', $runId); @@ -27,7 +27,7 @@ $workflowRun = $client->api('repo')->workflowRuns()->show('KnpLabs', 'php-github ### Delete a workflow run -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-a-workflow-run +https://docs.github.com/en/rest/reference/actions#delete-a-workflow-run ```php $client->api('repo')->workflowRuns()->remove('KnpLabs', 'php-github-api', $runId); @@ -35,7 +35,7 @@ $client->api('repo')->workflowRuns()->remove('KnpLabs', 'php-github-api', $runId ### Re-run a workflow -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#re-run-a-workflow +https://docs.github.com/en/rest/reference/actions#re-run-a-workflow ```php $client->api('repo')->workflowRuns()->rerun('KnpLabs', 'php-github-api', $runId); @@ -43,7 +43,7 @@ $client->api('repo')->workflowRuns()->rerun('KnpLabs', 'php-github-api', $runId) ### Cancel a workflow run -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#cancel-a-workflow-run +https://docs.github.com/en/rest/reference/actions#cancel-a-workflow-run ```php $client->api('repo')->workflowRuns()->cancel('KnpLabs', 'php-github-api', $runId); @@ -51,7 +51,7 @@ $client->api('repo')->workflowRuns()->cancel('KnpLabs', 'php-github-api', $runId ### Get workflow run usage -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-workflow-run-usage +https://docs.github.com/en/rest/reference/actions#get-workflow-run-usage ```php $workflowUsage = $client->api('repo')->workflowRuns()->usage('KnpLabs', 'php-github-api', $runId); @@ -59,7 +59,7 @@ $workflowUsage = $client->api('repo')->workflowRuns()->usage('KnpLabs', 'php-git ### Download workflow run logs -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#download-workflow-run-logs +https://docs.github.com/en/rest/reference/actions#download-workflow-run-logs ```php $logs = $client->api('repo')->workflowRuns()->downloadLogs('KnpLabs', 'php-github-api', $runId); @@ -69,8 +69,16 @@ file_put_contents('logs.zip', $logs); ### Delete workflow run logs -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-workflow-run-logs +https://docs.github.com/en/rest/reference/actions#delete-workflow-run-logs ```php $client->api('repo')->workflowRuns()->deleteLogs('KnpLabs', 'php-github-api', $runId); ``` + +### Approve workflow run + +https://docs.github.com/en/rest/reference/actions#approve-a-workflow-run-for-a-fork-pull-request + +```php +$client->api('repo')->workflowRuns()->approve('KnpLabs', 'php-github-api', $runId); +``` diff --git a/doc/repo/actions/workflows.md b/doc/repo/actions/workflows.md index d6689d90aa2..91839cf0ecf 100644 --- a/doc/repo/actions/workflows.md +++ b/doc/repo/actions/workflows.md @@ -1,9 +1,9 @@ -## Repo / Workflows API -[Back to the "Repos API"](../repos.md) | [Back to the navigation](../README.md) +## Repo / Actions / Workflows API +[Back to the "Repos API"](../../repos.md) | [Back to the navigation](../../README.md) ### List repository workflows -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-repository-workflows +https://docs.github.com/en/rest/reference/actions#list-repository-workflows ```php $workflows = $client->api('repo')->workflows()->all('KnpLabs', 'php-github-api'); @@ -11,16 +11,24 @@ $workflows = $client->api('repo')->workflows()->all('KnpLabs', 'php-github-api') ### Get a workflow -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-workflow +https://docs.github.com/en/rest/reference/actions#get-a-workflow ```php -$workflow = $client->api('repo')->workflows()->show('KnpLabs', 'php-github-api', $workflowId); +$workflow = $client->api('repo')->workflows()->show('KnpLabs', 'php-github-api', $workflow); ``` ### Get workflow usage -https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-workflow-usage +https://docs.github.com/en/rest/reference/actions#get-workflow-usage ```php -$usage = $client->api('repo')->workflows()->usage('KnpLabs', 'php-github-api', $workflowId); +$usage = $client->api('repo')->workflows()->usage('KnpLabs', 'php-github-api', $workflow); +``` + +### Dispatch a workflow + +https://docs.github.com/en/rest/reference/actions#create-a-workflow-dispatch-event + +```php +$client->api('repo')->workflows()->dispatches('KnpLabs', 'php-github-api', $workflow, 'main'); ``` diff --git a/doc/repo/assets.md b/doc/repo/assets.md index 3df3eae2b72..93234929074 100644 --- a/doc/repo/assets.md +++ b/doc/repo/assets.md @@ -13,6 +13,12 @@ $assets = $client->api('repo')->releases()->assets()->all('twbs', 'bootstrap', $ $asset = $client->api('repo')->releases()->assets()->show('twbs', 'bootstrap', $assetId); ``` +### Download binary content of asset + +```php +$asset = $client->api('repo')->releases()->assets()->show('twbs', 'bootstrap', $assetId, true); +``` + ### Create an asset ```php diff --git a/doc/repo/check_runs.md b/doc/repo/check_runs.md index 87109e07e69..3b7b69b8f86 100644 --- a/doc/repo/check_runs.md +++ b/doc/repo/check_runs.md @@ -3,7 +3,7 @@ ### Create a check run -[Visit GitHub for a full of list of parameters and their descriptions.](https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#create-a-check-run) +[Visit GitHub for a full of list of parameters and their descriptions.](https://docs.github.com/en/rest/reference/checks#create-a-check-run) ```php $params = [ @@ -17,7 +17,7 @@ $check = $client->api('repo')->checkRuns()->create('KnpLabs', 'php-github-api', ### Get a check run -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#get-a-check-run +https://docs.github.com/en/rest/reference/checks#get-a-check-run ```php $check = $client->api('repo')->checkRuns()->show('KnpLabs', 'php-github-api', $checkRunId); @@ -25,7 +25,7 @@ $check = $client->api('repo')->checkRuns()->show('KnpLabs', 'php-github-api', $c ### Update an existing check run -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#update-a-check-run +https://docs.github.com/en/rest/reference/checks#update-a-check-run ```php $params = [ @@ -38,7 +38,7 @@ $check = $client->api('repo')->checkRuns()->update('KnpLabs', 'php-github-api', ### List check run annotations -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#list-check-run-annotations +https://docs.github.com/en/rest/reference/checks#list-check-run-annotations ```php $annotations = $client->api('repo')->checkRuns()->annotations('KnpLabs', 'php-github-api', $checkRunId); @@ -46,7 +46,7 @@ $annotations = $client->api('repo')->checkRuns()->annotations('KnpLabs', 'php-gi ### List check runs for a check suite -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#list-check-runs-in-a-check-suite +https://docs.github.com/en/rest/reference/checks#list-check-runs-in-a-check-suite ```php $params = [/*...*/]; @@ -55,13 +55,17 @@ $checks = $client->api('repo')->checkRuns()->allForCheckSuite('KnpLabs', 'php-gi ### List check runs for a Git reference -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#list-check-runs-for-a-git-reference +https://docs.github.com/en/rest/reference/checks#list-check-runs-for-a-git-reference ```php $params = [/*...*/]; $checks = $client->api('repo')->checkRuns()->allForReference('KnpLabs', 'php-github-api', $reference, $params); ``` +### Rerequest a check run +https://docs.github.com/en/rest/reference/checks#rerequest-a-check-run - +```php +$checks = $client->api('repo')->checkRuns()->rerequest('KnpLabs', 'php-github-api', $checkRunId); +``` diff --git a/doc/repo/check_suites.md b/doc/repo/check_suites.md index 7131674b510..b91c8199813 100644 --- a/doc/repo/check_suites.md +++ b/doc/repo/check_suites.md @@ -3,7 +3,7 @@ ### Create a check suite -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#create-a-check-suite +https://docs.github.com/en/rest/reference/checks#create-a-check-suite ```php $params = [ @@ -14,7 +14,7 @@ $check = $client->api('repo')->checkSuites()->create('KnpLabs', 'php-github-api' ### Update check suite preferences -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#update-repository-preferences-for-check-suites +https://docs.github.com/en/rest/reference/checks#update-repository-preferences-for-check-suites ```php $params = [/*...*/]; @@ -23,7 +23,7 @@ $check = $client->api('repo')->checkSuites()->updatePreferences('KnpLabs', 'php- ### Get a check suite -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#get-a-check-suite +https://docs.github.com/en/rest/reference/checks#get-a-check-suite ```php $check = $client->api('repo')->checkSuites()->getCheckSuite('KnpLabs', 'php-github-api', $checkSuiteId); @@ -31,7 +31,7 @@ $check = $client->api('repo')->checkSuites()->getCheckSuite('KnpLabs', 'php-gith ### Rerequest a check suite -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#rerequest-a-check-suite +https://docs.github.com/en/rest/reference/checks#rerequest-a-check-suite ```php $annotations = $client->api('repo')->checkSuites()->rerequest('KnpLabs', 'php-github-api', $checkSuiteId); @@ -40,7 +40,7 @@ $annotations = $client->api('repo')->checkSuites()->rerequest('KnpLabs', 'php-gi ### List check suites for a Git reference -https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#list-check-suites-for-a-git-reference +https://docs.github.com/en/rest/reference/checks#list-check-suites-for-a-git-reference ```php $params = [/*...*/]; diff --git a/doc/repo/deployments.md b/doc/repo/deployments.md index 740bac4dd0c..8c2ae1a8675 100644 --- a/doc/repo/deployments.md +++ b/doc/repo/deployments.md @@ -21,7 +21,7 @@ $deployments = $client->api('deployment')->all('KnpLabs', 'php-github-api', arra $deployment = $client->api('deployment')->show('KnpLabs', 'php-github-api', $id); ``` -#### Create a new deployments. +#### Create a new deployment. The `ref` parameter is required. @@ -31,9 +31,19 @@ $data = $client->api('deployment')->create('KnpLabs', 'php-github-api', array('r Please note that once a deployment is created it cannot be edited. Only status updates can be created. +#### Delete a existing deployment. + +```php +$deployment = $client->api('deployment')->show('KnpLabs', 'php-github-api', $id); +``` + +Please note that a deployment can only be deleted when in inactive state. +Consider transitioning the status to `inactive` beforehand using `updateStatus`. + + #### Create a new status update. -The `state` parameter is required. At the time of writing, this must be pending, success, error, or failure. +The `state` parameter is required. At the time of writing, this must be pending, queued, in_progress, success, inactive, error, or failure. ```php $data = $client->api('deployment')->updateStatus('KnpLabs', 'php-github-api', 1, array('state' => 'error', 'description' => 'syntax error')); diff --git a/doc/repo/deployments/environment/secrets.md b/doc/repo/deployments/environment/secrets.md new file mode 100644 index 00000000000..5c0c86b85d7 --- /dev/null +++ b/doc/repo/deployments/environment/secrets.md @@ -0,0 +1,46 @@ +## Environment / Secrets API +[Back to the "Environments API"](../environments.md) | [Back to the navigation](../README.md) + +### List environment secrets + +https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28 + +```php +$secrets = $client->environment()->secrets()->all($repoId, $envName); +``` + +### Get an environment secret + +https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#get-an-environment-secret + +```php +$secret = $client->environment()->secrets()->show($repoId, $envName, $secretName); +``` + +### Create or Update an environment secret + +https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#create-or-update-an-environment-secret + +```php +$client->environment()->secrets()->createOrUpdate($repoId, $envName, $secretName, [ + 'encrypted_value' => $encryptedValue, + 'key_id' => $key_id +]); +``` + +### Delete an environment secret + +https://docs.github.com/en/rest/reference/actions#delete-an-organization-secret + +```php +$client->environment()->secrets()->remove($repoId, $envName, $secretName); +``` + +### Get an environment public key + +https://docs.github.com/en/rest/reference/actions#get-an-organization-public-key + +```php +$client->environment()->secrets()->publicKey($repoId, $envName); +``` + diff --git a/doc/repo/deployments/environment/variables.md b/doc/repo/deployments/environment/variables.md new file mode 100644 index 00000000000..d645349a204 --- /dev/null +++ b/doc/repo/deployments/environment/variables.md @@ -0,0 +1,49 @@ +## Environment / Variables API +[Back to the "Environments API"](../environments.md) | [Back to the navigation](../README.md) + +### List environment variables + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#list-environment-variables + +```php +$variables = $client->environment()->variables()->all($repoId, $envName); +``` + +### Get an environment variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#get-an-environment-variable + +```php +$variable = $client->environment()->variables()->show($repoId, $envName, $variableName); +``` + +### Create environment variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#create-an-environment-variable + +```php +$client->environment()->variables()->create($repoId, $envName, [ + 'name' => $name, + 'value' => $value +]); +``` + +### Update environment variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#update-an-environment-variable + +```php +$client->environment()->variables()->update($repoId, $envName, $variableName, [ + 'name' => $name, + 'value' => $value +]); +``` + +### Delete an environment variable + +https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#delete-an-environment-variable + +```php +$client->environment()->variables()->remove($repoId, $envName, $variableName); +``` + diff --git a/doc/repo/deployments/environments.md b/doc/repo/deployments/environments.md new file mode 100644 index 00000000000..6cb409ae3b3 --- /dev/null +++ b/doc/repo/deployments/environments.md @@ -0,0 +1,32 @@ +## Deployment / Environments API +[Back to the "Deployment API"](../deployments.md) | [Back to the navigation](../index.md) + +Provides information about environments for a repository. Wraps [GitHub Environments API](https://docs.github.com/en/rest/deployments/environments?apiVersion=2022-11-28). + +Additional APIs: +* [Secrets API](environment/secrets.md) +* [Variables API](environment/variables.md) + +#### List all environments. + +```php +$environments = $client->deployment()->environment()->all('KnpLabs', 'php-github-api'); +``` + +### Get one environment. + +```php +$environment = $client->deployment()->environment()->show('KnpLabs', 'php-github-api', $name); +``` + +#### Create or update environment. + +```php +$data = $client->deployment()->environment()->createOrUpdate('KnpLabs', 'php-github-api', $name); +``` + +#### Delete a existing environment. + +```php +$environment = $client->deployment()->environment()->remove('KnpLabs', 'php-github-api', $name); +``` diff --git a/doc/repo/deployments/policies.md b/doc/repo/deployments/policies.md new file mode 100644 index 00000000000..442fc0c4acb --- /dev/null +++ b/doc/repo/deployments/policies.md @@ -0,0 +1,38 @@ +## Deployment / Branch policies API +[Back to the "Deployment API"](../deployments.md) | [Back to the navigation](../index.md) + +Provides information about deployment branch policies. Wraps [GitHub Deployment branch policies API](https://docs.github.com/en/rest/deployments/branch-policies?apiVersion=2022-11-28#about-deployment-branch-policies). + +#### List deployment branch policies. + +```php +$policies = $client->deployment()->policies()->all('KnpLabs', 'php-github-api', 'production'); +``` + +### Get one environment. + +```php +$policy = $client->deployment()->policies()->show('KnpLabs', 'php-github-api', 'production', $branchPolicyId); +``` + +#### Create policy. + +```php +$data = $client->deployment()->policies()->create('KnpLabs', 'php-github-api', 'production', [ + 'name' => 'name' +]); +``` + +#### Update policy. + +```php +$data = $client->deployment()->policies()->update('KnpLabs', 'php-github-api', 'production', $branchPolicyId, [ + 'name' => 'name' +]); +``` + +#### Delete a existing policy. + +```php +$policy = $client->deployment()->policies()->remove('KnpLabs', 'php-github-api', 'production', $branchPolicyId); +``` diff --git a/doc/repo/hooks.md b/doc/repo/hooks.md new file mode 100644 index 00000000000..a4f9d9af655 --- /dev/null +++ b/doc/repo/hooks.md @@ -0,0 +1,46 @@ +## Repo / Hooks API +[Back to the "Repos API"](../repos.md) | [Back to the navigation](../README.md) + +For extended info see the [GitHub documentation](https://docs.github.com/en/rest/reference/repos#webhooks) + +### List repository webhooks + +```php +$hooks = $client->api('repo')->hooks()->all('twbs', 'bootstrap'); +``` + +### Get a repository webhook + +```php +$hook = $client->api('repo')->hooks()->show('twbs', 'bootstrap', $hookId); +``` + +### Create a repository webhook + +```php +$client->api('repo')->hooks()->create('twbs', 'bootstrap', $parameters); +``` + +### Update a repository webhook + +```php +$client->api('repo')->hooks()->update('twbs', 'bootstrap', $hookId, $parameters); +``` + +### Delete a repository webhook + +```php +$client->api('repo')->hooks()->remove('twbs', 'bootstrap', $hookId); +``` + +### Ping a repository webhook + +```php +$client->api('repo')->hooks()->ping('twbs', 'bootstrap', $hookId); +``` + +### Test the push repository webhook + +```php +$client->api('repo')->hooks()->test('twbs', 'bootstrap', $hookId); +``` diff --git a/doc/repo/secret-scanning.md b/doc/repo/secret-scanning.md new file mode 100644 index 00000000000..18f3ef20b28 --- /dev/null +++ b/doc/repo/secret-scanning.md @@ -0,0 +1,37 @@ +## Repository / Secret Scanning API +[Back to the "Repos API"](../../repos.md) | [Back to the navigation](../../README.md) + +# List secret-scanning alerts for a repository + +https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#list-secret-scanning-alerts-for-a-repository + +```php +$alerts = $client->api('repos')->secretScanning()->alerts('KnpLabs', 'php-github-api'); +``` + +# Get a secret-scanning alert + +https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#get-a-secret-scanning-alert + +```php +$alert = $client->api('repos')->secretScanning()->getAlert('KnpLabs', 'php-github-api', $alertNumber); +``` + +# Update a secret-scanning alert + +https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#update-a-secret-scanning-alert + +```php +$client->api('repos')->secretScanning()->updateAlert('KnpLabs', 'php-github-api', $alertNumber, [ + 'state' => 'resolved', + 'resolution' => 'wont-fix' +]); +``` + +# List Locations for a secret-scanning alert + +https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#list-locations-for-a-secret-scanning-alert + +```php +$locations = $client->api('repos')->secretScanning()->locations('KnpLabs', 'php-github-api', $alertNumber); +``` diff --git a/doc/repos.md b/doc/repos.md index 7b361aba9b2..d7c30d490f4 100644 --- a/doc/repos.md +++ b/doc/repos.md @@ -223,6 +223,15 @@ $repository = $client->api('repo')->forks()->create('ornicar', 'php-github-api') Creates a fork of the 'php-github-api' owned by 'ornicar' and returns the newly created repository. +### Merge upstream repository + +> Requires [authentication](security.md). + +```php +$repository = $client->api('repo')->mergeUpstream('ornicar', 'php-github-api', 'branchName'); +``` +Merge upstream a branch of a forked repository to keep it up-to-date with the upstream repository. + ### Get the tags of a repository ```php @@ -273,7 +282,7 @@ Returns a list of languages. ### Enable automated security fixes -https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#enable-automated-security-fixes +https://docs.github.com/en/rest/reference/repos#enable-automated-security-fixes ```php $client->api('repo')->enableAutomatedSecurityFixes('KnpLabs', 'php-github-api'); @@ -281,7 +290,7 @@ $client->api('repo')->enableAutomatedSecurityFixes('KnpLabs', 'php-github-api'); ### Disable automated security fixes -https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#disable-automated-security-fixes +https://docs.github.com/en/rest/reference/repos#disable-automated-security-fixes ```php $client->api('repo')->disableAutomatedSecurityFixes('KnpLabs', 'php-github-api'); @@ -310,8 +319,8 @@ $activity = $client->api('repo')->activity('ornicar', 'php-github-api'); Returns an array of commit activity group by week. ### `Moved` repositories -Github repositories can be moved to another org/user, but it remains the `id`. -In case if you can't no more find repo, you can retrieve it by `id`: +GitHub repositories can be moved to another org/user, but it remains the `id`. +In case you can't find the repo anymore, you can retrieve it by `id`: ```php use Github\HttpClient\Message\ResponseMediator; @@ -365,8 +374,43 @@ $repo = $client->api('repo')->transfer('KnpLabs', 'php-github-api', 'github', [1 ### Create a repository dispatch event -Example when you want to configure custom github action workflows. +Example when you want to configure custom GitHub action workflows. ```php $client->api('repo')->dispatch('KnpLabs', 'php-github-api', 'acme-event', ['foo'=>'bar']); ``` + +### Create a repository using a template + +Create a new repository using a repository template. + +```php +$client->api('repo')->createFromTemplate('template-owner', 'template-repo', [ + 'name' => 'name-of-new-repo', + 'owner' => 'name-of-new-repo-owner', // can be user or org +]); +``` + +### Check if vulnerability alerts (dependabot alerts) are enabled for a repository + +https://developer.github.com/v3/repos/#check-if-vulnerability-alerts-are-enabled-for-a-repository + +```php +$client->api('repo')->isVulnerabilityAlertsEnabled('KnpLabs', 'php-github-api'); +``` + +### Enable vulnerability alerts (dependabot alerts) + +https://developer.github.com/v3/repos/#enable-vulnerability-alerts + +```php +$client->api('repo')->enableVulnerabilityAlerts('KnpLabs', 'php-github-api'); +``` + +### Disable vulnerability alerts (dependabot alerts) + +https://developer.github.com/v3/repos/#disable-vulnerability-alerts + +```php +$client->api('repo')->disableVulnerabilityAlerts('KnpLabs', 'php-github-api'); +``` diff --git a/doc/request_response_info.md b/doc/request_response_info.md index 880e7f85a22..32e30981ea4 100644 --- a/doc/request_response_info.md +++ b/doc/request_response_info.md @@ -3,7 +3,7 @@ ### Get response headers -Get the repsonse header for the latest request +Get the response header for the latest request ``` $headers = $githubClient->getLastResponse()->getHeaders(); diff --git a/doc/result_pager.md b/doc/result_pager.md index 3eb0a115f5f..f074f1cc4a1 100644 --- a/doc/result_pager.md +++ b/doc/result_pager.md @@ -3,7 +3,7 @@ ### Usage examples -#### Get all repositories of a organization +#### Get all repositories of an organization ```php $client = new Github\Client(); @@ -21,7 +21,7 @@ Parameters of the `fetchAll` method: * The method of the API object you're using * The parameters of the method -Parameters are passed to the API method via [call_user_func_array](https://www.php.net/manual/en/function.call-user-func-array.php). +Parameters are passed to the API method via [call_user_func_array](https://www.php.net/manual/en/function.call-user-func-array.php). ```php $parameters = array('github', 'all', 1); // $organization, $type, $page @@ -63,7 +63,3 @@ $paginator->hasPrevious(); $paginator->fetchPrevious(); ``` -If you want to retrieve the pagination links (available after the call to fetch): -```php -$paginator->getPagination(); -``` diff --git a/doc/search.md b/doc/search.md index 0a674808001..24dbbef2302 100644 --- a/doc/search.md +++ b/doc/search.md @@ -13,13 +13,19 @@ $repos = $client->api('search')->repositories('github language:php'); Returns a list of repositories found by such criteria. ### Search code - + ```php $files = $client->api('search')->code('@todo language:php'); ``` Returns a list of files found by such criteria (containing "@todo" and language==php). +```php +$files = $client->api('search')->codeWithMatch('@todo language:php'); +``` + +Same as code, with additional data to highlight the matching fragments (see [Text match metadata](https://docs.github.com/en/rest/reference/search#text-match-metadata)). + ### Search issues ```php diff --git a/doc/security.md b/doc/security.md index 4ae62985d3f..a8596de20b1 100644 --- a/doc/security.md +++ b/doc/security.md @@ -17,51 +17,55 @@ $client->authenticate($usernameOrToken, $password, $method); and guess what should contain `$password`. The `$method` can contain one of the three allowed values: #### Supported methods -* `Github\Client::AUTH_CLIENT_ID` - https://developer.github.com/v3/#oauth2-keysecret -* `Github\Client::AUTH_ACCESS_TOKEN` - https://developer.github.com/v3/#oauth2-token-sent-in-a-header -* `Github\Client::AUTH_JWT` - https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-a-github-app +* `Github\AuthMethod::CLIENT_ID` - https://developer.github.com/v3/#oauth2-keysecret +* `Github\AuthMethod::ACCESS_TOKEN` - https://developer.github.com/v3/#oauth2-token-sent-in-a-header +* `Github\AuthMethod::JWT` - https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-a-github-app -The required value of `$password` depends on the chosen `$method`. For `Github\Client::AUTH_ACCESS_TOKEN`, `Github\Client::AUTH_ACCESS_TOKEN` and -`Github\Client::JWT` methods you should provide the API token in `$usernameOrToken` variable (`$password` is omitted in +The required value of `$password` depends on the chosen `$method`. For `Github\AuthMethod::CLIENT_ID`, `Github\AuthMethod::ACCESS_TOKEN` and +`Github\AuthMethod::JWT` methods you should provide the API token in `$usernameOrToken` variable (`$password` is omitted in this particular case). -The `Github\Client::AUTH_JWT` authentication method sends the specified JSON Web Token in an Authorization header. +The `Github\AuthMethod::JWT` authentication method sends the specified JSON Web Token in an Authorization header. After executing the `$client->authenticate($usernameOrToken, $secret, $method);` method using correct credentials, all further requests are done as the given user. ### Authenticating as an Integration -To authenticate as an integration you need to supply a JSON Web Token with `Github\Client::AUTH_JWT` to request -and installation access token which is then usable with `Github\Client::AUTH_ACCESS_TOKEN`. [Github´s integration +To authenticate as an integration you need to supply a JSON Web Token with `Github\AuthMethod::JWT` to request +and installation access token which is then usable with `Github\AuthMethod::ACCESS_TOKEN`. [GitHub´s integration authentication docs](https://developer.github.com/apps/building-github-apps/authentication-options-for-github-apps/#authenticating-as-a-github-app) describe the flow in detail. It´s important for integration requests to use the custom Accept header `application/vnd.github.machine-man-preview`. -The following sample code authenticates as an installation using [lcobucci/jwt](https://github.com/lcobucci/jwt/tree/3.3.2) +The following sample code authenticates as an installation using [lcobucci/jwt 4.1](https://github.com/lcobucci/jwt/tree/4.1.x) to generate a JSON Web Token (JWT). ```php -use Http\Adapter\Guzzle6\Client as GuzzleClient; -use Lcobucci\JWT\Builder; -use Lcobucci\JWT\Signer\Key; +use Github\HttpClient\Builder; +use Lcobucci\JWT\Configuration; +use Lcobucci\JWT\Encoding\ChainedFormatter; +use Lcobucci\JWT\Signer\Key\LocalFileReference; use Lcobucci\JWT\Signer\Rsa\Sha256; -$builder = new Github\HttpClient\Builder(new GuzzleClient()); +$builder = new Builder(); + $github = new Github\Client($builder, 'machine-man-preview'); -$jwt = (new Builder) - ->setIssuer($integrationId) - ->setIssuedAt(time()) - ->setExpiration(time() + 60) - // `file://` prefix for file path or file contents itself - ->sign(new Sha256(), new Key('file:///path/to/integration.private-key.pem')) - ->getToken(); +$config = Configuration::forSymmetricSigner( + new Sha256(), + LocalFileReference::file('path/to/integration.private-key.pem') +); -$github->authenticate($jwt, null, Github\Client::AUTH_JWT); +$now = new \DateTimeImmutable(); +$jwt = $config->builder(ChainedFormatter::withUnixTimestampDates()) + ->issuedBy($integrationId) + ->issuedAt($now) + ->expiresAt($now->modify('+1 minute')) + ->getToken($config->signer(), $config->signingKey()) +; -$token = $github->api('apps')->createInstallationToken($installationId); -$github->authenticate($token['token'], null, Github\Client::AUTH_ACCESS_TOKEN); +$github->authenticate($jwt->toString(), null, Github\AuthMethod::JWT); ``` -The `$integrationId` you can find in the about section of your github app. +The `$integrationId` you can find in the about section of your GitHub app. The `$installationId` you can find by installing the app and using the id in the url. diff --git a/doc/testing.md b/doc/testing.md index ec2effb3b5c..36df32097eb 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -4,7 +4,7 @@ ### Run Test Suite -The code is unit tested, there are also some functional tests. To run tests on +The code is unit tested, there are also some functional tests. To run tests on your machine, from a CLI, run ```bash @@ -14,12 +14,12 @@ $ phpunit ### Write tests -It is always great if someone wants to contribute and extend the functionality of -the API client. But all new features must be properly tested. To test a new API -function, one should test its communication with the HTTP client. The code should -never make an actual call to Github. Testing could easily be done with mocking. +It is always great if someone wants to contribute and extend the functionality of +the API client. But all new features must be properly tested. To test a new API +function, one should test its communication with the HTTP client. The code should +never make an actual call to GitHub. Testing could easily be done with mocking. -If you want to write test for the function that shows you comments to a gist. +If you want to write test for the function that shows you comments to a gist. ```php class Comments extends AbstractApi @@ -32,7 +32,7 @@ class Comments extends AbstractApi } ``` -The test will look like this: +The test will look like this: ```php use Github\Tests\Api\TestCase; @@ -51,7 +51,7 @@ class CommentsTest extends TestCase // Get the API mock (see "getApiClass" below). $api = $this->getApiMock(); - + $api->expects($this->once()) // Expect one call ->method('get') // A GET request ->with('/gists/123/comments/456') // URI should be "/gists/123/comments/456" @@ -59,14 +59,14 @@ class CommentsTest extends TestCase // Call Comments::show $result = $api->show(123, 456); - - // Verify that the result is the "Server response" as we expect. + + // Verify that the result is the "Server response" as we expect. $this->assertEquals($expectedValue, $result); } - + protected function getApiClass() { - // Tell the "getAPIMock" what class to mock. + // Tell the "getAPIMock" what class to mock. return \Github\Api\Gist\Comments::class; } } diff --git a/doc/two_factor_authentication.md b/doc/two_factor_authentication.md deleted file mode 100644 index 46e84e0daa5..00000000000 --- a/doc/two_factor_authentication.md +++ /dev/null @@ -1,19 +0,0 @@ -## Two factor authentication -[Back to the navigation](README.md) - - -### Raising the exception - -```php -try { - $authorization = $github->api('authorizations')->create(); -} catch (Github\Exception\TwoFactorAuthenticationRequiredException $e) { - echo sprintf("Two factor authentication of type %s is required.", $e->getType()); -} -``` - -Once the code has been retrieved (by sms for example), you can create an authorization: - -``` -$authorization = $github->api('authorizations')->create(array('note' => 'Optional'), $code); -``` diff --git a/doc/user/migration.md b/doc/user/migration.md new file mode 100644 index 00000000000..a2c3eb14c5e --- /dev/null +++ b/doc/user/migration.md @@ -0,0 +1,79 @@ +## User / Migrations API +[Back to the "Users API"](../../users.md) | [Back to the navigation](../../README.md) + +# List user migrations + +https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#list-user-migrations + +```php +$api = $github->api('user')->migration(); +$paginator = new Github\ResultPager($github); +$parameters = []; +$migrations = $paginator->fetchAll($api, 'list', $parameters); + +do { + foreach ($migrations as $migration) { + // do something + } + $migrations = $paginator->fetchNext(); +} +while($paginator->hasNext()); +``` + +# Start a User Migration + +https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#start-a-user-migration + +```php +$client->users()->migration()->start([ + 'repositories' => [ + 'KnpLabs/php-github-api' + ], + 'lock_repositories' => true, + 'exclude_metadata' => false, + 'exclude_git_data' => false, + 'exclude_attachments' => true, + 'exclude_releases' => false, + 'exclude_owner_projects' => true, + 'org_metadata_only' => false, + 'exclude' => [ + 'Exclude attributes from the API response to improve performance' + ] +]); +``` + +# Get a User Migration Status + +https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#get-a-user-migration-status + +```php +$status = $client->user()->migration()->status(12, [ + 'exclude' => [ + 'exclude attributes' + ] +]); +``` + +# Delete a User Migration Archive + +https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#delete-a-user-migration-archive + +```php +$client->user()->migration()->deleteArchive(12); +``` + +# Unlock a User Repository + +https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#unlock-a-user-repository + +```php +$client->user()->migration()->unlockRepo(12, 'php-github-api'); +``` + +# List repositories for a User Migration + +https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#list-repositories-for-a-user-migration + +```php +$repos = $client->user()->migration()->repos(2); +``` diff --git a/doc/users.md b/doc/users.md index 3bc20c39bc3..48bb0d7dc15 100644 --- a/doc/users.md +++ b/doc/users.md @@ -6,11 +6,7 @@ Wrap [GitHub User API](http://developer.github.com/v3/users/). ### Search for users by keyword -```php -$users = $client->api('user')->find('KnpLabs'); -``` - -Returns an array of found users. +Use the [Search API](https://github.com/KnpLabs/php-github-api/blob/master/doc/search.md#search-users) to find users by keyword. ### Lists all users, in the order they signed up, since the last user you've seen @@ -37,7 +33,7 @@ $user = $client->api('user')->show('KnpLabs'); Returns an array of information about the user. -You can also use the User ID, but it will use an undocumented Github API +You can also use the User ID, but it will use an undocumented GitHub API ```php $user = $client->api('user')->showById(202732); @@ -148,6 +144,17 @@ $users = $client->api('current_user')->starring()->all(); Returns an array of starred repos. +### Get the authenticated user activity + +> Requires [authentication](security.md). + +```php +$activity = $client->api('user')->events('ornicar'); +``` + +Returns an array of private and public events created for all repos related to the user. +> See [more](activity.md). + ### Get the authenticated user emails > Requires [authentication](security.md). diff --git a/lib/Github/Api/AbstractApi.php b/lib/Github/Api/AbstractApi.php index ce70bbe22ce..71f71cce5d6 100644 --- a/lib/Github/Api/AbstractApi.php +++ b/lib/Github/Api/AbstractApi.php @@ -20,7 +20,7 @@ abstract class AbstractApi private $client; /** - * The per page parameter. + * The per page parameter. It is used by the ResultPager. * * @var int|null */ diff --git a/lib/Github/Api/App/Hook.php b/lib/Github/Api/App/Hook.php new file mode 100644 index 00000000000..e7475dce740 --- /dev/null +++ b/lib/Github/Api/App/Hook.php @@ -0,0 +1,76 @@ +get('/app/hook/config'); + } + + /** + * Update the hook configuration of an app. + * + * @link https://docs.github.com/en/rest/apps/webhooks#update-a-webhook-configuration-for-an-app + * + * @param array $params + * + * @return array + */ + public function updateConfig(array $params) + { + return $this->patch('/app/hook/config', $params); + } + + /** + * List deliveries for an app webhook. + * + * @link https://docs.github.com/en/rest/apps/webhooks#list-deliveries-for-an-app-webhook + * + * @return array + */ + public function deliveries() + { + return $this->get('/app/hook/deliveries'); + } + + /** + * Get a delivery for an app webhook. + * + * @link https://docs.github.com/en/rest/apps/webhooks#get-a-delivery-for-an-app-webhook + * + * @param int $delivery + * + * @return array + */ + public function delivery($delivery) + { + return $this->get('/app/hook/deliveries/'.$delivery); + } + + /** + * Redeliver a delivery for an app webhook. + * + * @link https://docs.github.com/en/rest/apps/webhooks#redeliver-a-delivery-for-an-app-webhook + * + * @param int $delivery + * + * @return array + */ + public function redeliver($delivery) + { + return $this->post('/app/hook/deliveries/'.$delivery.'/attempts'); + } +} diff --git a/lib/Github/Api/Apps.php b/lib/Github/Api/Apps.php index bb2a2c463f9..15e1dfdcd4a 100644 --- a/lib/Github/Api/Apps.php +++ b/lib/Github/Api/Apps.php @@ -2,6 +2,8 @@ namespace Github\Api; +use Github\Api\App\Hook; + /** * @link https://developer.github.com/v3/apps/ * @@ -82,7 +84,7 @@ public function getInstallationForOrganization($org) { $this->configurePreviewHeader(); - return $this->get('/org/'.rawurldecode($org).'/installation'); + return $this->get('/orgs/'.rawurldecode($org).'/installation'); } /** @@ -186,4 +188,28 @@ public function removeRepository($installationId, $repositoryId) return $this->delete('/installations/'.$installationId.'/repositories/'.$repositoryId); } + + /** + * Get the currently authenticated app. + * + * @link https://docs.github.com/en/rest/reference/apps#get-the-authenticated-app + * + * @return array + */ + public function getAuthenticatedApp() + { + return $this->get('/app'); + } + + /** + * Manage the hook of an app. + * + * @link https://docs.github.com/en/rest/apps/webhooks + * + * @return Hook + */ + public function hook() + { + return new Hook($this->getClient()); + } } diff --git a/lib/Github/Api/Copilot/Usage.php b/lib/Github/Api/Copilot/Usage.php new file mode 100644 index 00000000000..0110a58bb40 --- /dev/null +++ b/lib/Github/Api/Copilot/Usage.php @@ -0,0 +1,34 @@ +get('/orgs/'.rawurlencode($organization).'/copilot/usage', $params); + } + + public function orgTeamUsageSummary(string $organization, string $teamSlug, array $params = []): array + { + return $this->get( + '/orgs/'.rawurlencode($organization).'/team/'.rawurlencode($teamSlug).'/copilot/usage', + $params + ); + } + + public function enterpriseUsageSummary(string $enterprise, array $params = []): array + { + return $this->get('/enterprises/'.rawurlencode($enterprise).'/copilot/usage', $params); + } + + public function enterpriseTeamUsageSummary(string $enterprise, string $teamSlug, array $params = []): array + { + return $this->get( + '/enterprises/'.rawurlencode($enterprise).'/team/'.rawurlencode($teamSlug).'/copilot/usage', + $params + ); + } +} diff --git a/lib/Github/Api/CurrentUser.php b/lib/Github/Api/CurrentUser.php index 70600a855a8..b5cbc89a376 100644 --- a/lib/Github/Api/CurrentUser.php +++ b/lib/Github/Api/CurrentUser.php @@ -54,7 +54,7 @@ public function followers($page = 1) } /** - * @link http://developer.github.com/v3/issues/#list-issues + * @link https://docs.github.com/en/rest/reference/issues#list-user-account-issues-assigned-to-the-authenticated-user * * @param array $params * @param bool $includeOrgIssues @@ -91,7 +91,7 @@ public function memberships() } /** - * @link http://developer.github.com/v3/orgs/#list-user-organizations + * @link https://docs.github.com/en/rest/reference/orgs#list-organizations-for-the-authenticated-user * * @return array */ @@ -111,7 +111,7 @@ public function teams() } /** - * @link http://developer.github.com/v3/repos/#list-your-repositories + * @link https://docs.github.com/en/rest/reference/repos#list-repositories-for-the-authenticated-user * * @param string $type role in the repository * @param string $sort sort by @@ -159,7 +159,7 @@ public function starring() } /** - * @link https://developer.github.com/v3/activity/watching/#list-repositories-being-watched + * @link https://docs.github.com/en/rest/reference/activity#list-repositories-watched-by-the-authenticated-user */ public function subscriptions() { @@ -167,7 +167,7 @@ public function subscriptions() } /** - * @link https://developer.github.com/v3/apps/installations/#list-app-installations-accessible-to-the-user-access-token + * @link https://docs.github.com/en/rest/reference/apps#list-app-installations-accessible-to-the-user-access-token * * @param array $params */ diff --git a/lib/Github/Api/CurrentUser/Watchers.php b/lib/Github/Api/CurrentUser/Watchers.php index 1ef35972c3f..79c04b5df36 100644 --- a/lib/Github/Api/CurrentUser/Watchers.php +++ b/lib/Github/Api/CurrentUser/Watchers.php @@ -8,6 +8,7 @@ * @link https://developer.github.com/v3/activity/watching/ * * @author Joseph Bielawski + * * @revised Felipe Valtl de Mello */ class Watchers extends AbstractApi diff --git a/lib/Github/Api/Deployment.php b/lib/Github/Api/Deployment.php index 6fa8700a6da..de5b0cb0eb9 100644 --- a/lib/Github/Api/Deployment.php +++ b/lib/Github/Api/Deployment.php @@ -2,6 +2,8 @@ namespace Github\Api; +use Github\Api\Deployment\Environments; +use Github\Api\Deployment\Policies; use Github\Exception\MissingArgumentException; /** @@ -11,6 +13,8 @@ */ class Deployment extends AbstractApi { + use AcceptHeaderTrait; + /** * List deployments for a particular repository. * @@ -66,6 +70,21 @@ public function create($username, $repository, array $params) return $this->post('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/deployments', $params); } + /** + * Delete a deployment for the given username and repo. + * + * @link https://docs.github.com/en/rest/reference/repos#delete-a-deployment + * + * Important: Deployments can only be deleted when in inactive state + * @see updateStatus + * + * @return mixed null on success, array on error with 'message' + */ + public function remove(string $username, string $repository, int $id) + { + return $this->delete('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/deployments/'.$id); + } + /** * Updates a deployment by creating a new status update. * @@ -76,7 +95,7 @@ public function create($username, $repository, array $params) * @param int $id the deployment number * @param array $params The information about the deployment update. * Must include a "state" field of pending, success, error, or failure. - * May also be given a target_url and description, ßee link for more details. + * May also be given a target_url and description, see link for more details. * * @throws MissingArgumentException * @@ -88,6 +107,15 @@ public function updateStatus($username, $repository, $id, array $params) throw new MissingArgumentException(['state']); } + // adjust media-type per github docs + // https://docs.github.com/en/rest/reference/repos#create-a-deployment-status + if ($params['state'] === 'inactive') { + $this->acceptHeaderValue = 'application/vnd.github.ant-man-preview+json'; + } + if ($params['state'] === 'in_progress' || $params['state'] === 'queued') { + $this->acceptHeaderValue = 'application/vnd.github.flash-preview+json'; + } + return $this->post('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/deployments/'.$id.'/statuses', $params); } @@ -104,4 +132,20 @@ public function getStatuses($username, $repository, $id) { return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/deployments/'.$id.'/statuses'); } + + /** + * @return Environments + */ + public function environments() + { + return new Environments($this->getClient()); + } + + /** + * @return Policies + */ + public function policies() + { + return new Policies($this->getClient()); + } } diff --git a/lib/Github/Api/Deployment/Environments.php b/lib/Github/Api/Deployment/Environments.php new file mode 100644 index 00000000000..191ec498eab --- /dev/null +++ b/lib/Github/Api/Deployment/Environments.php @@ -0,0 +1,90 @@ +get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/environments', $params); + } + + /** + * Get a environment in selected repository. + * + * @param string $username the user who owns the repo + * @param string $repository the name of the repo + * @param string $name the name of the environment + * + * @return array + */ + public function show($username, $repository, $name) + { + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/environments/'.rawurlencode($name)); + } + + /** + * Create or update a environment for the given username and repo. + * + * @link https://docs.github.com/en/rest/deployments/environments?apiVersion=2022-11-28#create-or-update-an-environment + * + * @param string $username the username + * @param string $repository the repository + * @param string $name the name of the environment + * @param array $params the new environment data + * + * @return array information about the environment + */ + public function createOrUpdate($username, $repository, $name, array $params = []) + { + return $this->put('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/environments/'.rawurlencode($name), $params); + } + + /** + * Delete a environment for the given username and repo. + * + * @link https://docs.github.com/en/rest/deployments/environments?apiVersion=2022-11-28#delete-an-environment + * + * @return mixed null on success, array on error with 'message' + */ + public function remove(string $username, string $repository, string $name) + { + return $this->delete('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/environments/'.rawurlencode($name)); + } + + /** + * @link https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#about-secrets-in-github-actions + */ + public function secrets(): Secrets + { + return new Secrets($this->getClient()); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#about-variables-in-github-actions + */ + public function variables(): Variables + { + return new Variables($this->getClient()); + } +} diff --git a/lib/Github/Api/Deployment/Policies.php b/lib/Github/Api/Deployment/Policies.php new file mode 100644 index 00000000000..e2d8fb59680 --- /dev/null +++ b/lib/Github/Api/Deployment/Policies.php @@ -0,0 +1,97 @@ +get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/environments/'.rawurlencode($environment).'/deployment-branch-policies', $params); + } + + /** + * Get a deployment branch policy. + * + * @link https://docs.github.com/en/rest/deployments/branch-policies?apiVersion=2022-11-28#get-a-deployment-branch-policy + * + * @param string $username the username of the user who owns the repository + * @param string $repository the name of the repository + * @param string $environment the name of the environment. + * @param int $id the unique identifier of the branch policy. + * + * @return array + */ + public function show(string $username, string $repository, string $environment, int $id) + { + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/environments/'.rawurlencode($environment).'/deployment-branch-policies/'.$id); + } + + /** + * Creates a deployment branch policy for an environment. + * + * @link https://docs.github.com/en/rest/deployments/branch-policies?apiVersion=2022-11-28#create-a-deployment-branch-policy + * + * @param string $username the username of the user who owns the repository + * @param string $repository the name of the repository + * @param string $environment the name of the environment. + * + * @return array information about the deployment branch policy + */ + public function create(string $username, string $repository, string $environment, array $params) + { + return $this->post('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/environments/'.rawurlencode($environment).'/deployment-branch-policies', $params); + } + + /** + * Updates a deployment branch policy for an environment. + * + * @link https://docs.github.com/en/rest/deployments/branch-policies?apiVersion=2022-11-28#update-a-deployment-branch-policy + * + * @param string $username the username of the user who owns the repository + * @param string $repository the name of the repository + * @param string $environment the name of the environment. + * @param int $id the unique identifier of the branch policy. + * + * @return array information about the deployment branch policy + */ + public function update(string $username, string $repository, string $environment, int $id, array $params) + { + return $this->put('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/environments/'.rawurlencode($environment).'/deployment-branch-policies/'.$id, $params); + } + + /** + * Delete a deployment branch policy. + * + * @link https://docs.github.com/en/rest/deployments/branch-policies?apiVersion=2022-11-28#delete-a-deployment-branch-policy + * + * @param string $username the username of the user who owns the repository + * @param string $repository the name of the repository + * @param string $environment the name of the environment. + * @param int $id the unique identifier of the branch policy. + * + * @return mixed null on success, array on error with 'message' + */ + public function remove(string $username, string $repository, string $environment, int $id) + { + return $this->delete('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/environments/'.rawurlencode($environment).'/deployment-branch-policies/'.$id); + } +} diff --git a/lib/Github/Api/Enterprise.php b/lib/Github/Api/Enterprise.php index b3daf95a177..62abaff577e 100644 --- a/lib/Github/Api/Enterprise.php +++ b/lib/Github/Api/Enterprise.php @@ -4,6 +4,7 @@ use Github\Api\Enterprise\License; use Github\Api\Enterprise\ManagementConsole; +use Github\Api\Enterprise\SecretScanning; use Github\Api\Enterprise\Stats; use Github\Api\Enterprise\UserAdmin; @@ -48,4 +49,12 @@ public function userAdmin() { return new UserAdmin($this->getClient()); } + + /** + * @return SecretScanning + */ + public function secretScanning(): SecretScanning + { + return new SecretScanning($this->getClient()); + } } diff --git a/lib/Github/Api/Enterprise/SecretScanning.php b/lib/Github/Api/Enterprise/SecretScanning.php new file mode 100644 index 00000000000..5d92c1d8a47 --- /dev/null +++ b/lib/Github/Api/Enterprise/SecretScanning.php @@ -0,0 +1,21 @@ +get('/enterprises/'.rawurlencode($enterprise).'/secret-scanning/alerts', $params); + } +} diff --git a/lib/Github/Api/Environment/Secrets.php b/lib/Github/Api/Environment/Secrets.php new file mode 100644 index 00000000000..cef84c34958 --- /dev/null +++ b/lib/Github/Api/Environment/Secrets.php @@ -0,0 +1,80 @@ +get('/repositories/'.$id.'/environments/'.rawurlencode($name).'/secrets'); + } + + /** + * @link https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#get-an-environment-secret + * + * @param int $id + * @param string $name + * @param string $secretName + * + * @return array|string + */ + public function show(int $id, string $name, string $secretName) + { + return $this->get('/repositories/'.$id.'/environments/'.rawurlencode($name).'/secrets/'.rawurlencode($secretName)); + } + + /** + * @link https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#create-or-update-an-environment-secret + * + * @param int $id + * @param string $name + * @param string $secretName + * @param array $parameters + * + * @return array|string + */ + public function createOrUpdate(int $id, string $name, string $secretName, array $parameters = []) + { + return $this->put('/repositories/'.$id.'/environments/'.rawurlencode($name).'/secrets/'.rawurlencode($secretName), $parameters); + } + + /** + * @link https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#delete-an-environment-secret + * + * @param int $id + * @param string $name + * @param string $secretName + * + * @return array|string + */ + public function remove(int $id, string $name, string $secretName) + { + return $this->delete('/repositories/'.$id.'/environments/'.rawurlencode($name).'/secrets/'.rawurlencode($secretName)); + } + + /** + * @link https://docs.github.com/en/rest/actions/secrets?apiVersion=2022-11-28#get-an-environment-public-key + * + * @param int $id + * @param string $name + * + * @return array|string + */ + public function publicKey(int $id, string $name) + { + return $this->get('/repositories/'.$id.'/environments/'.rawurlencode($name).'/secrets/public-key'); + } +} diff --git a/lib/Github/Api/Environment/Variables.php b/lib/Github/Api/Environment/Variables.php new file mode 100644 index 00000000000..035a8f605a3 --- /dev/null +++ b/lib/Github/Api/Environment/Variables.php @@ -0,0 +1,81 @@ +get('/repositories/'.$id.'/environments/'.rawurlencode($name).'/variables'); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#get-an-environment-variable + * + * @param int $id + * @param string $name + * @param string $variableName + * + * @return array|string + */ + public function show(int $id, string $name, string $variableName) + { + return $this->get('/repositories/'.$id.'/environments/'.rawurlencode($name).'/variables/'.rawurlencode($variableName)); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#create-an-environment-variable + * + * @param int $id + * @param string $name + * @param array $parameters + * + * @return array|string + */ + public function create(int $id, string $name, array $parameters) + { + return $this->post('/repositories/'.$id.'/environments/'.rawurlencode($name).'/variables', $parameters); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#update-an-environment-variable + * + * @param int $id + * @param string $name + * @param string $variableName + * @param array $parameters + * + * @return array|string + */ + public function update(int $id, string $name, string $variableName, array $parameters) + { + return $this->patch('/repositories/'.$id.'/environments/'.rawurlencode($name).'/variables/'.rawurlencode($variableName), $parameters); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#delete-an-environment-variable + * + * @param int $id + * @param string $name + * @param string $variableName + * + * @return array|string + */ + public function remove(int $id, string $name, string $variableName) + { + return $this->delete('/repositories/'.$id.'/environments/'.rawurlencode($name).'/variables/'.rawurlencode($variableName)); + } +} diff --git a/lib/Github/Api/GitData/Blobs.php b/lib/Github/Api/GitData/Blobs.php index 3b7357f3dd9..31aacda5674 100644 --- a/lib/Github/Api/GitData/Blobs.php +++ b/lib/Github/Api/GitData/Blobs.php @@ -59,8 +59,8 @@ public function show($username, $repository, $sha) */ public function create($username, $repository, array $params) { - if (!isset($params['content'], $params['encoding'])) { - throw new MissingArgumentException(['content', 'encoding']); + if (!isset($params['content'])) { + throw new MissingArgumentException('content'); } return $this->post('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/git/blobs', $params); diff --git a/lib/Github/Api/GraphQL.php b/lib/Github/Api/GraphQL.php index 9d66b5123fb..02499ad8ef7 100644 --- a/lib/Github/Api/GraphQL.php +++ b/lib/Github/Api/GraphQL.php @@ -18,12 +18,13 @@ class GraphQL extends AbstractApi /** * @param string $query * @param array $variables + * @param string $acceptHeaderValue * * @return array */ - public function execute($query, array $variables = []) + public function execute($query, array $variables = [], string $acceptHeaderValue = 'application/vnd.github.v4+json') { - $this->acceptHeaderValue = 'application/vnd.github.v4+json'; + $this->acceptHeaderValue = $acceptHeaderValue; $params = [ 'query' => $query, ]; diff --git a/lib/Github/Api/Issue/Assignees.php b/lib/Github/Api/Issue/Assignees.php index 8ae86d1cd99..46435650823 100644 --- a/lib/Github/Api/Issue/Assignees.php +++ b/lib/Github/Api/Issue/Assignees.php @@ -51,7 +51,7 @@ public function check($username, $repository, $assignee) * @throws InvalidArgumentException * @throws MissingArgumentException * - * @return string + * @return array */ public function add($username, $repository, $issue, array $parameters) { @@ -78,7 +78,7 @@ public function add($username, $repository, $issue, array $parameters) * * @throws MissingArgumentException * - * @return string + * @return array */ public function remove($username, $repository, $issue, array $parameters) { diff --git a/lib/Github/Api/Issue/Labels.php b/lib/Github/Api/Issue/Labels.php index d719578d943..3cfad23d5b0 100644 --- a/lib/Github/Api/Issue/Labels.php +++ b/lib/Github/Api/Issue/Labels.php @@ -108,7 +108,7 @@ public function deleteLabel($username, $repository, $label) public function update($username, $repository, $label, $newName, $color) { $params = [ - 'name' => $newName, + 'name' => $newName, 'color' => $color, ]; diff --git a/lib/Github/Api/Issue/Milestones.php b/lib/Github/Api/Issue/Milestones.php index 4cf2a3d5518..fe9f2296dd6 100644 --- a/lib/Github/Api/Issue/Milestones.php +++ b/lib/Github/Api/Issue/Milestones.php @@ -36,9 +36,9 @@ public function all($username, $repository, array $params = []) } return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/milestones', array_merge([ - 'page' => 1, - 'state' => 'open', - 'sort' => 'due_date', + 'page' => 1, + 'state' => 'open', + 'sort' => 'due_date', 'direction' => 'asc', ], $params)); } diff --git a/lib/Github/Api/Notification.php b/lib/Github/Api/Notification.php index e8c9b246a11..f720ad0c88c 100644 --- a/lib/Github/Api/Notification.php +++ b/lib/Github/Api/Notification.php @@ -27,7 +27,7 @@ class Notification extends AbstractApi * * @return array array of notifications */ - public function all($includingRead = false, $participating = false, DateTime $since = null, DateTime $before = null) + public function all($includingRead = false, $participating = false, ?DateTime $since = null, ?DateTime $before = null) { $parameters = [ 'all' => $includingRead, @@ -54,7 +54,7 @@ public function all($includingRead = false, $participating = false, DateTime $si * * @param DateTime|null $since */ - public function markRead(DateTime $since = null) + public function markRead(?DateTime $since = null) { $parameters = []; diff --git a/lib/Github/Api/Organization.php b/lib/Github/Api/Organization.php index d3e7646651d..0e1210c95b6 100644 --- a/lib/Github/Api/Organization.php +++ b/lib/Github/Api/Organization.php @@ -3,9 +3,13 @@ namespace Github\Api; use Github\Api\Organization\Actions\Secrets; +use Github\Api\Organization\Actions\SelfHostedRunners; +use Github\Api\Organization\Actions\Variables; use Github\Api\Organization\Hooks; use Github\Api\Organization\Members; +use Github\Api\Organization\OrganizationRoles; use Github\Api\Organization\OutsideCollaborators; +use Github\Api\Organization\SecretScanning; use Github\Api\Organization\Teams; /** @@ -110,6 +114,14 @@ public function secrets(): Secrets return new Secrets($this->getClient()); } + /** + * @return Variables + */ + public function variables(): Variables + { + return new Variables($this->getClient()); + } + /** * @return OutsideCollaborators */ @@ -131,4 +143,25 @@ public function issues($organization, array $params = [], $page = 1) { return $this->get('/orgs/'.rawurlencode($organization).'/issues', array_merge(['page' => $page], $params)); } + + /** + * @return SelfHostedRunners + */ + public function runners(): SelfHostedRunners + { + return new SelfHostedRunners($this->getClient()); + } + + /** + * @return SecretScanning + */ + public function secretScanning(): SecretScanning + { + return new SecretScanning($this->getClient()); + } + + public function organizationRoles(): OrganizationRoles + { + return new OrganizationRoles($this->getClient()); + } } diff --git a/lib/Github/Api/Organization/Actions/Secrets.php b/lib/Github/Api/Organization/Actions/Secrets.php index 7a08212907f..819e2c46738 100644 --- a/lib/Github/Api/Organization/Actions/Secrets.php +++ b/lib/Github/Api/Organization/Actions/Secrets.php @@ -5,12 +5,12 @@ use Github\Api\AbstractApi; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#secrets + * @link https://docs.github.com/en/rest/reference/actions#secrets */ class Secrets extends AbstractApi { /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-organization-secrets + * @link https://docs.github.com/en/rest/reference/actions#list-organization-secrets * * @param string $organization * @@ -22,7 +22,7 @@ public function all(string $organization) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-an-organization-secret + * @link https://docs.github.com/en/rest/reference/actions#get-an-organization-secret * * @param string $organization * @param string $secretName @@ -35,7 +35,7 @@ public function show(string $organization, string $secretName) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#create-or-update-an-organization-secret + * @link https://docs.github.com/en/rest/reference/actions#create-or-update-an-organization-secret * * @param string $organization * @param string $secretName @@ -49,7 +49,7 @@ public function create(string $organization, string $secretName, array $paramete } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#create-or-update-an-organization-secret + * @link https://docs.github.com/en/rest/reference/actions#create-or-update-an-organization-secret * * @param string $organization * @param string $secretName @@ -63,7 +63,7 @@ public function update(string $organization, string $secretName, array $paramete } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-an-organization-secret + * @link https://docs.github.com/en/rest/reference/actions#delete-an-organization-secret * * @param string $organization * @param string $secretName @@ -76,7 +76,7 @@ public function remove(string $organization, string $secretName) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-selected-repositories-for-an-organization-secret + * @link https://docs.github.com/en/rest/reference/actions#list-selected-repositories-for-an-organization-secret * * @param string $organization * @param string $secretName @@ -89,7 +89,7 @@ public function selectedRepositories(string $organization, string $secretName) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#set-selected-repositories-for-an-organization-secret + * @link https://docs.github.com/en/rest/reference/actions#set-selected-repositories-for-an-organization-secret * * @param string $organization * @param string $secretName @@ -103,7 +103,7 @@ public function setSelectedRepositories(string $organization, string $secretName } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#add-selected-repository-to-an-organization-secret + * @link https://docs.github.com/en/rest/reference/actions#add-selected-repository-to-an-organization-secret * * @param string $organization * @param string $repositoryId @@ -117,7 +117,7 @@ public function addSecret(string $organization, string $repositoryId, string $se } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#remove-selected-repository-from-an-organization-secret + * @link https://docs.github.com/en/rest/reference/actions#remove-selected-repository-from-an-organization-secret * * @param string $organization * @param string $repositoryId @@ -131,7 +131,7 @@ public function removeSecret(string $organization, string $repositoryId, string } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-an-organization-public-key + * @link https://docs.github.com/en/rest/reference/actions#get-an-organization-public-key * * @param string $organization * @@ -139,6 +139,6 @@ public function removeSecret(string $organization, string $repositoryId, string */ public function publicKey(string $organization) { - return $this->get('/orgs/'.rawurlencode($organization).'/actions/secrets/secret-key'); + return $this->get('/orgs/'.rawurlencode($organization).'/actions/secrets/public-key'); } } diff --git a/lib/Github/Api/Organization/Actions/SelfHostedRunners.php b/lib/Github/Api/Organization/Actions/SelfHostedRunners.php new file mode 100644 index 00000000000..f0b989f5751 --- /dev/null +++ b/lib/Github/Api/Organization/Actions/SelfHostedRunners.php @@ -0,0 +1,59 @@ +get('/orgs/'.rawurlencode($organization).'/actions/runners', $parameters); + } + + /** + * @link https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#get-a-self-hosted-runner-for-an-organization + * + * @param string $organization + * @param int $runnerId + * + * @return array|string + */ + public function show(string $organization, int $runnerId) + { + return $this->get('/orgs/'.rawurlencode($organization).'/actions/runners/'.$runnerId); + } + + /** + * @link https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#delete-a-self-hosted-runner-from-an-organization + * + * @param string $organization + * @param int $runnerId + * + * @return array|string + */ + public function remove(string $organization, int $runnerId) + { + return $this->delete('/orgs/'.rawurlencode($organization).'/actions/runners/'.$runnerId); + } + + /** + * @link https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#list-runner-applications-for-an-organization + * + * @param string $organization + * + * @return array|string + */ + public function applications(string $organization) + { + return $this->get('/orgs/'.rawurlencode($organization).'/actions/runners/downloads'); + } +} diff --git a/lib/Github/Api/Organization/Actions/Variables.php b/lib/Github/Api/Organization/Actions/Variables.php new file mode 100644 index 00000000000..88c037238d3 --- /dev/null +++ b/lib/Github/Api/Organization/Actions/Variables.php @@ -0,0 +1,131 @@ +get('/orgs/'.rawurlencode($organization).'/actions/variables'); + } + + /** + * @link https://docs.github.com/en/rest/reference/actions#get-an-organization-secret + * + * @param string $organization + * @param string $variableName + * + * @return array|string + */ + public function show(string $organization, string $variableName) + { + return $this->get('/orgs/'.rawurlencode($organization).'/actions/variables/'.rawurlencode($variableName)); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#create-an-organization-variable + * + * @param string $organization + * @param array $parameters + * + * @return array|string + */ + public function create(string $organization, array $parameters) + { + return $this->post('/orgs/'.rawurlencode($organization).'/actions/variables', $parameters); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#update-an-organization-variable + * + * @param string $organization + * @param string $variableName + * @param array $parameters + * + * @return array|string + */ + public function update(string $organization, string $variableName, array $parameters = []) + { + return $this->patch('/orgs/'.rawurlencode($organization).'/actions/variables/'.rawurlencode($variableName), $parameters); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#delete-an-organization-variable + * + * @param string $organization + * @param string $variableName + * + * @return array|string + */ + public function remove(string $organization, string $variableName) + { + return $this->delete('/orgs/'.rawurlencode($organization).'/actions/variables/'.rawurlencode($variableName)); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#list-selected-repositories-for-an-organization-variable + * + * @param string $organization + * @param string $variableName + * + * @return array|string + */ + public function selectedRepositories(string $organization, string $variableName) + { + return $this->get('/orgs/'.rawurlencode($organization).'/actions/variables/'.rawurlencode($variableName).'/repositories'); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#set-selected-repositories-for-an-organization-variable + * + * @param string $organization + * @param string $variableName + * @param array $parameters + * + * @return array|string + */ + public function setSelectedRepositories(string $organization, string $variableName, array $parameters = []) + { + return $this->put('/orgs/'.rawurlencode($organization).'/actions/variables/'.rawurlencode($variableName).'/repositories', $parameters); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#add-selected-repository-to-an-organization-variable + * + * @param string $organization + * @param int $repositoryId + * @param string $variableName + * + * @return array|string + */ + public function addRepository(string $organization, int $repositoryId, string $variableName) + { + return $this->put('/orgs/'.rawurlencode($organization).'/actions/variables/'.rawurlencode($variableName).'/repositories/'.$repositoryId); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#remove-selected-repository-from-an-organization-variable + * + * @param string $organization + * @param int $repositoryId + * @param string $variableName + * + * @return array|string + */ + public function removeRepository(string $organization, int $repositoryId, string $variableName) + { + return $this->delete('/orgs/'.rawurlencode($organization).'/actions/variables/'.rawurlencode($variableName).'/repositories/'.$repositoryId); + } +} diff --git a/lib/Github/Api/Organization/Members.php b/lib/Github/Api/Organization/Members.php index 3639e3ba57d..023e3f8d545 100644 --- a/lib/Github/Api/Organization/Members.php +++ b/lib/Github/Api/Organization/Members.php @@ -58,9 +58,9 @@ public function conceal($organization, $username) /* * Add user to organization */ - public function add($organization, $username) + public function add($organization, $username, array $params = []) { - return $this->put('/orgs/'.rawurlencode($organization).'/memberships/'.rawurlencode($username)); + return $this->put('/orgs/'.rawurlencode($organization).'/memberships/'.rawurlencode($username), $params); } public function addMember($organization, $username) diff --git a/lib/Github/Api/Organization/OrganizationRoles.php b/lib/Github/Api/Organization/OrganizationRoles.php new file mode 100644 index 00000000000..dd44fceceaf --- /dev/null +++ b/lib/Github/Api/Organization/OrganizationRoles.php @@ -0,0 +1,61 @@ +get('/orgs/'.rawurlencode($organization).'/organization-roles'); + } + + public function show(string $organization, int $roleId) + { + return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles/'.$roleId); + } + + public function listTeamsWithRole(string $organization, int $roleId) + { + return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles/'.$roleId.'/teams'); + } + + public function assignRoleToTeam(string $organization, int $roleId, string $teamSlug): void + { + $this->put('/orgs/'.rawurlencode($organization).'/organization-roles/teams/'.rawurlencode($teamSlug).'/'.$roleId); + } + + public function removeRoleFromTeam(string $organization, int $roleId, string $teamSlug): void + { + $this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/teams/'.rawurlencode($teamSlug).'/'.$roleId); + } + + public function removeAllRolesFromTeam(string $organization, string $teamSlug): void + { + $this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/teams/'.rawurlencode($teamSlug)); + } + + public function listUsersWithRole(string $organization, int $roleId): array + { + return $this->get('/orgs/'.rawurlencode($organization).'/organization-roles/'.$roleId.'/users'); + } + + public function assignRoleToUser(string $organization, int $roleId, string $username): void + { + $this->put('/orgs/'.rawurlencode($organization).'/organization-roles/users/'.rawurlencode($username).'/'.$roleId); + } + + public function removeRoleFromUser(string $organization, int $roleId, string $username): void + { + $this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/users/'.rawurlencode($username).'/'.$roleId); + } + + public function removeAllRolesFromUser(string $organization, string $username): void + { + $this->delete('/orgs/'.rawurlencode($organization).'/organization-roles/users/'.rawurlencode($username)); + } +} diff --git a/lib/Github/Api/Organization/SecretScanning.php b/lib/Github/Api/Organization/SecretScanning.php new file mode 100644 index 00000000000..a323fd06fcc --- /dev/null +++ b/lib/Github/Api/Organization/SecretScanning.php @@ -0,0 +1,19 @@ +get('/orgs/'.rawurlencode($organization).'/secret-scanning/alerts', $params); + } +} diff --git a/lib/Github/Api/Organization/Teams.php b/lib/Github/Api/Organization/Teams.php index 00b57758b05..20bb2791a7a 100644 --- a/lib/Github/Api/Organization/Teams.php +++ b/lib/Github/Api/Organization/Teams.php @@ -95,9 +95,16 @@ public function removeMember($team, $username, $organization) return $this->delete('/orgs/'.rawurlencode($organization).'/teams/'.rawurlencode($team).'/memberships/'.rawurlencode($username)); } - public function repositories($team) + /** + * @link https://docs.github.com/en/rest/teams/teams#list-team-repositories + */ + public function repositories($team, $organization = '') { - return $this->get('/teams/'.rawurlencode($team).'/repos'); + if (empty($organization)) { + return $this->get('/teams/'.rawurlencode($team).'/repos'); + } + + return $this->get('/orgs/'.rawurlencode($organization).'/teams/'.rawurlencode($team).'/repos'); } public function repository($team, $organization, $repository) @@ -107,15 +114,15 @@ public function repository($team, $organization, $repository) public function addRepository($team, $organization, $repository, $params = []) { - if (isset($params['permission']) && !in_array($params['permission'], ['pull', 'push', 'admin'])) { + if (isset($params['permission']) && !in_array($params['permission'], ['pull', 'push', 'admin', 'maintain', 'triage'])) { $params['permission'] = 'pull'; } - return $this->put('/teams/'.rawurlencode($team).'/repos/'.rawurlencode($organization).'/'.rawurlencode($repository), $params); + return $this->put('/orgs/'.rawurlencode($organization).'/teams/'.rawurlencode($team).'/repos/'.rawurlencode($organization).'/'.rawurlencode($repository), $params); } public function removeRepository($team, $organization, $repository) { - return $this->delete('/teams/'.rawurlencode($team).'/repos/'.rawurlencode($organization).'/'.rawurlencode($repository)); + return $this->delete('/orgs/'.rawurlencode($organization).'/teams/'.rawurlencode($team).'/repos/'.rawurlencode($organization).'/'.rawurlencode($repository)); } } diff --git a/lib/Github/Api/PullRequest.php b/lib/Github/Api/PullRequest.php index ce1c2b1d901..22922c1ee92 100644 --- a/lib/Github/Api/PullRequest.php +++ b/lib/Github/Api/PullRequest.php @@ -108,16 +108,25 @@ public function status($username, $repository, $id) return $this->get($link); } + /** + * @return Comments + */ public function comments() { return new Comments($this->getClient()); } + /** + * @return Review + */ public function reviews() { return new Review($this->getClient()); } + /** + * @return ReviewRequest + */ public function reviewRequests() { return new ReviewRequest($this->getClient()); diff --git a/lib/Github/Api/PullRequest/Review.php b/lib/Github/Api/PullRequest/Review.php index 249477f0478..ed586ddf6fc 100644 --- a/lib/Github/Api/PullRequest/Review.php +++ b/lib/Github/Api/PullRequest/Review.php @@ -20,6 +20,8 @@ class Review extends AbstractApi public function configure() { + trigger_deprecation('KnpLabs/php-github-api', '3.2', 'The "%s" is deprecated and will be removed.', __METHOD__); + return $this; } @@ -37,6 +39,10 @@ public function configure() */ public function all($username, $repository, $pullRequest, array $params = []) { + if (!empty($params)) { + trigger_deprecation('KnpLabs/php-github-api', '3.2', 'The "$params" parameter is deprecated, to paginate the results use the "ResultPager" instead.'); + } + $parameters = array_merge([ 'page' => 1, 'per_page' => 30, diff --git a/lib/Github/Api/PullRequest/ReviewRequest.php b/lib/Github/Api/PullRequest/ReviewRequest.php index 540307559e2..e9b9280a119 100644 --- a/lib/Github/Api/PullRequest/ReviewRequest.php +++ b/lib/Github/Api/PullRequest/ReviewRequest.php @@ -14,6 +14,8 @@ class ReviewRequest extends AbstractApi public function configure() { + trigger_deprecation('KnpLabs/php-github-api', '3.2', 'The "%s" is deprecated and will be removed.', __METHOD__); + return $this; } @@ -29,11 +31,15 @@ public function configure() */ public function all($username, $repository, $pullRequest, array $params = []) { + if (!empty($params)) { + trigger_deprecation('KnpLabs/php-github-api', '3.2', 'The "$params" parameter is deprecated, to paginate the results use the "ResultPager" instead.'); + } + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/pulls/'.$pullRequest.'/requested_reviewers', $params); } /** - * @link https://developer.github.com/v3/pulls/review_requests/#create-a-review-request + * @link https://docs.github.com/en/rest/reference/pulls#request-reviewers-for-a-pull-request * * @param string $username * @param string $repository @@ -41,7 +47,7 @@ public function all($username, $repository, $pullRequest, array $params = []) * @param array $reviewers * @param array $teamReviewers * - * @return string + * @return array */ public function create($username, $repository, $pullRequest, array $reviewers = [], array $teamReviewers = []) { @@ -57,7 +63,7 @@ public function create($username, $repository, $pullRequest, array $reviewers = * @param array $reviewers * @param array $teamReviewers * - * @return string + * @return array */ public function remove($username, $repository, $pullRequest, array $reviewers = [], array $teamReviewers = []) { diff --git a/lib/Github/Api/Repo.php b/lib/Github/Api/Repo.php index 4698ebbc031..5653ae4c152 100644 --- a/lib/Github/Api/Repo.php +++ b/lib/Github/Api/Repo.php @@ -5,6 +5,7 @@ use Github\Api\Repository\Actions\Artifacts; use Github\Api\Repository\Actions\Secrets; use Github\Api\Repository\Actions\SelfHostedRunners; +use Github\Api\Repository\Actions\Variables; use Github\Api\Repository\Actions\WorkflowJobs; use Github\Api\Repository\Actions\WorkflowRuns; use Github\Api\Repository\Actions\Workflows; @@ -23,6 +24,7 @@ use Github\Api\Repository\Projects; use Github\Api\Repository\Protection; use Github\Api\Repository\Releases; +use Github\Api\Repository\SecretScanning; use Github\Api\Repository\Stargazers; use Github\Api\Repository\Statuses; use Github\Api\Repository\Traffic; @@ -181,6 +183,7 @@ public function showById($id) * @param int $teamId The id of the team that will be granted access to this repository. This is only valid when creating a repo in an organization. * @param bool $autoInit `true` to create an initial commit with empty README, `false` for no initial commit * @param bool $hasProjects `true` to enable projects for this repository or false to disable them. + * @param string|null $visibility * * @return array returns repository data */ @@ -195,22 +198,27 @@ public function create( $hasDownloads = false, $teamId = null, $autoInit = false, - $hasProjects = true + $hasProjects = true, + $visibility = null ) { $path = null !== $organization ? '/orgs/'.$organization.'/repos' : '/user/repos'; $parameters = [ - 'name' => $name, - 'description' => $description, - 'homepage' => $homepage, - 'private' => !$public, - 'has_issues' => $hasIssues, - 'has_wiki' => $hasWiki, + 'name' => $name, + 'description' => $description, + 'homepage' => $homepage, + 'private' => ($visibility ?? ($public ? 'public' : 'private')) === 'private', + 'has_issues' => $hasIssues, + 'has_wiki' => $hasWiki, 'has_downloads' => $hasDownloads, - 'auto_init' => $autoInit, + 'auto_init' => $autoInit, 'has_projects' => $hasProjects, ]; + if ($visibility) { + $parameters['visibility'] = $visibility; + } + if ($organization && $teamId) { $parameters['team_id'] = $teamId; } @@ -257,12 +265,20 @@ public function remove($username, $repository) * @param string $username the user who owns the repository * @param string $repository the name of the repository * @param string $format one of formats: "raw", "html", or "v3+json" + * @param string $dir The alternate path to look for a README file + * @param array $params additional query params like "ref" to fetch readme for branch/tag * * @return string|array the readme content */ - public function readme($username, $repository, $format = 'raw') + public function readme($username, $repository, $format = 'raw', $dir = null, $params = []) { - return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/readme', [], [ + $path = '/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/readme'; + + if (null !== $dir) { + $path .= '/'.rawurlencode($dir); + } + + return $this->get($path, $params, [ 'Accept' => "application/vnd.github.$format", ]); } @@ -272,14 +288,19 @@ public function readme($username, $repository, $format = 'raw') * * @link https://developer.github.com/v3/repos/#create-a-repository-dispatch-event * - * @param string $username the user who owns the repository - * @param string $repository the name of the repository - * @param string $eventType A custom webhook event name + * @param string $username the user who owns the repository + * @param string $repository the name of the repository + * @param string $eventType A custom webhook event name + * @param array|object $clientPayload The payload to pass to Github. * * @return mixed null on success, array on error with 'message' */ - public function dispatch($username, $repository, $eventType, array $clientPayload) + public function dispatch($username, $repository, $eventType, $clientPayload) { + if (is_array($clientPayload)) { + $clientPayload = (object) $clientPayload; + } + return $this->post(\sprintf('/repos/%s/%s/dispatches', rawurlencode($username), rawurlencode($repository)), [ 'event_type' => $eventType, 'client_payload' => $clientPayload, @@ -323,7 +344,7 @@ public function commits() } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#check-runs + * @link https://docs.github.com/en/rest/reference/checks#check-runs */ public function checkRuns(): CheckRuns { @@ -331,7 +352,7 @@ public function checkRuns(): CheckRuns } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#check-suites + * @link https://docs.github.com/en/rest/reference/checks#check-suites */ public function checkSuites(): CheckSuites { @@ -347,7 +368,7 @@ public function artifacts(): Artifacts } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#workflows + * @link https://docs.github.com/en/rest/reference/actions#workflows */ public function workflows(): Workflows { @@ -355,7 +376,7 @@ public function workflows(): Workflows } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#workflow-runs + * @link https://docs.github.com/en/rest/reference/actions#workflow-runs */ public function workflowRuns(): WorkflowRuns { @@ -363,7 +384,7 @@ public function workflowRuns(): WorkflowRuns } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#workflow-jobs + * @link https://docs.github.com/en/rest/reference/actions#workflow-jobs */ public function workflowJobs(): WorkflowJobs { @@ -371,7 +392,7 @@ public function workflowJobs(): WorkflowJobs } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#self-hosted-runners + * @link https://docs.github.com/en/rest/reference/actions#self-hosted-runners */ public function selfHostedRunners(): SelfHostedRunners { @@ -379,13 +400,21 @@ public function selfHostedRunners(): SelfHostedRunners } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#secrets + * @link https://docs.github.com/en/rest/reference/actions#secrets */ public function secrets(): Secrets { return new Secrets($this->getClient()); } + /** + * @link https://docs.github.com/en/rest/reference/actions#secrets + */ + public function variables(): Variables + { + return new Variables($this->getClient()); + } + /** * Manage the content of a repository. * @@ -502,17 +531,33 @@ public function statuses() * @param string $username the username * @param string $repository the name of the repository * @param string $branch the name of the branch + * @param array $parameters parameters for the query string * * @return array list of the repository branches */ - public function branches($username, $repository, $branch = null) + public function branches($username, $repository, $branch = null, array $parameters = []) { $url = '/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/branches'; if (null !== $branch) { $url .= '/'.rawurlencode($branch); } - return $this->get($url); + return $this->get($url, $parameters); + } + + /** + * Sync a fork branch with the upstream repository. + * + * @link https://docs.github.com/en/rest/branches/branches#sync-a-fork-branch-with-the-upstream-repository + * + * @return array|string + */ + public function mergeUpstream(string $username, string $repository, string $branchName) + { + return $this->post( + '/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/merge-upstream', + ['branch' => $branchName] + ); } /** @@ -617,7 +662,7 @@ public function subscribers($username, $repository, $page = 1) * @param string $head The head to merge. This can be a branch name or a commit SHA1. * @param string $message Commit message to use for the merge commit. If omitted, a default message will be used. * - * @return array|null + * @return array|string */ public function merge($username, $repository, $base, $head, $message = null) { @@ -646,7 +691,7 @@ public function milestones($username, $repository, array $parameters = []) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#enable-automated-security-fixes + * @link https://docs.github.com/en/rest/reference/repos#enable-automated-security-fixes * * @param string $username * @param string $repository @@ -661,7 +706,7 @@ public function enableAutomatedSecurityFixes(string $username, string $repositor } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#disable-automated-security-fixes + * @link https://docs.github.com/en/rest/reference/repos#disable-automated-security-fixes * * @param string $username * @param string $repository @@ -793,4 +838,72 @@ public function transfer($username, $repository, $newOwner, $teamId = []) { return $this->post('/repos/'.rawurldecode($username).'/'.rawurldecode($repository).'/transfer', ['new_owner' => $newOwner, 'team_id' => $teamId]); } + + /** + * Create a repository using a template. + * + * @link https://developer.github.com/v3/repos/#create-a-repository-using-a-template + * + * @return array + */ + public function createFromTemplate(string $templateOwner, string $templateRepo, array $parameters = []) + { + //This api is in preview mode, so set the correct accept-header + $this->acceptHeaderValue = 'application/vnd.github.baptiste-preview+json'; + + return $this->post('/repos/'.rawurldecode($templateOwner).'/'.rawurldecode($templateRepo).'/generate', $parameters); + } + + /** + * Check if vulnerability alerts are enabled for a repository. + * + * @link https://developer.github.com/v3/repos/#check-if-vulnerability-alerts-are-enabled-for-a-repository + * + * @param string $username the username + * @param string $repository the repository + * + * @return array|string + */ + public function isVulnerabilityAlertsEnabled(string $username, string $repository) + { + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/vulnerability-alerts'); + } + + /** + * Enable vulnerability alerts for a repository. + * + * @link https://developer.github.com/v3/repos/#enable-vulnerability-alerts + * + * @param string $username the username + * @param string $repository the repository + * + * @return array|string + */ + public function enableVulnerabilityAlerts(string $username, string $repository) + { + return $this->put('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/vulnerability-alerts'); + } + + /** + * Disable vulnerability alerts for a repository. + * + * @link https://developer.github.com/v3/repos/#disable-vulnerability-alerts + * + * @param string $username the username + * @param string $repository the repository + * + * @return array|string + */ + public function disableVulnerabilityAlerts(string $username, string $repository) + { + return $this->delete('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/vulnerability-alerts'); + } + + /** + * @return SecretScanning + */ + public function secretScanning(): SecretScanning + { + return new SecretScanning($this->getClient()); + } } diff --git a/lib/Github/Api/Repository/Actions/Artifacts.php b/lib/Github/Api/Repository/Actions/Artifacts.php index b81d560b00d..84f3b0604af 100644 --- a/lib/Github/Api/Repository/Actions/Artifacts.php +++ b/lib/Github/Api/Repository/Actions/Artifacts.php @@ -5,12 +5,12 @@ use Github\Api\AbstractApi; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#artifacts + * @link https://docs.github.com/en/rest/reference/actions#artifacts */ class Artifacts extends AbstractApi { /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-artifacts-for-a-repository + * @link https://docs.github.com/en/rest/reference/actions#list-artifacts-for-a-repository * * @param string $username * @param string $repository @@ -24,7 +24,7 @@ public function all(string $username, string $repository, array $parameters = [] } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-workflow-run-artifacts + * @link https://docs.github.com/en/rest/reference/actions#list-workflow-run-artifacts * * @param string $username * @param string $repository @@ -38,7 +38,7 @@ public function runArtifacts(string $username, string $repository, int $runId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-an-artifact + * @link https://docs.github.com/en/rest/reference/actions#get-an-artifact * * @param string $username * @param string $repository @@ -52,7 +52,7 @@ public function show(string $username, string $repository, int $artifactId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-an-artifact + * @link https://docs.github.com/en/rest/reference/actions#delete-an-artifact * * @param string $username * @param string $repository @@ -66,7 +66,7 @@ public function remove(string $username, string $repository, int $artifactId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#download-an-artifact + * @link https://docs.github.com/en/rest/reference/actions#download-an-artifact * * @param string $username * @param string $repository diff --git a/lib/Github/Api/Repository/Actions/Secrets.php b/lib/Github/Api/Repository/Actions/Secrets.php index 4c38de203dc..2085a133f7a 100644 --- a/lib/Github/Api/Repository/Actions/Secrets.php +++ b/lib/Github/Api/Repository/Actions/Secrets.php @@ -5,12 +5,12 @@ use Github\Api\AbstractApi; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#secrets + * @link https://docs.github.com/en/rest/reference/actions#secrets */ class Secrets extends AbstractApi { /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-repository-secrets + * @link https://docs.github.com/en/rest/reference/actions#list-repository-secrets * * @param string $username * @param string $repository @@ -23,7 +23,7 @@ public function all(string $username, string $repository) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-repository-secret + * @link https://docs.github.com/en/rest/reference/actions#get-a-repository-secret * * @param string $username * @param string $repository @@ -37,7 +37,7 @@ public function show(string $username, string $repository, string $secretName) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#create-or-update-a-repository-secret + * @link https://docs.github.com/en/rest/reference/actions#create-or-update-a-repository-secret * * @param string $username * @param string $repository @@ -52,7 +52,7 @@ public function create(string $username, string $repository, string $secretName, } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#create-or-update-a-repository-secret + * @link https://docs.github.com/en/rest/reference/actions#create-or-update-a-repository-secret * * @param string $username * @param string $repository @@ -67,7 +67,7 @@ public function update(string $username, string $repository, string $secretName, } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-a-repository-secret + * @link https://docs.github.com/en/rest/reference/actions#delete-a-repository-secret * * @param string $username * @param string $repository @@ -81,7 +81,7 @@ public function remove(string $username, string $repository, string $secretName) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-repository-public-key + * @link https://docs.github.com/en/rest/reference/actions#get-a-repository-public-key * * @param string $username * @param string $repository @@ -90,6 +90,6 @@ public function remove(string $username, string $repository, string $secretName) */ public function publicKey(string $username, string $repository) { - return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/secrets/secret-key'); + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/secrets/public-key'); } } diff --git a/lib/Github/Api/Repository/Actions/SelfHostedRunners.php b/lib/Github/Api/Repository/Actions/SelfHostedRunners.php index 4a20b1169bf..7eb1a9d4e39 100644 --- a/lib/Github/Api/Repository/Actions/SelfHostedRunners.php +++ b/lib/Github/Api/Repository/Actions/SelfHostedRunners.php @@ -5,12 +5,12 @@ use Github\Api\AbstractApi; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#self-hosted-runners + * @link https://docs.github.com/en/rest/reference/actions#self-hosted-runners */ class SelfHostedRunners extends AbstractApi { /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-self-hosted-runners-for-a-repository + * @link https://docs.github.com/en/rest/reference/actions#list-self-hosted-runners-for-a-repository * * @param string $username * @param string $repository @@ -23,7 +23,7 @@ public function all(string $username, string $repository) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-self-hosted-runner-for-a-repository + * @link https://docs.github.com/en/rest/reference/actions#get-a-self-hosted-runner-for-a-repository * * @param string $username * @param string $repository @@ -37,7 +37,7 @@ public function show(string $username, string $repository, int $runnerId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-a-self-hosted-runner-from-a-repository + * @link https://docs.github.com/en/rest/reference/actions#delete-a-self-hosted-runner-from-a-repository * * @param string $username * @param string $repository @@ -51,7 +51,7 @@ public function remove(string $username, string $repository, int $runnerId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-runner-applications-for-a-repository + * @link https://docs.github.com/en/rest/reference/actions#list-runner-applications-for-a-repository * * @param string $username * @param string $repository diff --git a/lib/Github/Api/Repository/Actions/Variables.php b/lib/Github/Api/Repository/Actions/Variables.php new file mode 100644 index 00000000000..7414e82810b --- /dev/null +++ b/lib/Github/Api/Repository/Actions/Variables.php @@ -0,0 +1,81 @@ +get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/variables'); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#get-a-repository-variable + * + * @param string $username + * @param string $repository + * @param string $variableName + * + * @return array|string + */ + public function show(string $username, string $repository, string $variableName) + { + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/variables/'.rawurlencode($variableName)); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#create-a-repository-variable + * + * @param string $username + * @param string $repository + * @param array $parameters + * + * @return array|string + */ + public function create(string $username, string $repository, array $parameters = []) + { + return $this->post('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/variables', $parameters); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#update-a-repository-variable + * + * @param string $username + * @param string $repository + * @param string $variableName + * @param array $parameters + * + * @return array|string + */ + public function update(string $username, string $repository, string $variableName, array $parameters = []) + { + return $this->patch('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/variables/'.rawurlencode($variableName), $parameters); + } + + /** + * @link https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#delete-a-repository-variable + * + * @param string $username + * @param string $repository + * @param string $variableName + * + * @return array|string + */ + public function remove(string $username, string $repository, string $variableName) + { + return $this->delete('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/variables/'.rawurlencode($variableName)); + } +} diff --git a/lib/Github/Api/Repository/Actions/WorkflowJobs.php b/lib/Github/Api/Repository/Actions/WorkflowJobs.php index edcb806ee6c..3167d3dbf81 100644 --- a/lib/Github/Api/Repository/Actions/WorkflowJobs.php +++ b/lib/Github/Api/Repository/Actions/WorkflowJobs.php @@ -5,12 +5,12 @@ use Github\Api\AbstractApi; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#workflow-jobs + * @link https://docs.github.com/en/rest/reference/actions#workflow-jobs */ class WorkflowJobs extends AbstractApi { /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-jobs-for-a-workflow-run + * @link https://docs.github.com/en/rest/reference/actions#list-jobs-for-a-workflow-run * * @param string $username * @param string $repository @@ -25,7 +25,7 @@ public function all(string $username, string $repository, int $runId, array $par } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-job-for-a-workflow-run + * @link https://docs.github.com/en/rest/reference/actions#get-a-job-for-a-workflow-run * * @param string $username * @param string $repository @@ -39,7 +39,7 @@ public function show(string $username, string $repository, int $jobId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#download-job-logs-for-a-workflow-run + * @link https://docs.github.com/en/rest/reference/actions#download-job-logs-for-a-workflow-run * * @param string $username * @param string $repository diff --git a/lib/Github/Api/Repository/Actions/WorkflowRuns.php b/lib/Github/Api/Repository/Actions/WorkflowRuns.php index 27213826207..d6f95f1ed94 100644 --- a/lib/Github/Api/Repository/Actions/WorkflowRuns.php +++ b/lib/Github/Api/Repository/Actions/WorkflowRuns.php @@ -5,12 +5,12 @@ use Github\Api\AbstractApi; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#workflow-runs + * @link https://docs.github.com/en/rest/reference/actions#workflow-runs */ class WorkflowRuns extends AbstractApi { /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-workflow-runs-for-a-repository + * @link https://docs.github.com/en/rest/reference/actions#list-workflow-runs-for-a-repository * * @param string $username * @param string $repository @@ -24,22 +24,22 @@ public function all(string $username, string $repository, array $parameters = [] } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-workflow-runs + * @link https://docs.github.com/en/rest/reference/actions#list-workflow-runs * * @param string $username * @param string $repository - * @param string $workflowId + * @param string $workflow * @param array $parameters * * @return array */ - public function listRuns(string $username, string $repository, string $workflowId, array $parameters = []) + public function listRuns(string $username, string $repository, string $workflow, array $parameters = []) { - return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/workflows/'.$workflowId.'/runs', $parameters); + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/workflows/'.rawurlencode($workflow).'/runs', $parameters); } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-workflow-run + * @link https://docs.github.com/en/rest/reference/actions#get-a-workflow-run * * @param string $username * @param string $repository @@ -54,7 +54,7 @@ public function show(string $username, string $repository, int $runId, array $pa } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-a-workflow-run + * @link https://docs.github.com/en/rest/reference/actions#delete-a-workflow-run * * @param string $username * @param string $repository @@ -68,7 +68,7 @@ public function remove(string $username, string $repository, int $runId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#re-run-a-workflow + * @link https://docs.github.com/en/rest/reference/actions#re-run-a-workflow * * @param string $username * @param string $repository @@ -82,7 +82,7 @@ public function rerun(string $username, string $repository, int $runId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#cancel-a-workflow-run + * @link https://docs.github.com/en/rest/reference/actions#cancel-a-workflow-run * * @param string $username * @param string $repository @@ -96,7 +96,7 @@ public function cancel(string $username, string $repository, int $runId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-workflow-run-usage + * @link https://docs.github.com/en/rest/reference/actions#get-workflow-run-usage * * @param string $username * @param string $repository @@ -110,7 +110,7 @@ public function usage(string $username, string $repository, int $runId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#download-workflow-run-logs + * @link https://docs.github.com/en/rest/reference/actions#download-workflow-run-logs * * @param string $username * @param string $repository @@ -124,7 +124,7 @@ public function downloadLogs(string $username, string $repository, int $runId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#delete-workflow-run-logs + * @link https://docs.github.com/en/rest/reference/actions#delete-workflow-run-logs * * @param string $username * @param string $repository @@ -136,4 +136,20 @@ public function deleteLogs(string $username, string $repository, int $runId) { return $this->delete('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/runs/'.$runId.'/logs'); } + + /** + * @link https://docs.github.com/en/rest/reference/actions#approve-a-workflow-run-for-a-fork-pull-request + * + * @param string $username + * @param string $repository + * @param int $runId + * + * @return array|string + * + * @experimental This endpoint is currently in beta. + */ + public function approve(string $username, string $repository, int $runId) + { + return $this->post('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/runs/'.$runId.'/approve'); + } } diff --git a/lib/Github/Api/Repository/Actions/Workflows.php b/lib/Github/Api/Repository/Actions/Workflows.php index 3843c59a0ba..9a1c9e31c7b 100644 --- a/lib/Github/Api/Repository/Actions/Workflows.php +++ b/lib/Github/Api/Repository/Actions/Workflows.php @@ -5,12 +5,12 @@ use Github\Api\AbstractApi; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#workflows + * @link https://docs.github.com/en/rest/reference/actions#workflows */ class Workflows extends AbstractApi { /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#list-repository-workflows + * @link https://docs.github.com/en/rest/reference/actions#list-repository-workflows * * @param string $username * @param string $repository @@ -24,30 +24,59 @@ public function all(string $username, string $repository, array $parameters = [] } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-a-workflow + * @link https://docs.github.com/en/rest/reference/actions#get-a-workflow * - * @param string $username - * @param string $repository - * @param int $workflowId + * @param string $username + * @param string $repository + * @param string|int $workflow * * @return array */ - public function show(string $username, string $repository, int $workflowId) + public function show(string $username, string $repository, $workflow) { - return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/workflows/'.$workflowId); + if (is_string($workflow)) { + $workflow = rawurlencode($workflow); + } + + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/workflows/'.$workflow); } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/actions#get-workflow-usage + * @link https://docs.github.com/en/rest/reference/actions#get-workflow-usage * - * @param string $username - * @param string $repository - * @param int $workflowId + * @param string $username + * @param string $repository + * @param string|int $workflow * * @return array|string */ - public function usage(string $username, string $repository, int $workflowId) + public function usage(string $username, string $repository, $workflow) + { + if (is_string($workflow)) { + $workflow = rawurlencode($workflow); + } + + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/workflows/'.$workflow.'/timing'); + } + + /** + * @link https://docs.github.com/en/rest/reference/actions#create-a-workflow-dispatch-event + * + * @param string $username + * @param string $repository + * @param string|int $workflow + * @param string $ref + * @param array $inputs + * + * @return array|string empty + */ + public function dispatches(string $username, string $repository, $workflow, string $ref, ?array $inputs = null) { - return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/workflows/'.$workflowId.'/timing'); + if (is_string($workflow)) { + $workflow = rawurlencode($workflow); + } + $parameters = array_filter(['ref' => $ref, 'inputs' => $inputs]); + + return $this->post('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/actions/workflows/'.$workflow.'/dispatches', $parameters); } } diff --git a/lib/Github/Api/Repository/Assets.php b/lib/Github/Api/Repository/Assets.php index 39cdc5da913..043016e7801 100644 --- a/lib/Github/Api/Repository/Assets.php +++ b/lib/Github/Api/Repository/Assets.php @@ -3,6 +3,7 @@ namespace Github\Api\Repository; use Github\Api\AbstractApi; +use Github\Api\AcceptHeaderTrait; use Github\Exception\ErrorException; use Github\Exception\MissingArgumentException; @@ -13,6 +14,8 @@ */ class Assets extends AbstractApi { + use AcceptHeaderTrait; + /** * Get all release's assets in selected repository * GET /repos/:owner/:repo/releases/:id/assets. @@ -36,10 +39,14 @@ public function all($username, $repository, $id) * @param string $repository the name of the repo * @param int $id the id of the asset * - * @return array + * @return array|string */ - public function show($username, $repository, $id) + public function show($username, $repository, $id, bool $returnBinaryContent = false) { + if ($returnBinaryContent) { + $this->acceptHeaderValue = 'application/octet-stream'; + } + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/releases/assets/'.$id); } diff --git a/lib/Github/Api/Repository/Checks/CheckRuns.php b/lib/Github/Api/Repository/Checks/CheckRuns.php index d1e456212ce..1ddee3770c8 100644 --- a/lib/Github/Api/Repository/Checks/CheckRuns.php +++ b/lib/Github/Api/Repository/Checks/CheckRuns.php @@ -6,14 +6,14 @@ use Github\Api\AcceptHeaderTrait; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks + * @link https://docs.github.com/en/rest/reference/checks */ class CheckRuns extends AbstractApi { use AcceptHeaderTrait; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#create-a-check-run + * @link https://docs.github.com/en/rest/reference/checks#create-a-check-run * * @return array */ @@ -25,7 +25,7 @@ public function create(string $username, string $repository, array $params = []) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#get-a-check-run + * @link https://docs.github.com/en/rest/reference/checks#get-a-check-run * * @return array */ @@ -37,7 +37,7 @@ public function show(string $username, string $repository, int $checkRunId) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#update-a-check-run + * @link https://docs.github.com/en/rest/reference/checks#update-a-check-run * * @return array */ @@ -49,7 +49,7 @@ public function update(string $username, string $repository, int $checkRunId, ar } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#list-check-run-annotations + * @link https://docs.github.com/en/rest/reference/checks#list-check-run-annotations * * @return array */ @@ -61,7 +61,7 @@ public function annotations(string $username, string $repository, int $checkRunI } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#list-check-runs-in-a-check-suite + * @link https://docs.github.com/en/rest/reference/checks#list-check-runs-in-a-check-suite * * @return array */ @@ -73,7 +73,7 @@ public function allForCheckSuite(string $username, string $repository, int $chec } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#list-check-runs-for-a-git-reference + * @link https://docs.github.com/en/rest/reference/checks#list-check-runs-for-a-git-reference * * @return array */ @@ -83,4 +83,14 @@ public function allForReference(string $username, string $repository, string $re return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/commits/'.rawurlencode($ref).'/check-runs', $params); } + + /** + * @link https://docs.github.com/en/rest/reference/checks#rerequest-a-check-run + * + * @return array + */ + public function rerequest(string $username, string $repository, int $checkRunId) + { + return $this->post('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/check-runs/'.$checkRunId.'/rerequest'); + } } diff --git a/lib/Github/Api/Repository/Checks/CheckSuites.php b/lib/Github/Api/Repository/Checks/CheckSuites.php index ca6b432eb83..40c83a566c1 100644 --- a/lib/Github/Api/Repository/Checks/CheckSuites.php +++ b/lib/Github/Api/Repository/Checks/CheckSuites.php @@ -6,14 +6,14 @@ use Github\Api\AcceptHeaderTrait; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks + * @link https://docs.github.com/en/rest/reference/checks */ class CheckSuites extends AbstractApi { use AcceptHeaderTrait; /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#create-a-check-suite + * @link https://docs.github.com/en/rest/reference/checks#create-a-check-suite * * @return array */ @@ -25,7 +25,7 @@ public function create(string $username, string $repository, array $params = []) } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#update-repository-preferences-for-check-suites + * @link https://docs.github.com/en/rest/reference/checks#update-repository-preferences-for-check-suites * * @return array */ @@ -37,7 +37,7 @@ public function updatePreferences(string $username, string $repository, array $p } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#get-a-check-suite + * @link https://docs.github.com/en/rest/reference/checks#get-a-check-suite * * @return array */ @@ -49,7 +49,7 @@ public function getCheckSuite(string $username, string $repository, int $checkSu } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#rerequest-a-check-suite + * @link https://docs.github.com/en/rest/reference/checks#rerequest-a-check-suite * * @return array */ @@ -61,7 +61,7 @@ public function rerequest(string $username, string $repository, int $checkSuiteI } /** - * @link https://docs.github.com/en/free-pro-team@latest/rest/reference/checks#list-check-suites-for-a-git-reference + * @link https://docs.github.com/en/rest/reference/checks#list-check-suites-for-a-git-reference * * @return array */ diff --git a/lib/Github/Api/Repository/Commits.php b/lib/Github/Api/Repository/Commits.php index 8195e4baf0f..0bc5598cbff 100644 --- a/lib/Github/Api/Repository/Commits.php +++ b/lib/Github/Api/Repository/Commits.php @@ -16,18 +16,23 @@ public function all($username, $repository, array $params) return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/commits', $params); } - public function compare($username, $repository, $base, $head, $mediaType = null) + public function compare($username, $repository, $base, $head, $mediaType = null, array $params = []) { $headers = []; if (null !== $mediaType) { $headers['Accept'] = $mediaType; } - return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/compare/'.rawurlencode($base).'...'.rawurlencode($head), [], $headers); + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/compare/'.rawurlencode($base).'...'.rawurlencode($head), $params, $headers); } public function show($username, $repository, $sha) { return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/commits/'.rawurlencode($sha)); } + + public function pulls($username, $repository, $sha, array $params = []) + { + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/commits/'.rawurlencode($sha).'/pulls', $params); + } } diff --git a/lib/Github/Api/Repository/Contents.php b/lib/Github/Api/Repository/Contents.php index bc78503b2f9..a3cc1a3ea0e 100644 --- a/lib/Github/Api/Repository/Contents.php +++ b/lib/Github/Api/Repository/Contents.php @@ -61,14 +61,15 @@ public function readme($username, $repository, $reference = null) * * @link http://developer.github.com/v3/repos/contents/ * - * @param string $username the user who owns the repository - * @param string $repository the name of the repository - * @param string|null $path path to file or directory - * @param string|null $reference reference to a branch or commit + * @param string $username the user who owns the repository + * @param string $repository the name of the repository + * @param string|null $path path to file or directory + * @param string|null $reference reference to a branch or commit + * @param array $requestHeaders request headers * * @return array|string information for file | information for each item in directory */ - public function show($username, $repository, $path = null, $reference = null) + public function show($username, $repository, $path = null, $reference = null, $requestHeaders = []) { $url = '/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/contents'; if (null !== $path) { @@ -77,7 +78,7 @@ public function show($username, $repository, $path = null, $reference = null) return $this->get($url, [ 'ref' => $reference, - ]); + ], $requestHeaders); } /** @@ -97,7 +98,7 @@ public function show($username, $repository, $path = null, $reference = null) * * @return array information about the new file */ - public function create($username, $repository, $path, $content, $message, $branch = null, array $committer = null) + public function create($username, $repository, $path, $content, $message, $branch = null, ?array $committer = null) { $url = '/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/contents/'.rawurlencode($path); @@ -173,14 +174,14 @@ public function exists($username, $repository, $path, $reference = null) * * @return array information about the updated file */ - public function update($username, $repository, $path, $content, $message, $sha, $branch = null, array $committer = null) + public function update($username, $repository, $path, $content, $message, $sha, $branch = null, ?array $committer = null) { $url = '/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/contents/'.rawurlencode($path); $parameters = [ 'content' => base64_encode($content), 'message' => $message, - 'sha' => $sha, + 'sha' => $sha, ]; if (null !== $branch) { @@ -214,13 +215,13 @@ public function update($username, $repository, $path, $content, $message, $sha, * * @return array information about the updated file */ - public function rm($username, $repository, $path, $message, $sha, $branch = null, array $committer = null) + public function rm($username, $repository, $path, $message, $sha, $branch = null, ?array $committer = null) { $url = '/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/contents/'.rawurlencode($path); $parameters = [ 'message' => $message, - 'sha' => $sha, + 'sha' => $sha, ]; if (null !== $branch) { @@ -294,4 +295,25 @@ public function download($username, $repository, $path, $reference = null) return base64_decode($file['content']) ?: null; } + + /** + * Get the raw content of a file in a repository. + * + * Use this method instead of the download method if your file is bigger than 1MB + * + * @see https://docs.github.com/en/rest/repos/contents + * + * @param string $username the user who owns the repository + * @param string $repository the name of the repository + * @param string $path path to file + * @param string|null $reference reference to a branch or commit + * + * @return array|string + */ + public function rawDownload($username, $repository, $path, $reference = null) + { + return $this->show($username, $repository, $path, $reference, [ + 'Accept' => 'application/vnd.github.VERSION.raw', + ]); + } } diff --git a/lib/Github/Api/Repository/Releases.php b/lib/Github/Api/Repository/Releases.php index 10dfe09d290..6cd7fda4f0a 100644 --- a/lib/Github/Api/Repository/Releases.php +++ b/lib/Github/Api/Repository/Releases.php @@ -68,6 +68,20 @@ public function show($username, $repository, $id) return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/releases/'.$id); } + /** + * Generate release notes content for a release. + * + * @param string $username + * @param string $repository + * @param array $params + * + * @return array + */ + public function generateNotes($username, $repository, array $params) + { + return $this->post('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/releases/generate-notes', $params); + } + /** * Create new release in selected repository. * diff --git a/lib/Github/Api/Repository/SecretScanning.php b/lib/Github/Api/Repository/SecretScanning.php new file mode 100644 index 00000000000..968d352c3ec --- /dev/null +++ b/lib/Github/Api/Repository/SecretScanning.php @@ -0,0 +1,64 @@ +get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/secret-scanning/alerts', $params); + } + + /** + * @link https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#get-a-secret-scanning-alert + * + * @param string $username + * @param string $repository + * @param int $alertNumber + * + * @return array|string + */ + public function getAlert(string $username, string $repository, int $alertNumber) + { + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/secret-scanning/alerts/'.$alertNumber); + } + + /** + * @link https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#update-a-secret-scanning-alert + * + * @param string $username + * @param string $repository + * @param int $alertNumber + * @param array $params + * + * @return array|string + */ + public function updateAlert(string $username, string $repository, int $alertNumber, array $params = []) + { + return $this->patch('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/secret-scanning/alerts/'.$alertNumber, $params); + } + + /** + * @link https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#list-locations-for-a-secret-scanning-alert + * + * @param string $username + * @param string $repository + * @param int $alertNumber + * @param array $params + * + * @return array|string + */ + public function locations(string $username, string $repository, int $alertNumber, array $params = []) + { + return $this->get('/repos/'.rawurlencode($username).'/'.rawurlencode($repository).'/secret-scanning/alerts/'.$alertNumber.'/locations', $params); + } +} diff --git a/lib/Github/Api/Search.php b/lib/Github/Api/Search.php index 24bd59bbf83..96a51ea6a46 100644 --- a/lib/Github/Api/Search.php +++ b/lib/Github/Api/Search.php @@ -61,6 +61,21 @@ public function code($q, $sort = 'updated', $order = 'desc') return $this->get('/search/code', ['q' => $q, 'sort' => $sort, 'order' => $order]); } + /** + * Search code by filter (q), but will return additional data to highlight + * the matched results. + * + * @link https://docs.github.com/en/rest/reference/search#text-match-metadata + * + * @return array list of code found + */ + public function codeWithMatch(string $q, string $sort = 'updated', string $order = 'desc'): array + { + $this->acceptHeaderValue = 'application/vnd.github.v3.text-match+json'; + + return $this->code($q, $sort, $order); + } + /** * Search users by filter (q). * diff --git a/lib/Github/Api/User.php b/lib/Github/Api/User.php index b36ae47123b..d436a2b835e 100644 --- a/lib/Github/Api/User.php +++ b/lib/Github/Api/User.php @@ -2,6 +2,8 @@ namespace Github\Api; +use Github\Api\User\Migration; + /** * Searching users, getting user information. * @@ -234,4 +236,24 @@ public function publicEvents($username) { return $this->get('/users/'.rawurlencode($username).'/events/public'); } + + /** + * List events performed by an authenticated user. + * + * @link https://docs.github.com/en/rest/reference/activity#list-events-for-the-authenticated-user + * + * @return array + */ + public function events(string $username) + { + return $this->get('/users/'.rawurlencode($username).'/events'); + } + + /** + * @return Migration + */ + public function migration(): Migration + { + return new Migration($this->getClient()); + } } diff --git a/lib/Github/Api/User/Migration.php b/lib/Github/Api/User/Migration.php new file mode 100644 index 00000000000..4e1b61ca244 --- /dev/null +++ b/lib/Github/Api/User/Migration.php @@ -0,0 +1,83 @@ +get('/user/migrations', $params); + } + + /** + * @link https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#start-a-user-migration + * + * @param array $params + * + * @return array|string + */ + public function start(array $params) + { + return $this->post('/user/migrations', $params); + } + + /** + * @link https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#get-a-user-migration-status + * + * @param int $migrationId + * @param array $params + * + * @return array|string + */ + public function status(int $migrationId, array $params = []) + { + return $this->get('/user/migrations/'.$migrationId, $params); + } + + /** + * @link https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#delete-a-user-migration-archive + * + * @param int $migrationId + * + * @return array|string + */ + public function deleteArchive(int $migrationId) + { + return $this->delete('/user/migrations/'.$migrationId.'/archive'); + } + + /** + * @link https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#unlock-a-user-repository + * + * @param int $migrationId + * @param string $repository + * + * @return array|string + */ + public function unlockRepo(int $migrationId, string $repository) + { + return $this->delete('/user/migrations/'.$migrationId.'/repos/'.rawurlencode($repository).'/lock'); + } + + /** + * @link https://docs.github.com/en/rest/migrations/users?apiVersion=2022-11-28#list-repositories-for-a-user-migration + * + * @param int $migrationId + * @param array $params + * + * @return array|string + */ + public function repos(int $migrationId, array $params = []) + { + return $this->get('/user/migrations/'.$migrationId.'/repositories', $params); + } +} diff --git a/lib/Github/AuthMethod.php b/lib/Github/AuthMethod.php new file mode 100644 index 00000000000..4a390699a3c --- /dev/null +++ b/lib/Github/AuthMethod.php @@ -0,0 +1,30 @@ + * @@ -73,15 +75,19 @@ class Client * Authenticate using a client_id/client_secret combination. * * @var string + * + * @deprecated Use the AuthMethod const */ - const AUTH_CLIENT_ID = 'client_id_header'; + const AUTH_CLIENT_ID = AuthMethod::CLIENT_ID; /** * Authenticate using a GitHub access token. * * @var string + * + * @deprecated Use the AuthMethod const */ - const AUTH_ACCESS_TOKEN = 'access_token_header'; + const AUTH_ACCESS_TOKEN = AuthMethod::ACCESS_TOKEN; /** * Constant for authentication method. @@ -90,8 +96,10 @@ class Client * to the API. * * @var string + * + * @deprecated Use the AuthMethod const */ - const AUTH_JWT = 'jwt'; + const AUTH_JWT = AuthMethod::JWT; /** * @var string @@ -115,10 +123,11 @@ class Client * @param string|null $apiVersion * @param string|null $enterpriseUrl */ - public function __construct(Builder $httpClientBuilder = null, $apiVersion = null, $enterpriseUrl = null) + public function __construct(?Builder $httpClientBuilder = null, $apiVersion = null, $enterpriseUrl = null) { $this->responseHistory = new History(); $this->httpClientBuilder = $builder = $httpClientBuilder ?? new Builder(); + $this->apiVersion = $apiVersion ?: 'v3'; $builder->addPlugin(new GithubExceptionThrower()); $builder->addPlugin(new Plugin\HistoryPlugin($this->responseHistory)); @@ -126,11 +135,9 @@ public function __construct(Builder $httpClientBuilder = null, $apiVersion = nul $builder->addPlugin(new Plugin\AddHostPlugin(Psr17FactoryDiscovery::findUriFactory()->createUri('https://api.github.com'))); $builder->addPlugin(new Plugin\HeaderDefaultsPlugin([ 'User-Agent' => 'php-github-api (http://github.com/KnpLabs/php-github-api)', + 'Accept' => sprintf('application/vnd.github.%s+json', $this->apiVersion), ])); - $this->apiVersion = $apiVersion ?: 'v3'; - $builder->addHeaderValue('Accept', sprintf('application/vnd.github.%s+json', $this->apiVersion)); - if ($enterpriseUrl) { $this->setEnterpriseUrl($enterpriseUrl); } @@ -294,6 +301,11 @@ public function api($name): AbstractApi $api = new Api\Organization\OutsideCollaborators($this); break; + case 'copilotUsage': + case 'copilot_usage': + $api = new Api\Copilot\Usage($this); + break; + default: throw new InvalidArgumentException(sprintf('Undefined api instance called: "%s"', $name)); } @@ -314,7 +326,7 @@ public function api($name): AbstractApi */ public function authenticate($tokenOrLogin, $password = null, $authMethod = null): void { - if (null === $authMethod && (self::AUTH_JWT === $password || self::AUTH_ACCESS_TOKEN === $password)) { + if (null === $authMethod && (AuthMethod::JWT === $password || AuthMethod::ACCESS_TOKEN === $password)) { $authMethod = $password; $password = null; } @@ -341,7 +353,14 @@ private function setEnterpriseUrl($enterpriseUrl): void $builder->removePlugin(PathPrepend::class); $builder->addPlugin(new Plugin\AddHostPlugin(Psr17FactoryDiscovery::findUriFactory()->createUri($enterpriseUrl))); - $builder->addPlugin(new PathPrepend(sprintf('/api/%s', $this->getApiVersion()))); + + // For GHE, v4 API endpoint is at `api/graphql` so we don't want to add the version number + // For earlier versions add the version number after /api + if ($this->getApiVersion() === 'v4') { + $builder->addPlugin(new PathPrepend('/api')); + } else { + $builder->addPlugin(new PathPrepend(sprintf('/api/%s', $this->getApiVersion()))); + } } /** diff --git a/lib/Github/Exception/ApiLimitExceedException.php b/lib/Github/Exception/ApiLimitExceedException.php index 5c1dd4d8a17..c21f5c2729e 100644 --- a/lib/Github/Exception/ApiLimitExceedException.php +++ b/lib/Github/Exception/ApiLimitExceedException.php @@ -20,7 +20,7 @@ class ApiLimitExceedException extends RuntimeException * @param int $code * @param Throwable|null $previous */ - public function __construct(int $limit = 5000, int $reset = 1800, int $code = 0, Throwable $previous = null) + public function __construct(int $limit = 5000, int $reset = 1800, int $code = 0, ?Throwable $previous = null) { $this->limit = (int) $limit; $this->reset = (int) $reset; diff --git a/lib/Github/Exception/MissingArgumentException.php b/lib/Github/Exception/MissingArgumentException.php index 4cd3aeca81d..742cdc5ac7f 100644 --- a/lib/Github/Exception/MissingArgumentException.php +++ b/lib/Github/Exception/MissingArgumentException.php @@ -14,7 +14,7 @@ class MissingArgumentException extends ErrorException * @param int $code * @param Throwable|null $previous */ - public function __construct($required, int $code = 0, Throwable $previous = null) + public function __construct($required, int $code = 0, ?Throwable $previous = null) { if (is_string($required)) { $required = [$required]; diff --git a/lib/Github/Exception/SsoRequiredException.php b/lib/Github/Exception/SsoRequiredException.php index 1725270a036..09b9d63db08 100644 --- a/lib/Github/Exception/SsoRequiredException.php +++ b/lib/Github/Exception/SsoRequiredException.php @@ -14,7 +14,7 @@ class SsoRequiredException extends RuntimeException * @param int $code * @param Throwable|null $previous */ - public function __construct(string $url, int $code = 0, Throwable $previous = null) + public function __construct(string $url, int $code = 0, ?Throwable $previous = null) { $this->url = $url; diff --git a/lib/Github/Exception/TwoFactorAuthenticationRequiredException.php b/lib/Github/Exception/TwoFactorAuthenticationRequiredException.php index c57e67b8e1d..139033dff5b 100644 --- a/lib/Github/Exception/TwoFactorAuthenticationRequiredException.php +++ b/lib/Github/Exception/TwoFactorAuthenticationRequiredException.php @@ -14,7 +14,7 @@ class TwoFactorAuthenticationRequiredException extends RuntimeException * @param int $code * @param Throwable|null $previous */ - public function __construct(string $type, int $code = 0, Throwable $previous = null) + public function __construct(string $type, int $code = 0, ?Throwable $previous = null) { $this->type = $type; parent::__construct('Two factor authentication is enabled on this account', $code, $previous); diff --git a/lib/Github/HttpClient/Builder.php b/lib/Github/HttpClient/Builder.php index a8713de13bc..c77f1ac83d8 100644 --- a/lib/Github/HttpClient/Builder.php +++ b/lib/Github/HttpClient/Builder.php @@ -78,9 +78,9 @@ class Builder * @param StreamFactoryInterface|null $streamFactory */ public function __construct( - ClientInterface $httpClient = null, - RequestFactoryInterface $requestFactory = null, - StreamFactoryInterface $streamFactory = null + ?ClientInterface $httpClient = null, + ?RequestFactoryInterface $requestFactory = null, + ?StreamFactoryInterface $streamFactory = null ) { $this->httpClient = $httpClient ?? Psr18ClientDiscovery::find(); $this->requestFactory = $requestFactory ?? Psr17FactoryDiscovery::findRequestFactory(); diff --git a/lib/Github/HttpClient/Plugin/Authentication.php b/lib/Github/HttpClient/Plugin/Authentication.php index 2b533436617..91ed9caa2cf 100644 --- a/lib/Github/HttpClient/Plugin/Authentication.php +++ b/lib/Github/HttpClient/Plugin/Authentication.php @@ -2,7 +2,7 @@ namespace Github\HttpClient\Plugin; -use Github\Client; +use Github\AuthMethod; use Github\Exception\RuntimeException; use Http\Client\Common\Plugin; use Http\Promise\Promise; @@ -58,11 +58,11 @@ public function handleRequest(RequestInterface $request, callable $next, callabl private function getAuthorizationHeader(): string { switch ($this->method) { - case Client::AUTH_CLIENT_ID: + case AuthMethod::CLIENT_ID: return sprintf('Basic %s', base64_encode($this->tokenOrLogin.':'.$this->password)); - case Client::AUTH_ACCESS_TOKEN: + case AuthMethod::ACCESS_TOKEN: return sprintf('token %s', $this->tokenOrLogin); - case Client::AUTH_JWT: + case AuthMethod::JWT: return sprintf('Bearer %s', $this->tokenOrLogin); default: throw new RuntimeException(sprintf('%s not yet implemented', $this->method)); diff --git a/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php b/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php index e4adb6a5f5c..9479aaaf2be 100644 --- a/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php +++ b/lib/Github/HttpClient/Plugin/GithubExceptionThrower.php @@ -34,7 +34,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl // If error: $remaining = ResponseMediator::getHeader($response, 'X-RateLimit-Remaining'); - if (null !== $remaining && 1 > $remaining && 'rate_limit' !== substr($request->getRequestTarget(), 1, 10)) { + if ((429 === $response->getStatusCode()) && null !== $remaining && 1 > $remaining && 'rate_limit' !== substr($request->getRequestTarget(), 1, 10)) { $limit = (int) ResponseMediator::getHeader($response, 'X-RateLimit-Limit'); $reset = (int) ResponseMediator::getHeader($response, 'X-RateLimit-Reset'); @@ -56,7 +56,7 @@ public function handleRequest(RequestInterface $request, callable $next, callabl if (422 === $response->getStatusCode() && isset($content['errors'])) { $errors = []; foreach ($content['errors'] as $error) { - switch ($error['code']) { + switch ($error['code'] ?? null) { case 'missing': $errors[] = sprintf('The %s %s does not exist, for resource "%s"', $error['field'], $error['value'], $error['resource']); break; @@ -78,11 +78,16 @@ public function handleRequest(RequestInterface $request, callable $next, callabl break; default: + if (is_string($error)) { + $errors[] = $error; + + break; + } + if (isset($error['message'])) { $errors[] = $error['message']; } break; - } } @@ -114,6 +119,21 @@ public function handleRequest(RequestInterface $request, callable $next, callabl throw new SsoRequiredException($url); } + $remaining = ResponseMediator::getHeader($response, 'X-RateLimit-Remaining'); + if ((403 === $response->getStatusCode()) && null !== $remaining && 1 > $remaining && isset($content['message']) && (0 === strpos($content['message'], 'API rate limit exceeded'))) { + $limit = (int) ResponseMediator::getHeader($response, 'X-RateLimit-Limit'); + $reset = (int) ResponseMediator::getHeader($response, 'X-RateLimit-Reset'); + + throw new ApiLimitExceedException($limit, $reset); + } + + $reset = (int) ResponseMediator::getHeader($response, 'X-RateLimit-Reset'); + if ((403 === $response->getStatusCode()) && 0 < $reset && isset($content['message']) && (0 === strpos($content['message'], 'You have exceeded a secondary rate limit'))) { + $limit = (int) ResponseMediator::getHeader($response, 'X-RateLimit-Limit'); + + throw new ApiLimitExceedException($limit, $reset); + } + throw new RuntimeException(isset($content['message']) ? $content['message'] : $content, $response->getStatusCode()); }); } diff --git a/lib/Github/ResultPager.php b/lib/Github/ResultPager.php index 5f9c40d0911..fb8739c4a1c 100644 --- a/lib/Github/ResultPager.php +++ b/lib/Github/ResultPager.php @@ -59,7 +59,7 @@ class ResultPager implements ResultPagerInterface * * @return void */ - public function __construct(Client $client, int $perPage = null) + public function __construct(Client $client, ?int $perPage = null) { if (null !== $perPage && ($perPage < 1 || $perPage > 100)) { throw new ValueError(sprintf('%s::__construct(): Argument #2 ($perPage) must be between 1 and 100, or null', self::class)); @@ -86,7 +86,11 @@ public function fetch(AbstractApi $api, string $method, array $parameters = []): $api = $closure($api); $result = $api->$method(...$parameters); - $this->postFetch(); + if ($result === '') { + $result = []; + } + + $this->postFetch(true); return $result; } @@ -130,9 +134,13 @@ public function fetchAllLazy(AbstractApi $api, string $method, array $parameters /** * {@inheritdoc} */ - public function postFetch(): void + public function postFetch(/* $skipDeprecation = false */): void { - $this->pagination = ResponseMediator::getPagination($this->client->getLastResponse()); + if (func_num_args() === 0 || (func_num_args() > 0 && false === func_get_arg(0))) { + trigger_deprecation('KnpLabs/php-github-api', '3.2', 'The "%s" method is deprecated and will be removed.', __METHOD__); + } + + $this->setPagination(); } /** @@ -196,8 +204,13 @@ protected function get(string $key): array $result = $this->client->getHttpClient()->get($this->pagination[$key]); - $this->postFetch(); + $this->postFetch(true); return ResponseMediator::getContent($result); } + + private function setPagination(): void + { + $this->pagination = ResponseMediator::getPagination($this->client->getLastResponse()); + } } diff --git a/lib/Github/ResultPagerInterface.php b/lib/Github/ResultPagerInterface.php index 350f8453e05..bf7618ee411 100644 --- a/lib/Github/ResultPagerInterface.php +++ b/lib/Github/ResultPagerInterface.php @@ -54,6 +54,8 @@ public function fetchAllLazy(AbstractApi $api, string $method, array $parameters /** * Method that performs the actual work to refresh the pagination property. * + * @deprecated since 3.2 and will be removed in 4.0. + * * @return void */ public function postFetch(): void; diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 3b6dc204b03..98d2e51cc8f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -27,4 +27,8 @@ ./lib/Github/ + + + + diff --git a/test/Github/Tests/Api/AbstractApiTest.php b/test/Github/Tests/Api/AbstractApiTest.php index 428ece12cf3..53e0eb6970a 100644 --- a/test/Github/Tests/Api/AbstractApiTest.php +++ b/test/Github/Tests/Api/AbstractApiTest.php @@ -4,6 +4,7 @@ use Github\Api\AbstractApi; use GuzzleHttp\Psr7\Response; +use GuzzleHttp\Psr7\Utils; use Http\Client\Common\HttpMethodsClientInterface; class AbstractApiTest extends TestCase @@ -232,7 +233,7 @@ private function getPSR7Response($expectedArray) return new Response( 200, ['Content-Type' => 'application/json'], - \GuzzleHttp\Psr7\stream_for(json_encode($expectedArray)) + Utils::streamFor(json_encode($expectedArray)) ); } } diff --git a/test/Github/Tests/Api/App/HookTest.php b/test/Github/Tests/Api/App/HookTest.php new file mode 100644 index 00000000000..f2ed6ae5ab4 --- /dev/null +++ b/test/Github/Tests/Api/App/HookTest.php @@ -0,0 +1,109 @@ + 'json', + 'insecure_ssl' => 0, + 'secret' => '********', + 'url' => 'https://localhost/', + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/app/hook/config', []) + ->willReturn($result); + + $this->assertEquals($result, $api->showConfig()); + } + + /** + * @test + */ + public function shouldUpdateHookConfiguration() + { + $parameters = [ + 'content_type' => 'json', + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('patch') + ->with('/app/hook/config', $parameters) + ->willReturn([]); + + $this->assertEquals([], $api->updateConfig($parameters)); + } + + /** + * @test + */ + public function shouldListHookDelivieries() + { + $result = []; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/app/hook/deliveries', []) + ->willReturn($result); + + $this->assertEquals($result, $api->deliveries()); + } + + /** + * @test + */ + public function shouldListHookDeliviery() + { + $result = []; + + $delivery = 1234567; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/app/hook/deliveries/'.$delivery, []) + ->willReturn($result); + + $this->assertEquals($result, $api->delivery($delivery)); + } + + /** + * @test + */ + public function shouldRedeliveryHook() + { + $result = []; + + $delivery = 1234567; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('/app/hook/deliveries/'.$delivery.'/attempts', []) + ->willReturn($result); + + $this->assertEquals($result, $api->redeliver($delivery)); + } + + /** + * @return string + */ + protected function getApiClass() + { + return \Github\Api\App\Hook::class; + } +} diff --git a/test/Github/Tests/Api/AppTest.php b/test/Github/Tests/Api/AppTest.php index e5d5fcf57b4..b813a11dd1f 100644 --- a/test/Github/Tests/Api/AppTest.php +++ b/test/Github/Tests/Api/AppTest.php @@ -66,7 +66,7 @@ public function shouldGetInstallationForOrganization() $api = $this->getApiMock(); $api->expects($this->once()) ->method('get') - ->with('/org/1234/installation') + ->with('/orgs/1234/installation') ->willReturn($result); $this->assertEquals($result, $api->getInstallationForOrganization('1234')); @@ -160,6 +160,23 @@ public function shouldRemoveRepositoryToInstallation() $api->removeRepository('1234', '5678'); } + /** + * @test + */ + public function shouldGetAuthenticatedApp() + { + $api = $this->getApiMock(); + + $result = ['authenticatedApp1']; + + $api->expects($this->once()) + ->method('get') + ->with('/app') + ->willReturn($result); + + $this->assertEquals($result, $api->getAuthenticatedApp()); + } + /** * @return string */ diff --git a/test/Github/Tests/Api/Copilot/UsageTest.php b/test/Github/Tests/Api/Copilot/UsageTest.php new file mode 100644 index 00000000000..c14c3e3ffa8 --- /dev/null +++ b/test/Github/Tests/Api/Copilot/UsageTest.php @@ -0,0 +1,78 @@ +getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/copilot/usage', []) + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->orgUsageSummary('KnpLabs')); + } + + /** + * @test + */ + public function shouldGetOrgTeamUsageSummary(): void + { + $expectedValue = ['usage1', 'usage2']; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/team/php-github-api/copilot/usage', []) + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->orgTeamUsageSummary('KnpLabs', 'php-github-api')); + } + + /** + * @test + */ + public function shouldGetEnterpriseUsageSummary(): void + { + $expectedValue = ['usage1', 'usage2']; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/enterprises/KnpLabs/copilot/usage', []) + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->enterpriseUsageSummary('KnpLabs')); + } + + /** + * @test + */ + public function shouldGetEnterpriseTeamUsageSummary(): void + { + $expectedValue = ['usage1', 'usage2']; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/enterprises/KnpLabs/team/php-github-api/copilot/usage', []) + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->enterpriseTeamUsageSummary('KnpLabs', 'php-github-api')); + } + + protected function getApiClass(): string + { + return Usage::class; + } +} diff --git a/test/Github/Tests/Api/CurrentUser/MembershipsTest.php b/test/Github/Tests/Api/CurrentUser/MembershipsTest.php index d3d8e1cbc77..aef9f374c23 100644 --- a/test/Github/Tests/Api/CurrentUser/MembershipsTest.php +++ b/test/Github/Tests/Api/CurrentUser/MembershipsTest.php @@ -15,21 +15,21 @@ public function shouldGetMemberships() [ 'organization' => [ 'login' => 'octocat', - 'id' => 1, + 'id' => 1, ], - 'user' => [ + 'user' => [ 'login' => 'defunkt', - 'id' => 3, + 'id' => 3, ], ], [ 'organization' => [ 'login' => 'invitocat', - 'id' => 2, + 'id' => 2, ], - 'user' => [ + 'user' => [ 'login' => 'defunkt', - 'id' => 3, + 'id' => 3, ], ], ]; @@ -51,11 +51,11 @@ public function shouldGetMembershipsForOrganization() $expectedValue = [ 'organization' => [ 'login' => 'invitocat', - 'id' => 2, + 'id' => 2, ], - 'user' => [ + 'user' => [ 'login' => 'defunkt', - 'id' => 3, + 'id' => 3, ], ]; diff --git a/test/Github/Tests/Api/Deployment/EnvironmentsTest.php b/test/Github/Tests/Api/Deployment/EnvironmentsTest.php new file mode 100644 index 00000000000..ab761ab90cf --- /dev/null +++ b/test/Github/Tests/Api/Deployment/EnvironmentsTest.php @@ -0,0 +1,73 @@ +getApiMock(); + + $api->expects($this->once()) + ->method('put') + ->with('/repos/KnpLabs/php-github-api/environments/production'); + + $api->createOrUpdate('KnpLabs', 'php-github-api', 'production'); + } + + /** + * @test + */ + public function shouldGetAllEnvironments() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/environments'); + + $api->all('KnpLabs', 'php-github-api'); + } + + /** + * @test + */ + public function shouldShowEnvironment() + { + $expectedValue = 'production'; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/environments/production') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->show('KnpLabs', 'php-github-api', 'production')); + } + + /** + * @test + */ + public function shouldDeleteEnvironment() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('/repos/KnpLabs/php-github-api/environments/production') + ->will($this->returnValue(null)); + + $this->assertNull($api->remove('KnpLabs', 'php-github-api', 'production')); + } + + /** + * @return string + */ + protected function getApiClass() + { + return \Github\Api\Deployment\Environments::class; + } +} diff --git a/test/Github/Tests/Api/Deployment/PoliciesTest.php b/test/Github/Tests/Api/Deployment/PoliciesTest.php new file mode 100644 index 00000000000..6b387881ce7 --- /dev/null +++ b/test/Github/Tests/Api/Deployment/PoliciesTest.php @@ -0,0 +1,91 @@ +getApiMock(); + + $api->expects($this->once()) + ->method('post') + ->with('/repos/KnpLabs/php-github-api/environments/production/deployment-branch-policies'); + + $api->create('KnpLabs', 'php-github-api', 'production', [ + 'name' => 'name', + ]); + } + + /** + * @test + */ + public function shouldUpdatePolicy() + { + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('put') + ->with('/repos/KnpLabs/php-github-api/environments/production/deployment-branch-policies/1'); + + $api->update('KnpLabs', 'php-github-api', 'production', 1, [ + 'name' => 'name', + ]); + } + + /** + * @test + */ + public function shouldGetAllPolicies() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/environments/production/deployment-branch-policies'); + + $api->all('KnpLabs', 'php-github-api', 'production'); + } + + /** + * @test + */ + public function shouldShowPolicy() + { + $expectedValue = 'production'; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/environments/production/deployment-branch-policies/1') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->show('KnpLabs', 'php-github-api', 'production', 1)); + } + + /** + * @test + */ + public function shouldDeletePolicy() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('/repos/KnpLabs/php-github-api/environments/production/deployment-branch-policies/1') + ->will($this->returnValue(null)); + + $this->assertNull($api->remove('KnpLabs', 'php-github-api', 'production', 1)); + } + + /** + * @return string + */ + protected function getApiClass() + { + return \Github\Api\Deployment\Policies::class; + } +} diff --git a/test/Github/Tests/Api/DeploymentTest.php b/test/Github/Tests/Api/DeploymentTest.php index 223f3e2fd33..8741ee625f7 100644 --- a/test/Github/Tests/Api/DeploymentTest.php +++ b/test/Github/Tests/Api/DeploymentTest.php @@ -51,7 +51,7 @@ public function shouldGetAllDeploymentsWithFilterParameters() /** * @test */ - public function shouldShowProject() + public function shouldShowDeployment() { $expectedValue = ['id' => 123, 'ref' => 'master']; @@ -64,6 +64,20 @@ public function shouldShowProject() $this->assertEquals($expectedValue, $api->show('KnpLabs', 'php-github-api', 123)); } + /** + * @test + */ + public function shouldDeleteDeployment() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('/repos/KnpLabs/php-github-api/deployments/123') + ->will($this->returnValue(null)); + + $this->assertNull($api->remove('KnpLabs', 'php-github-api', 123)); + } + /** * @test */ @@ -104,6 +118,26 @@ public function shouldGetAllStatuses() $api->getStatuses('KnpLabs', 'php-github-api', 1); } + /** + * @test + */ + public function shouldGetEnvironmentsApiObject() + { + $api = $this->getApiMock(); + + $this->assertInstanceOf(\Github\Api\Deployment\Environments::class, $api->environments()); + } + + /** + * @test + */ + public function shouldGetPoliciesApiObject() + { + $api = $this->getApiMock(); + + $this->assertInstanceOf(\Github\Api\Deployment\Policies::class, $api->policies()); + } + /** * @return string */ diff --git a/test/Github/Tests/Api/Enterprise/SecretScanningTest.php b/test/Github/Tests/Api/Enterprise/SecretScanningTest.php new file mode 100644 index 00000000000..cc5b14b6547 --- /dev/null +++ b/test/Github/Tests/Api/Enterprise/SecretScanningTest.php @@ -0,0 +1,41 @@ + 1, 'state' => 'resolved', 'resolution' => 'false_positive'], + ['number' => 2, 'state' => 'open', 'resolution' => null], + ['number' => 3, 'state' => 'resolved', 'resolution' => 'wont_fix'], + ['number' => 4, 'state' => 'resolved', 'resolution' => 'revoked'], + ]; + + /** @var SecretScanning|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/enterprises/KnpLabs/secret-scanning/alerts') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->alerts('KnpLabs', [ + 'state' => 'all', + ])); + } + + protected function getApiClass() + { + return \Github\Api\Enterprise\SecretScanning::class; + } +} diff --git a/test/Github/Tests/Api/Enterprise/StatsTest.php b/test/Github/Tests/Api/Enterprise/StatsTest.php index d3a8a89883a..f97060e0a14 100644 --- a/test/Github/Tests/Api/Enterprise/StatsTest.php +++ b/test/Github/Tests/Api/Enterprise/StatsTest.php @@ -24,6 +24,7 @@ public function shouldShowStats() /** * @test + * * @dataProvider getTypes */ public function shouldShowStatsByType($type) diff --git a/test/Github/Tests/Api/Environment/SecretsTest.php b/test/Github/Tests/Api/Environment/SecretsTest.php new file mode 100644 index 00000000000..0609a64f0f6 --- /dev/null +++ b/test/Github/Tests/Api/Environment/SecretsTest.php @@ -0,0 +1,116 @@ + 'name', 'created_at' => 'created_at', 'updated_at' => 'updated_at'], + ['name' => 'name', 'created_at' => 'created_at', 'updated_at' => 'updated_at'], + ['name' => 'name', 'created_at' => 'created_at', 'updated_at' => 'updated_at'], + ]; + + /** @var Secrets|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repositories/3948501/environments/production/secrets') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->all(3948501, 'production')); + } + + /** + * @test + */ + public function shouldGetEnvironmentSecret() + { + $expectedArray = []; + + /** @var Secrets|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repositories/3948501/environments/production/secrets/secretName') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->show(3948501, 'production', 'secretName')); + } + + /** + * @test + */ + public function shouldUpdateOrCreateEnvironmentSecret() + { + $expectedValue = 'response'; + + /** @var Secrets|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('put') + ->with('/repositories/3948501/environments/production/secrets/secretName') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->createOrUpdate(3948501, 'production', 'secretName', [ + 'encrypted_value' => 'foo', 'key_id' => 'key_id', + ])); + } + + /** + * @test + */ + public function shouldRemoveEnvironmentSecret() + { + $expectedValue = 'response'; + + /** @var Secrets|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('delete') + ->with('/repositories/3948501/environments/production/secrets/secretName') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->remove(3948501, 'production', 'secretName')); + } + + /** + * @test + */ + public function shouldGetPublicKey() + { + $expectedArray = ['key_id' => 'key_id', 'key' => 'foo']; + + /** @var Secrets|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repositories/3948501/environments/production/secrets/public-key') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->publicKey(3948501, 'production')); + } + + protected function getApiClass() + { + return Secrets::class; + } +} diff --git a/test/Github/Tests/Api/Environment/VariablesTest.php b/test/Github/Tests/Api/Environment/VariablesTest.php new file mode 100644 index 00000000000..0fc01193fd1 --- /dev/null +++ b/test/Github/Tests/Api/Environment/VariablesTest.php @@ -0,0 +1,118 @@ + 'name', 'value' => 'value', 'created_at' => 'created_at', 'updated_at' => 'updated_at'], + ['name' => 'name', 'value' => 'value', 'created_at' => 'created_at', 'updated_at' => 'updated_at'], + ['name' => 'name', 'value' => 'value', 'created_at' => 'created_at', 'updated_at' => 'updated_at'], + ]; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repositories/3948501/environments/production/variables') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->all(3948501, 'production')); + } + + /** + * @test + */ + public function shouldGetEnvironmentVariable() + { + $expectedArray = []; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repositories/3948501/environments/production/variables/variableName') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->show(3948501, 'production', 'variableName')); + } + + /** + * @test + */ + public function shouldCreateEnvironmentVariable() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('post') + ->with('/repositories/3948501/environments/production/variables') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->create(3948501, 'production', [ + 'name' => 'foo', 'value' => 'bar', + ])); + } + + /** + * @test + */ + public function shouldUpdateEnvironmentVariable() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('patch') + ->with('/repositories/3948501/environments/production/variables/variableName') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->update(3948501, 'production', 'variableName', [ + 'name' => 'variableName', 'value' => 'bar', + ])); + } + + /** + * @test + */ + public function shouldRemoveEnvironmentVariable() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('delete') + ->with('/repositories/3948501/environments/production/variables/variableName') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->remove(3948501, 'production', 'variableName')); + } + + protected function getApiClass() + { + return Variables::class; + } +} diff --git a/test/Github/Tests/Api/GistsTest.php b/test/Github/Tests/Api/GistsTest.php index 093af712911..ff4673e4082 100644 --- a/test/Github/Tests/Api/GistsTest.php +++ b/test/Github/Tests/Api/GistsTest.php @@ -227,10 +227,10 @@ public function shouldUpdateGist() 'files' => [ 'filename.txt' => [ 'filename' => 'new_name.txt', - 'content' => 'content', + 'content' => 'content', ], 'filename_new.txt' => [ - 'content' => 'content new', + 'content' => 'content new', ], ], ]; diff --git a/test/Github/Tests/Api/GitData/BlobsTest.php b/test/Github/Tests/Api/GitData/BlobsTest.php index 368d47c3cc2..4b87ed33e41 100644 --- a/test/Github/Tests/Api/GitData/BlobsTest.php +++ b/test/Github/Tests/Api/GitData/BlobsTest.php @@ -68,21 +68,6 @@ public function shouldCreateBlob() $this->assertEquals($expectedValue, $api->create('l3l0', 'l3l0repo', $data)); } - /** - * @test - */ - public function shouldNotCreateBlobWithoutEncoding() - { - $this->expectException(MissingArgumentException::class); - $data = ['content' => 'some cotent']; - - $api = $this->getApiMock(); - $api->expects($this->never()) - ->method('post'); - - $api->create('l3l0', 'l3l0repo', $data); - } - /** * @test */ diff --git a/test/Github/Tests/Api/GitData/TreesTest.php b/test/Github/Tests/Api/GitData/TreesTest.php index 901af559e24..0b415f1fb1c 100644 --- a/test/Github/Tests/Api/GitData/TreesTest.php +++ b/test/Github/Tests/Api/GitData/TreesTest.php @@ -35,13 +35,13 @@ public function shouldCreateTreeUsingSha() 'path' => 'path', 'mode' => 'mode', 'type' => 'type', - 'sha' => '1234', + 'sha' => '1234', ], [ 'path' => 'htap', 'mode' => 'edom', 'type' => 'epyt', - 'sha' => '4321', + 'sha' => '4321', ], ], ]; @@ -118,7 +118,7 @@ public function shouldNotCreateTreeWithoutPathParam() 'tree' => [ 'mode' => 'mode', 'type' => 'type', - 'content' => 'content', + 'content' => 'content', ], ]; @@ -139,7 +139,7 @@ public function shouldNotCreateTreeWithoutModeParam() 'tree' => [ 'path' => 'path', 'type' => 'type', - 'content' => 'content', + 'content' => 'content', ], ]; @@ -160,7 +160,7 @@ public function shouldNotCreateTreeWithoutTypeParam() 'tree' => [ 'path' => 'path', 'mode' => 'mode', - 'content' => 'content', + 'content' => 'content', ], ]; diff --git a/test/Github/Tests/Api/GraphQLTest.php b/test/Github/Tests/Api/GraphQLTest.php index 042cb014a50..b241cc5ae90 100644 --- a/test/Github/Tests/Api/GraphQLTest.php +++ b/test/Github/Tests/Api/GraphQLTest.php @@ -13,7 +13,7 @@ public function shouldTestGraphQL() $api->expects($this->once()) ->method('post') - ->with($this->equalTo('/graphql'), $this->equalTo(['query'=>'bar'])) + ->with($this->equalTo('/graphql'), $this->equalTo(['query' => 'bar'])) ->will($this->returnValue('foo')); $result = $api->execute('bar'); @@ -44,7 +44,7 @@ public function shouldJSONEncodeGraphQLVariables() $api->expects($this->once()) ->method('post') ->with('/graphql', $this->equalTo([ - 'query'=>'bar', + 'query' => 'bar', 'variables' => '{"variable":"foo"}', ])); diff --git a/test/Github/Tests/Api/IssueTest.php b/test/Github/Tests/Api/IssueTest.php index bc8b80fdf5e..a151076ce1f 100644 --- a/test/Github/Tests/Api/IssueTest.php +++ b/test/Github/Tests/Api/IssueTest.php @@ -35,10 +35,10 @@ public function shouldGetIssuesUsingAdditionalParameters() $data = [ 'state' => 'open', 'milestone' => '*', - 'assignee' => 'l3l0', + 'assignee' => 'l3l0', 'mentioned' => 'l3l0', - 'labels' => 'bug,@high', - 'sort' => 'created', + 'labels' => 'bug,@high', + 'sort' => 'created', 'direction' => 'asc', ]; $sentData = $data + [ @@ -77,7 +77,7 @@ public function shouldCreateIssue() { $data = [ 'title' => 'some title', - 'body' => 'some body', + 'body' => 'some body', ]; $api = $this->getApiMock(); @@ -95,7 +95,7 @@ public function shouldNotCreateIssueWithoutTitle() { $this->expectException(MissingArgumentException::class); $data = [ - 'body' => 'some body', + 'body' => 'some body', ]; $api = $this->getApiMock(); diff --git a/test/Github/Tests/Api/Organization/Actions/SecretsTest.php b/test/Github/Tests/Api/Organization/Actions/SecretsTest.php index cf10c066c99..324b706975d 100644 --- a/test/Github/Tests/Api/Organization/Actions/SecretsTest.php +++ b/test/Github/Tests/Api/Organization/Actions/SecretsTest.php @@ -206,7 +206,7 @@ public function shouldGetPublicKey() $api ->expects($this->once()) ->method('get') - ->with('/orgs/KnpLabs/actions/secrets/secret-key') + ->with('/orgs/KnpLabs/actions/secrets/public-key') ->will($this->returnValue($expectedArray)); $this->assertEquals($expectedArray, $api->publicKey('KnpLabs')); diff --git a/test/Github/Tests/Api/Organization/Actions/SelfHostedRunnersTest.php b/test/Github/Tests/Api/Organization/Actions/SelfHostedRunnersTest.php new file mode 100644 index 00000000000..e313a88202a --- /dev/null +++ b/test/Github/Tests/Api/Organization/Actions/SelfHostedRunnersTest.php @@ -0,0 +1,115 @@ + 1, + 'name' => 'MBP', + 'os' => 'macos', + 'status' => 'online', + ], + [ + 'id' => 2, + 'name' => 'iMac', + 'os' => 'macos', + 'status' => 'offline', + ], + ]; + + /** @var SelfHostedRunners|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/actions/runners') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->all('KnpLabs')); + } + + /** + * @test + */ + public function shouldGetSelfHostedRunner() + { + $expectedArray = [ + 'id' => 1, + 'name' => 'MBP', + 'os' => 'macos', + 'status' => 'online', + ]; + + /** @var SelfHostedRunners|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/actions/runners/1') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->show('KnpLabs', 1)); + } + + /** + * @test + */ + public function shouldRemoveSelfHostedRunner() + { + $expectedValue = 'response'; + + /** @var SelfHostedRunners|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('delete') + ->with('/orgs/KnpLabs/actions/runners/1') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->remove('KnpLabs', 1)); + } + + /** + * @test + */ + public function shouldGetSelfHostedRunnerApps() + { + $expectedArray = [ + ['os' => 'osx', 'architecture' => 'x64', 'download_url' => 'download_url', 'filename' => 'filename'], + ['os' => 'linux', 'architecture' => 'x64', 'download_url' => 'download_url', 'filename' => 'filename'], + ['os' => 'linux', 'architecture' => 'arm', 'download_url' => 'download_url', 'filename' => 'filename'], + ['os' => 'win', 'architecture' => 'x64', 'download_url' => 'download_url', 'filename' => 'filename'], + ['os' => 'linux', 'architecture' => 'arm64', 'download_url' => 'download_url', 'filename' => 'filename'], + ]; + + /** @var SelfHostedRunners|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/actions/runners/downloads') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->applications('KnpLabs')); + } + + protected function getApiClass() + { + return SelfHostedRunners::class; + } +} diff --git a/test/Github/Tests/Api/Organization/Actions/VariablesTest.php b/test/Github/Tests/Api/Organization/Actions/VariablesTest.php new file mode 100644 index 00000000000..98d5072377e --- /dev/null +++ b/test/Github/Tests/Api/Organization/Actions/VariablesTest.php @@ -0,0 +1,198 @@ + 'name', 'value' => 'value', 'created_at' => 'created_at', 'updated_at' => 'updated_at', 'visibility' => 'all'], + ['name' => 'name', 'value' => 'value', 'created_at' => 'created_at', 'updated_at' => 'updated_at', 'visibility' => 'private'], + ['name' => 'name', 'value' => 'value', 'created_at' => 'created_at', 'updated_at' => 'updated_at', 'visibility' => 'selected'], + ]; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/actions/variables') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->all('KnpLabs')); + } + + /** + * @test + */ + public function shouldGetOrganizationVariable() + { + $expectedArray = []; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/actions/variables/variableName') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->show('KnpLabs', 'variableName')); + } + + /** + * @test + */ + public function shouldCreateOrganizationVariable() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('post') + ->with('/orgs/KnpLabs/actions/variables') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->create('KnpLabs', [ + 'name' => 'foo', 'value' => 'value', 'visibility' => 'all', + ])); + } + + /** + * @test + */ + public function shouldUpdateOrganizationVariable() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('patch') + ->with('/orgs/KnpLabs/actions/variables/variableName') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->update('KnpLabs', 'variableName', [ + 'name' => 'foo', 'value' => 'value', 'visibility' => 'private', + ])); + } + + /** + * @test + */ + public function shouldRemoveOrganizationVariable() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('delete') + ->with('/orgs/KnpLabs/actions/variables/variableName') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->remove('KnpLabs', 'variableName')); + } + + /** + * @test + */ + public function shouldGetSelectedRepositories() + { + $expectedArray = [1, 2, 3]; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/actions/variables/variableName/repositories') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->selectedRepositories('KnpLabs', 'variableName')); + } + + /** + * @test + */ + public function shouldSetSelectedRepositories() + { + $expectedArray = [ + 'selected_repository_ids' => [1, 2, 3], + ]; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('put') + ->with('/orgs/KnpLabs/actions/variables/variableName/repositories') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->setSelectedRepositories('KnpLabs', 'variableName', [ + 'selected_repository_ids' => [1, 2, 3], + ])); + } + + /** + * @test + */ + public function shouldAddRepository() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('put') + ->with('/orgs/KnpLabs/actions/variables/variableName/repositories/1') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->addRepository('KnpLabs', 1, 'variableName')); + } + + /** + * @test + */ + public function shouldRemoveRepository() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('delete') + ->with('/orgs/KnpLabs/actions/variables/variableName/repositories/1') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->removeRepository('KnpLabs', 1, 'variableName')); + } + + protected function getApiClass() + { + return Variables::class; + } +} diff --git a/test/Github/Tests/Api/Organization/OrganizationRolesTest.php b/test/Github/Tests/Api/Organization/OrganizationRolesTest.php new file mode 100644 index 00000000000..f2d801afceb --- /dev/null +++ b/test/Github/Tests/Api/Organization/OrganizationRolesTest.php @@ -0,0 +1,187 @@ + 1, + 'roles' => [[ + 'id' => 1, + 'name' => 'all_repo_admin', + 'description' => 'Grants admin access to all repositories in the organization.', + 'permissions' => [], + 'organization' => null, + 'created_at' => '2023-01-01T00:00:00Z', + 'updated_at' => '2023-01-01T00:00:00Z', + 'source' => 'Predefined', + 'base_role' => 'admin', + ]], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/orgs/acme/organization-roles') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->all('acme')); + } + + /** + * @test + */ + public function shouldShowSingleOrganizationRole() + { + $expectedValue = [ + 'id' => 1, + 'name' => 'all_repo_admin', + 'description' => 'Grants admin access to all repositories in the organization.', + 'permissions' => [], + 'organization' => null, + 'created_at' => '2023-01-01T00:00:00Z', + 'updated_at' => '2023-01-01T00:00:00Z', + 'source' => 'Predefined', + 'base_role' => 'admin', + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/orgs/acme/organization-roles/1') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->show('acme', 1)); + } + + /** + * @test + */ + public function shouldGetAllTeamsWithRole() + { + $expectedValue = [['name' => 'Acme Admins']]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/orgs/acme/organization-roles/1/teams') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->listTeamsWithRole('acme', 1)); + } + + /** + * @test + */ + public function shouldAssignRoleToTeam() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('/orgs/acme/organization-roles/teams/acme-admins/1') + ->will($this->returnValue('')); + + $api->assignRoleToTeam('acme', 1, 'acme-admins'); + } + + /** + * @test + */ + public function shouldRemoveRoleFromTeam() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('/orgs/acme/organization-roles/teams/acme-admins/1') + ->will($this->returnValue('')); + + $api->removeRoleFromTeam('acme', 1, 'acme-admins'); + } + + /** + * @test + */ + public function shouldRemoveAllRolesFromTeam() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('/orgs/acme/organization-roles/teams/acme-admins') + ->will($this->returnValue('')); + + $api->removeAllRolesFromTeam('acme', 'acme-admins'); + } + + /** + * @test + */ + public function shouldGetAllUsersWithRole() + { + $expectedValue = [['username' => 'Admin']]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/orgs/acme/organization-roles/1/users') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->listUsersWithRole('acme', 1)); + } + + /** + * @test + */ + public function shouldAssignRoleToUser() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('put') + ->with('/orgs/acme/organization-roles/users/admin/1') + ->will($this->returnValue('')); + + $api->assignRoleToUser('acme', 1, 'admin'); + } + + /** + * @test + */ + public function shouldRemoveRoleFromUser() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('/orgs/acme/organization-roles/users/admin/1') + ->will($this->returnValue('')); + + $api->removeRoleFromUser('acme', 1, 'admin'); + } + + /** + * @test + */ + public function shouldRemoveAllRolesFromUser() + { + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('/orgs/acme/organization-roles/users/admin') + ->will($this->returnValue('')); + + $api->removeAllRolesFromUser('acme', 'admin'); + } + + protected function getApiClass(): string + { + return OrganizationRoles::class; + } +} diff --git a/test/Github/Tests/Api/Organization/SecretScanningTest.php b/test/Github/Tests/Api/Organization/SecretScanningTest.php new file mode 100644 index 00000000000..01b8f844007 --- /dev/null +++ b/test/Github/Tests/Api/Organization/SecretScanningTest.php @@ -0,0 +1,41 @@ + 1, 'state' => 'resolved', 'resolution' => 'false_positive'], + ['number' => 2, 'state' => 'open', 'resolution' => null], + ['number' => 3, 'state' => 'resolved', 'resolution' => 'wont_fix'], + ['number' => 4, 'state' => 'resolved', 'resolution' => 'revoked'], + ]; + + /** @var SecretScanning|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/secret-scanning/alerts') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->alerts('KnpLabs', [ + 'state' => 'all', + ])); + } + + protected function getApiClass() + { + return \Github\Api\Organization\SecretScanning::class; + } +} diff --git a/test/Github/Tests/Api/Organization/TeamsTest.php b/test/Github/Tests/Api/Organization/TeamsTest.php index 3538113ad61..18b476986aa 100644 --- a/test/Github/Tests/Api/Organization/TeamsTest.php +++ b/test/Github/Tests/Api/Organization/TeamsTest.php @@ -126,6 +126,22 @@ public function shouldGetTeamRepositories() { $expectedValue = [['name' => 'l3l0repo']]; + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/orgs/KnpLabs/teams/KnpWorld/repos') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->repositories('KnpWorld', 'KnpLabs')); + } + + /** + * @test + */ + public function shouldGetTeamRepositoriesViaLegacy() + { + $expectedValue = [['name' => 'l3l0repo']]; + $api = $this->getApiMock(); $api->expects($this->once()) ->method('get') @@ -161,7 +177,7 @@ public function shouldAddTeamRepository() $api = $this->getApiMock(); $api->expects($this->once()) ->method('put') - ->with('/teams/KnpWorld/repos/l3l0/l3l0Repo') + ->with('/orgs/l3l0/teams/KnpWorld/repos/l3l0/l3l0Repo') ->will($this->returnValue($expectedValue)); $this->assertEquals($expectedValue, $api->addRepository('KnpWorld', 'l3l0', 'l3l0Repo')); @@ -177,7 +193,7 @@ public function shouldRemoveTeamRepository() $api = $this->getApiMock(); $api->expects($this->once()) ->method('delete') - ->with('/teams/KnpWorld/repos/l3l0/l3l0Repo') + ->with('/orgs/l3l0/teams/KnpWorld/repos/l3l0/l3l0Repo') ->will($this->returnValue($expectedValue)); $this->assertEquals($expectedValue, $api->removeRepository('KnpWorld', 'l3l0', 'l3l0Repo')); diff --git a/test/Github/Tests/Api/OrganizationTest.php b/test/Github/Tests/Api/OrganizationTest.php index 04f389c0337..2b920662691 100644 --- a/test/Github/Tests/Api/OrganizationTest.php +++ b/test/Github/Tests/Api/OrganizationTest.php @@ -88,6 +88,26 @@ public function shouldGetTeamsApiObject() $this->assertInstanceOf(\Github\Api\Organization\Teams::class, $api->teams()); } + /** + * @test + */ + public function shouldGetSelfHostedRunnersApiObject() + { + $api = $this->getApiMock(); + + $this->assertInstanceOf(\Github\Api\Organization\Actions\SelfHostedRunners::class, $api->runners()); + } + + /** + * @test + */ + public function shouldGetVariablesApiObject() + { + $api = $this->getApiMock(); + + $this->assertInstanceOf(\Github\Api\Organization\Actions\Variables::class, $api->variables()); + } + /** * @return string */ diff --git a/test/Github/Tests/Api/PullRequestTest.php b/test/Github/Tests/Api/PullRequestTest.php index 90505535ff9..54cc34f55e0 100644 --- a/test/Github/Tests/Api/PullRequestTest.php +++ b/test/Github/Tests/Api/PullRequestTest.php @@ -144,15 +144,15 @@ public function shouldShowStatusesFromPullRequest() $expectedArray['_links']['statuses']['href'] = '/repos/ezsystems/ezpublish/pulls/15/statuses'; $api = $this->getApiMock(); - $api->expects($this->at(0)) - ->method('get') - ->with('/repos/ezsystems/ezpublish/pulls/15') - ->will($this->returnValue($expectedArray)); - $api->expects($this->at(1)) + $api->expects($this->exactly(2)) ->method('get') - ->with('/repos/ezsystems/ezpublish/pulls/15/statuses') - ->will($this->returnValue($expectedArray)); + ->withConsecutive( + [$this->equalTo('/repos/ezsystems/ezpublish/pulls/15')], + [$this->equalTo('/repos/ezsystems/ezpublish/pulls/15/statuses')] + ) + ->willReturn($expectedArray) + ; $this->assertEquals($expectedArray, $api->status('ezsystems', 'ezpublish', '15')); } @@ -243,10 +243,10 @@ public function shouldMergePullRequestWithMergeMethod() public function shouldCreatePullRequestUsingTitle() { $data = [ - 'base' => 'master', - 'head' => 'virtualtestbranch', + 'base' => 'master', + 'head' => 'virtualtestbranch', 'title' => 'TITLE: Testing pull-request creation from PHP Github API', - 'body' => 'BODY: Testing pull-request creation from PHP Github API', + 'body' => 'BODY: Testing pull-request creation from PHP Github API', ]; $api = $this->getApiMock(); @@ -263,8 +263,8 @@ public function shouldCreatePullRequestUsingTitle() public function shouldCreatePullRequestUsingIssueId() { $data = [ - 'base' => 'master', - 'head' => 'virtualtestbranch', + 'base' => 'master', + 'head' => 'virtualtestbranch', 'issue' => 25, ]; @@ -282,10 +282,10 @@ public function shouldCreatePullRequestUsingIssueId() public function shouldCreateDraftPullRequest() { $data = [ - 'base' => 'master', - 'head' => 'virtualtestbranch', + 'base' => 'master', + 'head' => 'virtualtestbranch', 'title' => 'TITLE: Testing draft pull-request creation from PHP Github API', - 'body' => 'BODY: Testing draft pull-request creation from PHP Github API', + 'body' => 'BODY: Testing draft pull-request creation from PHP Github API', 'draft' => 'true', ]; @@ -304,9 +304,9 @@ public function shouldNotCreatePullRequestWithoutBase() { $this->expectException(MissingArgumentException::class); $data = [ - 'head' => 'virtualtestbranch', + 'head' => 'virtualtestbranch', 'title' => 'TITLE: Testing pull-request creation from PHP Github API', - 'body' => 'BODY: Testing pull-request creation from PHP Github API', + 'body' => 'BODY: Testing pull-request creation from PHP Github API', ]; $api = $this->getApiMock(); @@ -323,9 +323,9 @@ public function shouldNotCreatePullRequestWithoutHead() { $this->expectException(MissingArgumentException::class); $data = [ - 'base' => 'master', + 'base' => 'master', 'title' => 'TITLE: Testing pull-request creation from PHP Github API', - 'body' => 'BODY: Testing pull-request creation from PHP Github API', + 'body' => 'BODY: Testing pull-request creation from PHP Github API', ]; $api = $this->getApiMock(); @@ -342,8 +342,8 @@ public function shouldNotCreatePullRequestUsingTitleButWithoutBody() { $this->expectException(MissingArgumentException::class); $data = [ - 'base' => 'master', - 'head' => 'virtualtestbranch', + 'base' => 'master', + 'head' => 'virtualtestbranch', 'title' => 'TITLE: Testing pull-request creation from PHP Github API', ]; diff --git a/test/Github/Tests/Api/RepoTest.php b/test/Github/Tests/Api/RepoTest.php index 083d7201aa8..786c27d97b5 100644 --- a/test/Github/Tests/Api/RepoTest.php +++ b/test/Github/Tests/Api/RepoTest.php @@ -92,14 +92,14 @@ public function shouldCreateRepositoryUsingNameOnly() $api->expects($this->once()) ->method('post') ->with('/user/repos', [ - 'name' => 'l3l0Repo', - 'description' => '', - 'homepage' => '', - 'private' => false, - 'has_issues' => false, - 'has_wiki' => false, + 'name' => 'l3l0Repo', + 'description' => '', + 'homepage' => '', + 'private' => false, + 'has_issues' => false, + 'has_wiki' => false, 'has_downloads' => false, - 'auto_init' => false, + 'auto_init' => false, 'has_projects' => true, ]) ->will($this->returnValue($expectedArray)); @@ -118,14 +118,14 @@ public function shouldCreateRepositoryForOrganization() $api->expects($this->once()) ->method('post') ->with('/orgs/KnpLabs/repos', [ - 'name' => 'KnpLabsRepo', - 'description' => '', - 'homepage' => '', - 'private' => false, - 'has_issues' => false, - 'has_wiki' => false, + 'name' => 'KnpLabsRepo', + 'description' => '', + 'homepage' => '', + 'private' => false, + 'has_issues' => false, + 'has_wiki' => false, 'has_downloads' => false, - 'auto_init' => false, + 'auto_init' => false, 'has_projects' => true, ]) ->will($this->returnValue($expectedArray)); @@ -133,6 +133,49 @@ public function shouldCreateRepositoryForOrganization() $this->assertEquals($expectedArray, $api->create('KnpLabsRepo', '', '', true, 'KnpLabs')); } + /** + * @test + */ + public function shouldCreateRepositoryWithInternalVisibility() + { + $expectedArray = ['id' => 1, 'name' => 'KnpLabsRepo']; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('/user/repos', [ + 'name' => 'KnpLabsRepo', + 'description' => '', + 'homepage' => '', + 'has_issues' => false, + 'has_wiki' => false, + 'has_downloads' => false, + 'auto_init' => false, + 'has_projects' => true, + 'visibility' => 'internal', + 'private' => false, + ]) + ->will($this->returnValue($expectedArray)); + + $this->assertEquals( + $expectedArray, + $api->create( + 'KnpLabsRepo', + '', + '', + false, + null, + false, + false, + false, + null, + false, + true, + 'internal' + ) + ); + } + /** * @test */ @@ -197,6 +240,26 @@ public function shouldGetRepositoryBranch() $this->assertEquals($expectedArray, $api->branches('KnpLabs', 'php-github-api', 'master')); } + /** + * @test + */ + public function shouldMergeUpstreamRepository() + { + $expectedArray = [ + 'message' => 'Successfully fetched and fast-forwarded from upstream upstreamRepo:main', + 'merge_type' => 'fast-forward', + 'merge_branch' => 'upstreamRepo:main', + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('/repos/KnpLabs/php-github-api/merge-upstream', ['branch' => 'main']) + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->mergeUpstream('KnpLabs', 'php-github-api', 'main')); + } + /** * @test */ @@ -326,14 +389,14 @@ public function shouldCreateUsingAllParams() $api->expects($this->once()) ->method('post') ->with('/user/repos', [ - 'name' => 'l3l0Repo', - 'description' => 'test', - 'homepage' => 'http://l3l0.eu', - 'private' => true, - 'has_issues' => false, - 'has_wiki' => false, + 'name' => 'l3l0Repo', + 'description' => 'test', + 'homepage' => 'http://l3l0.eu', + 'private' => true, + 'has_issues' => false, + 'has_wiki' => false, 'has_downloads' => false, - 'auto_init' => false, + 'auto_init' => false, 'has_projects' => true, ]) ->will($this->returnValue($expectedArray)); @@ -507,6 +570,16 @@ public function shouldGetReleasesApiObject() $this->assertInstanceOf(\Github\Api\Repository\Releases::class, $api->releases()); } + /** + * @test + */ + public function shouldGetVariablesApiObject() + { + $api = $this->getApiMock(); + + $this->assertInstanceOf(\Github\Api\Repository\Actions\Variables::class, $api->variables()); + } + /** * @test */ @@ -626,6 +699,32 @@ public function shouldTransferRepository() $this->assertEquals($expectedArray, $api->transfer('KnpLabs', 'php-github-api', 'github', [1234, 1235])); } + /** + * @test + */ + public function shouldCreateRepositoryUsingTemplate() + { + $expectedArray = [ + 'id' => 1, + 'name' => 'newrepo', + 'full_name' => 'johndoe/newrepo', + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('/repos/acme/template/generate', [ + 'name' => 'newrepo', + 'owner' => 'johndoe', + ]) + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->createFromTemplate('acme', 'template', [ + 'name' => 'newrepo', + 'owner' => 'johndoe', + ])); + } + /** * @return string */ @@ -633,4 +732,58 @@ protected function getApiClass() { return \Github\Api\Repo::class; } + + /** + * @test + */ + public function shouldCheckVulnerabilityAlertsEnabled() + { + $expectedResponse = ''; + + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/vulnerability-alerts') + ->will($this->returnValue($expectedResponse)); + + $this->assertEquals($expectedResponse, $api->isVulnerabilityAlertsEnabled('KnpLabs', 'php-github-api')); + } + + /** + * @test + */ + public function shouldEnableVulnerabilityAlerts() + { + $expectedResponse = ''; + + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('put') + ->with('/repos/KnpLabs/php-github-api/vulnerability-alerts') + ->will($this->returnValue($expectedResponse)); + + $this->assertEquals($expectedResponse, $api->enableVulnerabilityAlerts('KnpLabs', 'php-github-api')); + } + + /** + * @test + */ + public function shouldDisableVulnerabilityAlerts() + { + $expectedResponse = ''; + + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('delete') + ->with('/repos/KnpLabs/php-github-api/vulnerability-alerts') + ->will($this->returnValue($expectedResponse)); + + $this->assertEquals($expectedResponse, $api->disableVulnerabilityAlerts('KnpLabs', 'php-github-api')); + } } diff --git a/test/Github/Tests/Api/Repository/Actions/SecretsTest.php b/test/Github/Tests/Api/Repository/Actions/SecretsTest.php index 670e623b688..5a5e20a4616 100644 --- a/test/Github/Tests/Api/Repository/Actions/SecretsTest.php +++ b/test/Github/Tests/Api/Repository/Actions/SecretsTest.php @@ -123,7 +123,7 @@ public function shouldGetPublicKey() $api ->expects($this->once()) ->method('get') - ->with('/repos/KnpLabs/php-github-api/actions/secrets/secret-key') + ->with('/repos/KnpLabs/php-github-api/actions/secrets/public-key') ->will($this->returnValue($expectedArray)); $this->assertEquals($expectedArray, $api->publicKey('KnpLabs', 'php-github-api')); diff --git a/test/Github/Tests/Api/Repository/Actions/VariablesTest.php b/test/Github/Tests/Api/Repository/Actions/VariablesTest.php new file mode 100644 index 00000000000..e362d31f7bc --- /dev/null +++ b/test/Github/Tests/Api/Repository/Actions/VariablesTest.php @@ -0,0 +1,119 @@ + 'GH_TOKEN', 'value' => 'value', 'created_at' => 'created_at', 'updated_at' => 'updated_at'], + ['name' => 'GIST_ID', 'value' => 'value', 'created_at' => 'created_at', 'updated_at' => 'updated_at'], + ]; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/actions/variables') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->all('KnpLabs', 'php-github-api')); + } + + /** + * @test + */ + public function shouldGetVariable() + { + $expectedArray = ['name' => 'name', 'value' => 'value', 'created_at' => 'created_at', 'updated_at' => 'updated_at']; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/actions/variables/variableName') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->show('KnpLabs', 'php-github-api', 'variableName')); + } + + /** + * @test + */ + public function shouldCreateVariable() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('post') + ->with('/repos/KnpLabs/php-github-api/actions/variables') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->create('KnpLabs', 'php-github-api', [ + 'name' => 'name', + 'value' => 'value', + ])); + } + + /** + * @test + */ + public function shouldUpdateVariable() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('patch') + ->with('/repos/KnpLabs/php-github-api/actions/variables/variableName') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->update('KnpLabs', 'php-github-api', 'variableName', [ + 'name' => 'name', + 'value' => 'value', + ])); + } + + /** + * @test + */ + public function shouldRemoveVariable() + { + $expectedValue = 'response'; + + /** @var Variables|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('delete') + ->with('/repos/KnpLabs/php-github-api/actions/variables/variableName') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->remove('KnpLabs', 'php-github-api', 'variableName')); + } + + protected function getApiClass() + { + return Variables::class; + } +} diff --git a/test/Github/Tests/Api/Repository/Actions/WorkflowRunsTest.php b/test/Github/Tests/Api/Repository/Actions/WorkflowRunsTest.php index 27155148ce0..1c5af0badc9 100644 --- a/test/Github/Tests/Api/Repository/Actions/WorkflowRunsTest.php +++ b/test/Github/Tests/Api/Repository/Actions/WorkflowRunsTest.php @@ -198,6 +198,24 @@ public function shouldDeleteWorkflowRunLogs() $this->assertEquals($expectedValue, $api->deleteLogs('KnpLabs', 'php-github-api', 374473304)); } + /** + * @test + */ + public function shouldApproveWorkflowRunLogs() + { + $expectedValue = 'response'; + + /** @var WorkflowRuns|MockObject $api */ + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('post') + ->with('/repos/KnpLabs/php-github-api/actions/runs/374473304/approve') + ->will($this->returnValue($expectedValue)); + + $this->assertSame($expectedValue, $api->approve('KnpLabs', 'php-github-api', 374473304)); + } + protected function getApiClass() { return WorkflowRuns::class; diff --git a/test/Github/Tests/Api/Repository/Actions/WorkflowsTest.php b/test/Github/Tests/Api/Repository/Actions/WorkflowsTest.php index a018f396531..7413fc5d7c0 100644 --- a/test/Github/Tests/Api/Repository/Actions/WorkflowsTest.php +++ b/test/Github/Tests/Api/Repository/Actions/WorkflowsTest.php @@ -89,6 +89,26 @@ public function shouldGetWorkflowUsage() $this->assertEquals($expectedArray, $api->usage('KnpLabs', 'php-github-api', 1)); } + /** + * @test + */ + public function shouldDispatchWorkflow() + { + // empty + $expectedArray = []; + + /** @var Workflows|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('post') + ->with('/repos/KnpLabs/php-github-api/actions/workflows/1/dispatches') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->dispatches('KnpLabs', 'php-github-api', 1, 'main')); + } + protected function getApiClass() { return Workflows::class; diff --git a/test/Github/Tests/Api/Repository/AssetsTest.php b/test/Github/Tests/Api/Repository/AssetsTest.php index 029c10a380f..6cea75fe975 100644 --- a/test/Github/Tests/Api/Repository/AssetsTest.php +++ b/test/Github/Tests/Api/Repository/AssetsTest.php @@ -43,6 +43,7 @@ public function shouldGetSingleReleaseAsset() /** * @test + * * @requires PHP 5.3.4 */ public function shouldCreateReleaseAsset() diff --git a/test/Github/Tests/Api/Repository/Checks/CheckRunsTest.php b/test/Github/Tests/Api/Repository/Checks/CheckRunsTest.php index 4b7ff086ec5..66bb5277c4b 100644 --- a/test/Github/Tests/Api/Repository/Checks/CheckRunsTest.php +++ b/test/Github/Tests/Api/Repository/Checks/CheckRunsTest.php @@ -102,6 +102,20 @@ public function shouldGetAllChecksForReference() $api->allForReference('KnpLabs', 'php-github-api', 'cb4abc15424c0015b4468d73df55efb8b60a4a3d', $params); } + /** + * @test + */ + public function shouldRerequestCheckRun() + { + /** @var CheckRuns|MockObject $api */ + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('/repos/KnpLabs/php-github-api/check-runs/123/rerequest'); + + $api->rerequest('KnpLabs', 'php-github-api', 123); + } + protected function getApiClass(): string { return CheckRuns::class; diff --git a/test/Github/Tests/Api/Repository/CommitsTest.php b/test/Github/Tests/Api/Repository/CommitsTest.php index 25ef2536a1c..9d1b3288afe 100644 --- a/test/Github/Tests/Api/Repository/CommitsTest.php +++ b/test/Github/Tests/Api/Repository/CommitsTest.php @@ -55,6 +55,25 @@ public function shouldShowCommitUsingSha() $this->assertEquals($expectedValue, $api->show('KnpLabs', 'php-github-api', 123)); } + /** + * @test + */ + public function shouldGetAllPullRequestsUsingSha() + { + $expectedValue = [ + ['number' => '1', 'title' => 'My first PR'], + ['number' => '2', 'title' => 'Another PR'], + ]; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/commits/123/pulls') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->pulls('KnpLabs', 'php-github-api', 123)); + } + /** * @return string */ diff --git a/test/Github/Tests/Api/Repository/ContentsTest.php b/test/Github/Tests/Api/Repository/ContentsTest.php index 122fbf5cdf9..81a79db64fa 100644 --- a/test/Github/Tests/Api/Repository/ContentsTest.php +++ b/test/Github/Tests/Api/Repository/ContentsTest.php @@ -71,6 +71,7 @@ public function getFailureStubsForExistsTest() * @param \PHPUnit_Framework_MockObject_Stub|\PHPUnit\Framework\MockObject\Stub\Exception * * @test + * * @dataProvider getFailureStubsForExistsTest */ public function shouldReturnFalseWhenFileIsNotFound($failureStub) @@ -110,10 +111,10 @@ public function shouldCreateNewFile() $branch = 'master'; $committer = ['name' => 'committer name', 'email' => 'email@example.com']; $parameters = [ - 'content' => base64_encode($content), - 'message' => $message, + 'content' => base64_encode($content), + 'message' => $message, 'committer' => $committer, - 'branch' => $branch, + 'branch' => $branch, ]; $api = $this->getApiMock(); @@ -149,11 +150,11 @@ public function shouldUpdateFile() $branch = 'master'; $committer = ['name' => 'committer name', 'email' => 'email@example.com']; $parameters = [ - 'content' => base64_encode($content), - 'message' => $message, + 'content' => base64_encode($content), + 'message' => $message, 'committer' => $committer, - 'branch' => $branch, - 'sha' => $sha, + 'branch' => $branch, + 'sha' => $sha, ]; $api = $this->getApiMock(); @@ -188,10 +189,10 @@ public function shouldDeleteFile() $branch = 'master'; $committer = ['name' => 'committer name', 'email' => 'email@example.com']; $parameters = [ - 'message' => $message, + 'message' => $message, 'committer' => $committer, - 'branch' => $branch, - 'sha' => $sha, + 'branch' => $branch, + 'sha' => $sha, ]; $api = $this->getApiMock(); @@ -319,6 +320,23 @@ public function shouldDownloadForSpacedPath() $this->assertEquals($expectedValue, $api->download('mads379', 'scala.tmbundle', 'Syntaxes/Simple Build Tool.tmLanguage')); } + /** + * @test + */ + public function shouldRawDownloadForGivenPath() + { + // The show() method return + $getValue = include __DIR__.'/fixtures/ContentsDownloadFixture.php'; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/contents/test%2FGithub%2FTests%2FApi%2FRepository%2FContentsTest.php', ['ref' => null]) + ->will($this->returnValue($getValue)); + + $this->assertEquals($getValue, $api->rawDownload('KnpLabs', 'php-github-api', 'test/Github/Tests/Api/Repository/ContentsTest.php')); + } + /** * @return string */ diff --git a/test/Github/Tests/Api/Repository/PagesTest.php b/test/Github/Tests/Api/Repository/PagesTest.php index c6b34cbc8b3..2fde0df1622 100644 --- a/test/Github/Tests/Api/Repository/PagesTest.php +++ b/test/Github/Tests/Api/Repository/PagesTest.php @@ -37,7 +37,7 @@ public function shouldEnablePages() $params = [ 'source' => [ 'branch' => 'master', - 'path' => '/path', + 'path' => '/path', ], ]; diff --git a/test/Github/Tests/Api/Repository/ReleasesTest.php b/test/Github/Tests/Api/Repository/ReleasesTest.php index 8668195c1e6..dda8999a163 100644 --- a/test/Github/Tests/Api/Repository/ReleasesTest.php +++ b/test/Github/Tests/Api/Repository/ReleasesTest.php @@ -76,6 +76,26 @@ public function shouldGetSingleRepositoryRelease() $this->assertEquals($expectedValue, $api->show('KnpLabs', 'php-github-api', $id)); } + /** + * @test + */ + public function shouldGenerateReleaseNotes() + { + $expectedValue = [ + 'name' => 'Release v1.0.0 is now available!', + 'body' => '##Changes in Release v1.0.0 ... ##Contributors @monalisa', + ]; + $data = ['tag_name' => 'some-tag']; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('/repos/KnpLabs/php-github-api/releases/generate-notes') + ->will($this->returnValue($expectedValue)); + + $this->assertEquals($expectedValue, $api->generateNotes('KnpLabs', 'php-github-api', $data)); + } + /** * @test */ diff --git a/test/Github/Tests/Api/Repository/SecretScanningTest.php b/test/Github/Tests/Api/Repository/SecretScanningTest.php new file mode 100644 index 00000000000..e2e98dfa879 --- /dev/null +++ b/test/Github/Tests/Api/Repository/SecretScanningTest.php @@ -0,0 +1,132 @@ + 1, 'state' => 'resolved', 'resolution' => 'false_positive'], + ['number' => 2, 'state' => 'open', 'resolution' => null], + ['number' => 3, 'state' => 'resolved', 'resolution' => 'wont_fix'], + ['number' => 4, 'state' => 'resolved', 'resolution' => 'revoked'], + ]; + + /** @var SecretScanning|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/secret-scanning/alerts') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->alerts('KnpLabs', 'php-github-api', [ + 'state' => 'all', + ])); + } + + /** + * @test + */ + public function shouldGetAlert() + { + $expectedArray = ['number' => 1, 'state' => 'resolved', 'resolution' => 'false_positive']; + + /** @var SecretScanning|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/secret-scanning/alerts/1') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->getAlert('KnpLabs', 'php-github-api', 1)); + } + + /** + * @test + */ + public function shouldUpdateAlert() + { + $expectedArray = ['number' => 1, 'state' => 'resolved', 'resolution' => 'false_positive']; + + /** @var SecretScanning|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('patch') + ->with('/repos/KnpLabs/php-github-api/secret-scanning/alerts/2') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->updateAlert('KnpLabs', 'php-github-api', 2, [ + 'state' => 'resolved', + 'resolution' => 'false_positive', + ])); + } + + /** + * @test + */ + public function shouldGetLocations() + { + $expectedArray = [ + [ + 'type' => 'commit', + 'details' => [ + 'path' => '/example/secrets.txt', + 'start_line' => 1, + 'end_line' => 1, + 'start_column' => 1, + 'end_column' => 64, + 'blob_sha' => 'af5626b4a114abcb82d63db7c8082c3c4756e51b', + 'blob_url' => 'https://HOSTNAME/repos/octocat/hello-world/git/blobs/af5626b4a114abcb82d63db7c8082c3c4756e51b', + 'commit_sha' => 'f14d7debf9775f957cf4f1e8176da0786431f72b', + 'commit_url' => 'https://HOSTNAME/repos/octocat/hello-world/git/commits/f14d7debf9775f957cf4f1e8176da0786431f72b', + ], + ], + [ + 'type' => 'commit', + 'details' => [ + 'path' => '/example/secrets.txt', + 'start_line' => 5, + 'end_line' => 5, + 'start_column' => 1, + 'end_column' => 64, + 'blob_sha' => '9def38117ab2d8355b982429aa924e268b4b0065', + 'blob_url' => 'https://HOSTNAME/repos/octocat/hello-world/git/blobs/9def38117ab2d8355b982429aa924e268b4b0065', + 'commit_sha' => '588483b99a46342501d99e3f10630cfc1219ea32', + 'commit_url' => 'https://HOSTNAME/repos/octocat/hello-world/git/commits/588483b99a46342501d99e3f10630cfc1219ea32', + ], + ], + ]; + + /** @var SecretScanning|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/repos/KnpLabs/php-github-api/secret-scanning/alerts/2/locations') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->locations('KnpLabs', 'php-github-api', 2, [ + 'per_page' => 10, + ])); + } + + protected function getApiClass() + { + return \Github\Api\Repository\SecretScanning::class; + } +} diff --git a/test/Github/Tests/Api/SearchTest.php b/test/Github/Tests/Api/SearchTest.php index a44c7b7499e..feecb7b5a74 100644 --- a/test/Github/Tests/Api/SearchTest.php +++ b/test/Github/Tests/Api/SearchTest.php @@ -133,6 +133,49 @@ public function shouldSearchCodeRegardingSortAndOrder() ); } + /** + * @test + */ + public function shouldSearchCodeWithMatchByQuery() + { + $expectedArray = [['total_count' => '0']]; + + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with( + '/search/code', + ['q' => 'query text', 'sort' => 'updated', 'order' => 'desc'] + ) + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->codeWithMatch('query text')); + } + + /** + * @test + */ + public function shouldSearchCodeWithMatchRegardingSortAndOrder() + { + $expectedArray = [['total_count' => '0']]; + + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with( + '/search/code', + ['q' => 'query text', 'sort' => 'created', 'order' => 'asc'] + ) + ->will($this->returnValue($expectedArray)); + + $this->assertEquals( + $expectedArray, + $api->codeWithMatch('query text', 'created', 'asc') + ); + } + /** * @test */ diff --git a/test/Github/Tests/Api/User/MigrationTest.php b/test/Github/Tests/Api/User/MigrationTest.php new file mode 100644 index 00000000000..3ee1620a3ae --- /dev/null +++ b/test/Github/Tests/Api/User/MigrationTest.php @@ -0,0 +1,186 @@ + 79, + 'state' => 'pending', + 'lock_repositories' => true, + 'repositories' => [ + [ + 'id' => 1296269, + 'name' => 'Hello-World', + 'full_name' => 'octocat/Hello-World', + ], + ], + ], + [ + 'id' => 2, + 'name' => 'pending', + 'lock_repositories' => false, + 'repositories' => [ + [ + 'id' => 123, + 'name' => 'php-github-api', + 'full_name' => 'KnpLabs/php-github-api', + ], + ], + ], + ]; + + /** @var Migration|MockObject $api */ + $api = $this->getApiMock(); + + $api + ->expects($this->once()) + ->method('get') + ->with('/user/migrations') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->list()); + } + + /** + * @test + */ + public function shouldStartMigration() + { + $expectedArray = [ + 'id' => 79, + 'state' => 'pending', + 'lock_repositories' => true, + 'repositories' => [ + [ + 'id' => 1296269, + 'name' => 'Hello-World', + 'full_name' => 'octocat/Hello-World', + ], + ], + ]; + + /** @var Migration|MockObject $api */ + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('post') + ->with('/user/migrations') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->start([ + 'lock_repositories' => true, + 'repositories' => [ + 'KnpLabs/php-github-api', + ], + ])); + } + + /** + * @test + */ + public function shouldGetMigrationStatus() + { + $expectedArray = [ + 'id' => 79, + 'state' => 'exported', + 'lock_repositories' => true, + 'repositories' => [ + [ + 'id' => 1296269, + 'name' => 'Hello-World', + 'full_name' => 'octocat/Hello-World', + ], + ], + ]; + + /** @var Migration|MockObject $api */ + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with('/user/migrations/79') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->status(79)); + } + + /** + * @test + */ + public function shouldDeleteMigrationArchive() + { + /** @var Migration|MockObject $api */ + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('delete') + ->with('/user/migrations/79/archive') + ->will($this->returnValue(204)); + + $this->assertEquals(204, $api->deleteArchive(79)); + } + + /** + * @test + */ + public function shouldUnlockUserRepo() + { + /** @var Migration|MockObject $api */ + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('delete') + ->with('/user/migrations/79/repos/php-github-api/lock') + ->will($this->returnValue(204)); + + $this->assertEquals(204, $api->unlockRepo(79, 'php-github-api')); + } + + /** + * @test + */ + public function shouldListRepos() + { + $expectedArray = [ + [ + 'id' => 1296269, + 'name' => 'Hello-World', + 'full_name' => 'test/Hello-World', + ], + [ + 'id' => 234324, + 'name' => 'Hello-World2', + 'full_name' => 'test/Hello-World2', + ], + ]; + + /** @var Migration|MockObject $api */ + $api = $this->getApiMock(); + + $api->expects($this->once()) + ->method('get') + ->with('/user/migrations/79/repositories') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->repos(79)); + } + + /** + * @return string + */ + protected function getApiClass() + { + return \Github\Api\User\Migration::class; + } +} diff --git a/test/Github/Tests/Api/UserTest.php b/test/Github/Tests/Api/UserTest.php index 491a58f8602..0be80a28f01 100644 --- a/test/Github/Tests/Api/UserTest.php +++ b/test/Github/Tests/Api/UserTest.php @@ -228,6 +228,29 @@ public function shouldGetUserGists() $this->assertEquals($expectedArray, $api->gists('l3l0')); } + /** + * @test + */ + public function shouldGetAuthorizedUserEvents() + { + $expectedArray = [ + [ + 'id' => 1, + 'actor' => [ + 'id' => 1, + 'login' => 'l3l0', + ], + ], + ]; + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('get') + ->with('/users/l3l0/events') + ->will($this->returnValue($expectedArray)); + + $this->assertEquals($expectedArray, $api->events('l3l0')); + } + /** * @return string */ diff --git a/test/Github/Tests/ClientTest.php b/test/Github/Tests/ClientTest.php index d1eb5737acf..e5992284404 100644 --- a/test/Github/Tests/ClientTest.php +++ b/test/Github/Tests/ClientTest.php @@ -3,6 +3,7 @@ namespace Github\Tests; use Github\Api; +use Github\AuthMethod; use Github\Client; use Github\Exception\BadMethodCallException; use Github\Exception\InvalidArgumentException; @@ -39,6 +40,7 @@ public function shouldPassHttpClientInterfaceToConstructor() /** * @test + * * @dataProvider getAuthenticationFullData */ public function shouldAuthenticateUsingAllGivenParameters($login, $password, $method) @@ -68,9 +70,9 @@ public function shouldAuthenticateUsingAllGivenParameters($login, $password, $me public function getAuthenticationFullData() { return [ - ['token', null, Client::AUTH_ACCESS_TOKEN], - ['client_id', 'client_secret', Client::AUTH_CLIENT_ID], - ['token', null, Client::AUTH_JWT], + ['token', null, AuthMethod::ACCESS_TOKEN], + ['client_id', 'client_secret', AuthMethod::CLIENT_ID], + ['token', null, AuthMethod::JWT], ]; } @@ -84,7 +86,7 @@ public function shouldAuthenticateUsingGivenParameters() ->getMock(); $builder->expects($this->once()) ->method('addPlugin') - ->with($this->equalTo(new Authentication('token', null, Client::AUTH_ACCESS_TOKEN))); + ->with($this->equalTo(new Authentication('token', null, AuthMethod::ACCESS_TOKEN))); $builder->expects($this->once()) ->method('removePlugin') @@ -98,7 +100,7 @@ public function shouldAuthenticateUsingGivenParameters() ->method('getHttpClientBuilder') ->willReturn($builder); - $client->authenticate('token', Client::AUTH_ACCESS_TOKEN); + $client->authenticate('token', AuthMethod::ACCESS_TOKEN); } /** @@ -114,6 +116,7 @@ public function shouldThrowExceptionWhenAuthenticatingWithoutMethodSet() /** * @test + * * @dataProvider getApiClassesProvider */ public function shouldGetApiInstance($apiName, $class) @@ -125,6 +128,7 @@ public function shouldGetApiInstance($apiName, $class) /** * @test + * * @dataProvider getApiClassesProvider */ public function shouldGetMagicApiInstance($apiName, $class) @@ -222,4 +226,25 @@ public function testEnterpriseUrl() $client = new Client($httpClientBuilder, null, 'https://foobar.com'); $client->enterprise()->stats()->show('all'); } + + /** + * Make sure that the prepend is correct when using the v4 endpoint on Enterprise. + */ + public function testEnterprisePrependGraphQLV4() + { + $httpClientMock = $this->getMockBuilder(ClientInterface::class) + ->setMethods(['sendRequest']) + ->getMock(); + + $httpClientMock->expects($this->once()) + ->method('sendRequest') + ->with($this->callback(function (RequestInterface $request) { + return (string) $request->getUri() === 'https://foobar.com/api/graphql'; + })) + ->willReturn(new Response(200, [], '[]')); + + $httpClientBuilder = new Builder($httpClientMock); + $client = new Client($httpClientBuilder, 'v4', 'https://foobar.com'); + $client->graphql()->execute('query'); + } } diff --git a/test/Github/Tests/Functional/CacheTest.php b/test/Github/Tests/Functional/CacheTest.php index 58afe5f61f3..bd217dc5dc2 100644 --- a/test/Github/Tests/Functional/CacheTest.php +++ b/test/Github/Tests/Functional/CacheTest.php @@ -2,8 +2,10 @@ namespace Github\Tests\Functional; +use Github\AuthMethod; use Github\Client; use GuzzleHttp\Psr7\Response; +use GuzzleHttp\Psr7\Utils; use Symfony\Component\Cache\Adapter\ArrayAdapter; /** @@ -23,9 +25,9 @@ public function shouldServeCachedResponse() $mockClient->addResponse($this->getCurrentUserResponse('octocat')); $github = Client::createWithHttpClient($mockClient); - $github->addCache(new ArrayAdapter(), ['default_ttl'=>600]); + $github->addCache(new ArrayAdapter(), ['default_ttl' => 600]); - $github->authenticate('fake_token_aaa', Client::AUTH_ACCESS_TOKEN); + $github->authenticate('fake_token_aaa', AuthMethod::ACCESS_TOKEN); $userA = $github->currentUser()->show(); $this->assertEquals('nyholm', $userA['login']); @@ -43,13 +45,13 @@ public function shouldVaryOnAuthorization() $mockClient->addResponse($this->getCurrentUserResponse('octocat')); $github = Client::createWithHttpClient($mockClient); - $github->addCache(new ArrayAdapter(), ['default_ttl'=>600]); + $github->addCache(new ArrayAdapter(), ['default_ttl' => 600]); - $github->authenticate('fake_token_aaa', Client::AUTH_ACCESS_TOKEN); + $github->authenticate('fake_token_aaa', AuthMethod::ACCESS_TOKEN); $userA = $github->currentUser()->show(); $this->assertEquals('nyholm', $userA['login']); - $github->authenticate('fake_token_bbb', Client::AUTH_ACCESS_TOKEN); + $github->authenticate('fake_token_bbb', AuthMethod::ACCESS_TOKEN); $userB = $github->currentUser()->show(); $this->assertEquals('octocat', $userB['login'], 'We must vary on the Authorization header.'); } @@ -60,7 +62,7 @@ private function getCurrentUserResponse($username) 'Content-Type' => 'application/json', ]; - $body = \GuzzleHttp\Psr7\stream_for(json_encode([ + $body = Utils::streamFor(json_encode([ 'login' => $username, ])); diff --git a/test/Github/Tests/HttpClient/Message/ResponseMediatorTest.php b/test/Github/Tests/HttpClient/Message/ResponseMediatorTest.php index c14eac8a297..b6216d57044 100644 --- a/test/Github/Tests/HttpClient/Message/ResponseMediatorTest.php +++ b/test/Github/Tests/HttpClient/Message/ResponseMediatorTest.php @@ -4,6 +4,7 @@ use Github\HttpClient\Message\ResponseMediator; use GuzzleHttp\Psr7\Response; +use GuzzleHttp\Psr7\Utils; /** * @author Tobias Nyholm @@ -15,8 +16,8 @@ public function testGetContent() $body = ['foo' => 'bar']; $response = new Response( 200, - ['Content-Type'=>'application/json'], - \GuzzleHttp\Psr7\stream_for(json_encode($body)) + ['Content-Type' => 'application/json'], + Utils::streamFor(json_encode($body)) ); $this->assertEquals($body, ResponseMediator::getContent($response)); @@ -31,7 +32,7 @@ public function testGetContentNotJson() $response = new Response( 200, [], - \GuzzleHttp\Psr7\stream_for($body) + Utils::streamFor($body) ); $this->assertEquals($body, ResponseMediator::getContent($response)); @@ -45,8 +46,8 @@ public function testGetContentInvalidJson() $body = 'foobar'; $response = new Response( 200, - ['Content-Type'=>'application/json'], - \GuzzleHttp\Psr7\stream_for($body) + ['Content-Type' => 'application/json'], + Utils::streamFor($body) ); $this->assertEquals($body, ResponseMediator::getContent($response)); @@ -54,22 +55,17 @@ public function testGetContentInvalidJson() public function testGetPagination() { - $header = <<<'TEXT' -; rel="first", -; rel="next", -; rel="prev", -; rel="last", -TEXT; + $header = '; rel="first",; rel="next",; rel="prev",; rel="last",'; $pagination = [ - 'first' => 'http://github.com', - 'next' => 'http://github.com', - 'prev' => 'http://github.com', - 'last' => 'http://github.com', + 'first' => 'https://github.com', + 'next' => 'https://github.com', + 'prev' => 'https://github.com', + 'last' => 'https://github.com', ]; // response mock - $response = new Response(200, ['link'=>$header]); + $response = new Response(200, ['link' => $header]); $result = ResponseMediator::getPagination($response); $this->assertEquals($pagination, $result); @@ -80,7 +76,7 @@ public function testGetHeader() $header = 'application/json'; $response = new Response( 200, - ['Content-Type'=> $header] + ['Content-Type' => $header] ); $this->assertEquals($header, ResponseMediator::getHeader($response, 'content-type')); diff --git a/test/Github/Tests/HttpClient/Plugin/AuthenticationTest.php b/test/Github/Tests/HttpClient/Plugin/AuthenticationTest.php index e8c3d24a6a6..be937684d01 100644 --- a/test/Github/Tests/HttpClient/Plugin/AuthenticationTest.php +++ b/test/Github/Tests/HttpClient/Plugin/AuthenticationTest.php @@ -2,7 +2,7 @@ namespace Github\Tests\HttpClient\Plugin; -use Github\Client; +use Github\AuthMethod; use Github\HttpClient\Plugin\Authentication; use GuzzleHttp\Psr7\Request; use Http\Promise\FulfilledPromise; @@ -41,9 +41,9 @@ public function testAuthenticationMethods($tokenOrLogin, $password, $method, $ex public function getAuthenticationData() { return [ - ['access_token', null, Client::AUTH_ACCESS_TOKEN, 'token access_token'], - ['client_id', 'client_secret', Client::AUTH_CLIENT_ID, sprintf('Basic %s', base64_encode('client_id'.':'.'client_secret'))], - ['jwt_token', null, Client::AUTH_JWT, 'Bearer jwt_token'], + ['access_token', null, AuthMethod::ACCESS_TOKEN, 'token access_token'], + ['client_id', 'client_secret', AuthMethod::CLIENT_ID, sprintf('Basic %s', base64_encode('client_id'.':'.'client_secret'))], + ['jwt_token', null, AuthMethod::JWT, 'Bearer jwt_token'], ]; } } diff --git a/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php index 377d75ce732..7cb7dfe33a8 100644 --- a/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php +++ b/test/Github/Tests/HttpClient/Plugin/GithubExceptionThrowerTest.php @@ -4,6 +4,7 @@ use Github\Exception\ExceptionInterface; use Github\HttpClient\Plugin\GithubExceptionThrower; +use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Response; use Http\Client\Promise\HttpFulfilledPromise; use Http\Client\Promise\HttpRejectedPromise; @@ -17,14 +18,11 @@ class GithubExceptionThrowerTest extends TestCase { /** - * @param ResponseInterface $response - * @param ExceptionInterface|\Exception|null $exception * @dataProvider responseProvider */ - public function testHandleRequest(ResponseInterface $response, ExceptionInterface $exception = null) + public function testHandleRequest(ResponseInterface $response, ?ExceptionInterface $exception = null): void { - /** @var RequestInterface $request */ - $request = $this->getMockForAbstractClass(RequestInterface::class); + $request = new Request('GET', 'https://api.github.com/issues'); $promise = new HttpFulfilledPromise($response); @@ -49,7 +47,7 @@ function (RequestInterface $request) use ($promise) { if ($exception) { $this->expectException(get_class($exception)); $this->expectExceptionCode($exception->getCode()); - $this->expectExceptionMessage($exception->getMessage()); + $this->expectExceptionMessageMatches('/'.preg_quote($exception->getMessage(), '/').'$/'); } $result->wait(); @@ -77,6 +75,40 @@ public static function responseProvider() ), 'exception' => new \Github\Exception\ApiLimitExceedException(5000), ], + 'Rate Limit Exceeded via 403 status' => [ + 'response' => new Response( + 403, + [ + 'Content-Type' => 'application/json', + 'X-RateLimit-Remaining' => 0, + 'X-RateLimit-Limit' => 5000, + 'X-RateLimit-Reset' => 1609245810, + ], + json_encode( + [ + 'message' => 'API rate limit exceeded for installation ID xxxxxxx.', + ] + ) + ), + 'exception' => new \Github\Exception\ApiLimitExceedException(5000), + ], + 'Secondary Rate Limit Exceeded via 403 status' => [ + 'response' => new Response( + 403, + [ + 'Content-Type' => 'application/json', + 'X-RateLimit-Remaining' => 100, + 'X-RateLimit-Limit' => 5000, + 'X-RateLimit-Reset' => 1609245810, + ], + json_encode( + [ + 'message' => 'You have exceeded a secondary rate limit and have been temporarily blocked from content creation. Please retry your request again later. If you reach out to GitHub Support for help, please include the request ID #xxxxxxx.', + ] + ) + ), + 'exception' => new \Github\Exception\ApiLimitExceedException(5000), + ], 'Two Factor Authentication Required' => [ 'response' => new Response( 401, @@ -181,6 +213,41 @@ public static function responseProvider() ), 'exception' => new \Github\Exception\RuntimeException('Field "xxxx" doesn\'t exist on type "Issue", Field "dummy" doesn\'t exist on type "PullRequest"'), ], + 'Grapql requires authentication' => [ + 'response' => new Response( + 401, + [ + 'content-type' => 'application/json', + 'X-RateLimit-Limit' => 0, + 'X-RateLimit-Remaining' => 0, + 'X-RateLimit-Reset' => 1609245810, + 'X-RateLimit-Used' => 0, + ], + json_encode( + [ + 'message' => 'This endpoint requires you to be authenticated.', + 'documentation_url' => 'https://docs.github.com/v3/#authentication', + ] + ) + ), + 'exception' => new \Github\Exception\RuntimeException('This endpoint requires you to be authenticated.', 401), + ], + 'Cannot delete active deployment' => [ + 'response' => new Response( + 422, + [ + 'content-type' => 'application/json', + ], + json_encode( + [ + 'message' => 'Validation Failed', + 'errors' => ['We cannot delete an active deployment unless it is the only deployment in a given environment.'], + 'documentation_url' => 'https://docs.github.com/rest/reference/repos#delete-a-deployment', + ] + ) + ), + 'exception' => new \Github\Exception\ValidationFailedException('Validation Failed: We cannot delete an active deployment unless it is the only deployment in a given environment.', 422), + ], ]; } } diff --git a/test/Github/Tests/Integration/IssueCommentTest.php b/test/Github/Tests/Integration/IssueCommentTest.php index 3db9ce8bb46..0cb39a1f8e3 100644 --- a/test/Github/Tests/Integration/IssueCommentTest.php +++ b/test/Github/Tests/Integration/IssueCommentTest.php @@ -31,6 +31,7 @@ public function shouldRetrieveCommentsForIssue() /** * @test + * * @depends shouldRetrieveCommentsForIssue */ public function shouldRetrieveSingleComment($commentId) @@ -72,6 +73,7 @@ public function shouldCreateCommentForIssue() /** * @test + * * @depends shouldCreateCommentForIssue */ public function shouldUpdateCommentByCommentId($commentId) @@ -94,6 +96,7 @@ public function shouldUpdateCommentByCommentId($commentId) /** * @test + * * @depends shouldUpdateCommentByCommentId */ public function shouldRemoveCommentByCommentId($commentId) diff --git a/test/Github/Tests/Integration/RepoCommentTest.php b/test/Github/Tests/Integration/RepoCommentTest.php index b2d5dec528a..352dac4b7ff 100644 --- a/test/Github/Tests/Integration/RepoCommentTest.php +++ b/test/Github/Tests/Integration/RepoCommentTest.php @@ -70,6 +70,7 @@ public function shouldCreateCommentForCommit() /** * @test + * * @depends shouldCreateCommentForCommit */ public function shouldShowCommentByCommentId($commentId) @@ -91,6 +92,7 @@ public function shouldShowCommentByCommentId($commentId) /** * @test + * * @depends shouldShowCommentByCommentId */ public function shouldUpdateCommentByCommentId($commentId) @@ -113,6 +115,7 @@ public function shouldUpdateCommentByCommentId($commentId) /** * @test + * * @depends shouldUpdateCommentByCommentId */ public function shouldRemoveCommentByCommentId($commentId) diff --git a/test/Github/Tests/Integration/ResultPagerTest.php b/test/Github/Tests/Integration/ResultPagerTest.php index 447c52913ed..4dd24e37904 100644 --- a/test/Github/Tests/Integration/ResultPagerTest.php +++ b/test/Github/Tests/Integration/ResultPagerTest.php @@ -9,24 +9,6 @@ */ class ResultPagerTest extends TestCase { - /** - * @test - */ - public function shouldPaginateGetRequests() - { - $repositoriesApi = $this->client->api('user'); - $repositoriesApi->setPerPage(10); - - $pager = $this->createPager(); - - $repositories = $pager->fetch($repositoriesApi, 'repositories', ['KnpLabs']); - $this->assertCount(10, $repositories); - - $repositoriesApi->setPerPage(20); - $repositories = $pager->fetch($repositoriesApi, 'repositories', ['KnpLabs']); - $this->assertCount(20, $repositories); - } - /** * @test * @@ -43,10 +25,8 @@ public function shouldPaginateGetRequests() public function shouldGetAllResultsFromSearchApi() { $searchApi = $this->client->search(); - $searchApi->setPerPage(10); $pager = $this->createPager(); - $users = $pager->fetch($searchApi, 'users', ['location:Kyiv']); $this->assertCount(10, $users); } diff --git a/test/Github/Tests/Integration/UserTest.php b/test/Github/Tests/Integration/UserTest.php index 57dbeceeefc..7b8f9f0c364 100644 --- a/test/Github/Tests/Integration/UserTest.php +++ b/test/Github/Tests/Integration/UserTest.php @@ -138,4 +138,25 @@ public function shouldGetReposBeingStarred() $this->assertArrayHasKey('git_url', $repo); $this->assertArrayHasKey('svn_url', $repo); } + + /** + * @test + */ + public function shouldGetEventsForAuthenticatedUserBeignWatched() + { + $username = 'l3l0'; + + $events = $this->client->api('user')->events($username); + $event = array_pop($events); + + $this->assertArrayHasKey('id', $event); + $this->assertArrayHasKey('type', $event); + $this->assertArrayHasKey('actor', $event); + $this->assertArrayHasKey('login', $event['actor']); + $this->assertArrayHasKey('repo', $event); + $this->assertArrayHasKey('name', $event['repo']); + $this->assertArrayHasKey('payload', $event); + $this->assertArrayHasKey('public', $event); + $this->assertArrayHasKey('created_at', $event); + } } diff --git a/test/Github/Tests/Mock/PaginatedResponse.php b/test/Github/Tests/Mock/PaginatedResponse.php index 4586de402ec..296adf86457 100644 --- a/test/Github/Tests/Mock/PaginatedResponse.php +++ b/test/Github/Tests/Mock/PaginatedResponse.php @@ -3,6 +3,7 @@ namespace Github\Tests\Mock; use GuzzleHttp\Psr7\Response; +use GuzzleHttp\Psr7\Utils; /** * @author Tobias Nyholm @@ -18,10 +19,10 @@ public function __construct($loopCount, array $content = []) $this->loopCount = $loopCount; $this->content = $content; - parent::__construct(200, ['Content-Type'=>'application/json'], \GuzzleHttp\Psr7\stream_for(json_encode($content))); + parent::__construct(200, ['Content-Type' => 'application/json'], Utils::streamFor(json_encode($content))); } - public function getHeader($header) + public function getHeader($header): array { if ($header === 'Link') { if ($this->loopCount > 1) { @@ -38,7 +39,7 @@ public function getHeader($header) return parent::getHeader($header); } - public function hasHeader($header) + public function hasHeader($header): bool { if ($header === 'Link') { return true; diff --git a/test/Github/Tests/ResultPagerTest.php b/test/Github/Tests/ResultPagerTest.php index 41327c5d9d1..b898528483b 100644 --- a/test/Github/Tests/ResultPagerTest.php +++ b/test/Github/Tests/ResultPagerTest.php @@ -4,8 +4,10 @@ use Github\Api\Issue; use Github\Api\Organization\Members; +use Github\Api\Repo; use Github\Api\Repository\Statuses; use Github\Api\Search; +use Github\Api\User; use Github\Client; use Github\ResultPager; use Github\Tests\Mock\PaginatedResponse; @@ -13,6 +15,7 @@ use GuzzleHttp\Psr7\Utils; use Http\Client\HttpClient; use Psr\Http\Client\ClientInterface; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; /** * @author Ramon de la Fuente @@ -21,6 +24,8 @@ */ class ResultPagerTest extends \PHPUnit\Framework\TestCase { + use ExpectDeprecationTrait; + public function provideFetchCases() { return [ @@ -113,6 +118,40 @@ public function shouldGetAllSearchResults() $this->assertCount($amountLoops * count($content['items']), $result); } + /** + * @test + */ + public function shouldHandleEmptyContributorListWith204Header() + { + // Set up a 204 response with an empty body + $response = new Response(204, [], ''); + $username = 'testuser'; + $reponame = 'testrepo'; + + // Mock the HttpClient to return the empty response + $httpClientMock = $this->getMockBuilder(HttpClient::class) + ->onlyMethods(['sendRequest']) + ->getMock(); + $httpClientMock + ->method('sendRequest') + ->willReturn($response); + + $client = Client::createWithHttpClient($httpClientMock); + + $repoApi = new Repo($client); + + $paginator = $this->getMockBuilder(ResultPager::class) + ->setConstructorArgs([$client]) // Pass the Client in the constructor + ->onlyMethods(['fetchAll']) + ->getMock(); + $paginator->expects($this->once()) + ->method('fetchAll') + ->with($repoApi, 'contributors', [$username, $reponame]) + ->willReturn([]); + + $this->assertEquals([], $paginator->fetchAll($repoApi, 'contributors', [$username, $reponame])); + } + public function testFetch() { $result = ['foo']; @@ -138,6 +177,29 @@ public function testFetch() $this->assertEquals($result, $paginator->fetch($api, $method, $parameters)); } + public function testEmptyFetch() + { + $parameters = ['username']; + $api = $this->getMockBuilder(User::class) + ->disableOriginalConstructor() + ->onlyMethods(['events']) + ->getMock(); + $api->expects($this->once()) + ->method('events') + ->with(...$parameters) + ->willReturn(''); + + $paginator = $this->getMockBuilder(ResultPager::class) + ->disableOriginalConstructor() + ->onlyMethods(['postFetch']) + ->getMock(); + + $paginator->expects($this->once()) + ->method('postFetch'); + + $this->assertEquals([], $paginator->fetch($api, 'events', $parameters)); + } + public function testFetchAllPreserveKeys() { $content = [ @@ -149,7 +211,7 @@ public function testFetchAllPreserveKeys() 'sha' => '43068834af7e501778708ed13106de95f782328c', ]; - $response = new Response(200, ['Content-Type'=>'application/json'], Utils::streamFor(json_encode($content))); + $response = new Response(200, ['Content-Type' => 'application/json'], Utils::streamFor(json_encode($content))); // httpClient mock $httpClientMock = $this->getMockBuilder(HttpClient::class) @@ -197,4 +259,46 @@ public function testFetchAllWithoutKeys() $this->assertCount(9, $result); } + + public function testFetchAll() + { + $content = [ + ['title' => 'issue 1'], + ['title' => 'issue 2'], + ['title' => 'issue 3'], + ]; + + $response = new PaginatedResponse(3, $content); + + // httpClient mock + $httpClientMock = $this->getMockBuilder(HttpClient::class) + ->onlyMethods(['sendRequest']) + ->getMock(); + $httpClientMock + ->expects($this->exactly(3)) + ->method('sendRequest') + ->willReturn($response); + + $client = Client::createWithHttpClient($httpClientMock); + + $api = new Issue($client); + $paginator = new ResultPager($client); + $result = $paginator->fetchAll($api, 'all', ['knplabs', 'php-github-api']); + + $this->assertCount(9, $result); + } + + /** + * @group legacy + */ + public function testPostFetchDeprecation() + { + $this->expectDeprecation('Since KnpLabs/php-github-api 3.2: The "Github\ResultPager::postFetch" method is deprecated and will be removed.'); + + $clientMock = $this->createMock(Client::class); + $clientMock->method('getLastResponse')->willReturn(new PaginatedResponse(3, [])); + + $paginator = new ResultPager($clientMock); + $paginator->postFetch(); + } }