diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..94fed74 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,22 @@ +name: Tests + +on: + push: + pull_request: + +jobs: + tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: ['7.1', '8.5'] + + steps: + - uses: actions/checkout@v4 + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + - run: composer update --prefer-dist --no-interaction + - run: vendor/bin/phpunit diff --git a/README.md b/README.md index a27b422..38b261a 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,12 @@ # PHP GitHub Status API -[![Build Status](https://travis-ci.com/Jord-JD/php-github-status-api.svg?branch=master)](https://travis-ci.com/Jord-JD/php-github-status-api) - ---- - -⚠️ **Warning:** As of 11th December 2018, GitHub have deprecated the status page that this package parses, so current status information may not be up-to-date. More information: https://blog.github.com/2018-12-11-introducing-the-new-github-status-site/ - ---- +[![Tests](https://github.com/Jord-JD/php-github-status-api/actions/workflows/tests.yml/badge.svg)](https://github.com/Jord-JD/php-github-status-api/actions/workflows/tests.yml) This package provides a way to programmatically determine if GitHub is working -well, or experiencing issues. -Both the current status and historical statuses can be looked up by date. +well, or experiencing issues. It uses GitHub's current Statuspage API. + +The replacement API does not provide the historical feed used by older package +versions. Passing a past date therefore returns `GitHubStatus::UNKNOWN`.

diff --git a/composer.json b/composer.json index 2a05d53..d956f2c 100644 --- a/composer.json +++ b/composer.json @@ -10,12 +10,11 @@ ], "license": "LGPL-3.0-only", "require": { - "ivopetkov/html5-dom-document-php": "^1.1", "nesbot/carbon": "^2.7", "php": "^7.1 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.6" + "phpunit/phpunit": "^7.5 || ^9.6" }, "autoload": { "psr-4": { diff --git a/src/Client.php b/src/Client.php index 7236325..234ec15 100644 --- a/src/Client.php +++ b/src/Client.php @@ -4,60 +4,49 @@ use Carbon\Carbon; use JordJD\GitHubStatusApi\Enums\GitHubStatus; -use IvoPetkov\HTML5DOMDocument; class Client { - const GITHUB_STATUS_URL = 'https://status.github.com/messages'; + const GITHUB_STATUS_URL = 'https://www.githubstatus.com/api/v2/status.json'; - const CLASS_TO_STATUS_MAP = [ - 'good' => GitHubStatus::GOOD, - 'major' => GitHubStatus::MAJOR, + const INDICATOR_TO_STATUS_MAP = [ + 'none' => GitHubStatus::GOOD, 'minor' => GitHubStatus::MINOR, + 'major' => GitHubStatus::MAJOR, + 'critical' => GitHubStatus::MAJOR, ]; + private $statusFetcher; + + public function __construct(callable $statusFetcher = null) + { + $this->statusFetcher = $statusFetcher; + } + public function status(Carbon $datetime = null) { - if ($datetime === null) { - $datetime = Carbon::now(); + if ($datetime !== null && !$datetime->isToday()) { + return GitHubStatus::UNKNOWN; } - $dom = $this->getDomDocument($datetime); - - $timeElements = $dom->querySelectorAll('time'); - - /** @var HTML5DOMDocument $timeElement*/ - foreach($timeElements as $timeElement) { - - $timeElementDatetime = Carbon::parse($timeElement->getAttribute('datetime')); + $response = $this->statusFetcher + ? call_user_func($this->statusFetcher) + : @file_get_contents(self::GITHUB_STATUS_URL); - if ($datetime >= $timeElementDatetime) { - - $class = $timeElement->parentNode->attributes->getNamedItem('class')->textContent; - $classParts = explode(' ', $class); - - foreach($classParts as $classPart) { - - if (array_key_exists($classPart, self::CLASS_TO_STATUS_MAP)) { - return self::CLASS_TO_STATUS_MAP[$classPart]; - } - - } + if (!is_string($response)) { + return GitHubStatus::UNKNOWN; + } - return GitHubStatus::UNKNOWN; - } + $statusResponse = json_decode($response, true); + if (!is_array($statusResponse) || empty($statusResponse['status']['indicator'])) { + return GitHubStatus::UNKNOWN; } - } - - private function getDomDocument(Carbon $datetime) - { - $url = self::GITHUB_STATUS_URL.'/'.$datetime->format('Y-m-d'); - $html = file_get_contents($url); - $dom = new HTML5DOMDocument(); - $dom->loadHTML($html); + $indicator = $statusResponse['status']['indicator']; - return $dom; + return array_key_exists($indicator, self::INDICATOR_TO_STATUS_MAP) + ? self::INDICATOR_TO_STATUS_MAP[$indicator] + : GitHubStatus::UNKNOWN; } -} \ No newline at end of file +} diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 79f4f86..9726b3b 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -2,45 +2,50 @@ namespace JordJD\GitHubStatusApi; -use JordJD\GitHubStatusApi\Client; +use Carbon\Carbon; use JordJD\GitHubStatusApi\Enums\GitHubStatus; use PHPUnit\Framework\TestCase; class ClientTest extends TestCase { - public function testStatusShouldReturnGood() + /** + * @dataProvider statusIndicatorProvider + */ + public function testStatusIndicatorsAreMapped($indicator, $expectedStatus) { - $mockedClient = $this->createMock(Client::class); - $mockedClient->method('status') - ->willReturn(GitHubStatus::GOOD); + $client = new Client(function () use ($indicator) { + return json_encode(['status' => ['indicator' => $indicator]]); + }); - $this->assertSame(GitHubStatus::GOOD, $mockedClient->status()); + $this->assertSame($expectedStatus, $client->status()); } - public function testStatusShouldReturnMinor() + public function statusIndicatorProvider() { - $mockedClient = $this->createMock(Client::class); - $mockedClient->method('status') - ->willReturn(GitHubStatus::MINOR); - - $this->assertSame(GitHubStatus::MINOR, $mockedClient->status()); + return [ + ['none', GitHubStatus::GOOD], + ['minor', GitHubStatus::MINOR], + ['major', GitHubStatus::MAJOR], + ['critical', GitHubStatus::MAJOR], + ['unrecognised', GitHubStatus::UNKNOWN], + ]; } - public function testStatusShouldReturnMajor() + public function testInvalidResponsesReturnUnknown() { - $mockedClient = $this->createMock(Client::class); - $mockedClient->method('status') - ->willReturn(GitHubStatus::MAJOR); + $client = new Client(function () { + return 'not-json'; + }); - $this->assertSame(GitHubStatus::MAJOR, $mockedClient->status()); + $this->assertSame(GitHubStatus::UNKNOWN, $client->status()); } - public function testStatusShouldReturnUnknown() + public function testHistoricalDatesReturnUnknown() { - $mockedClient = $this->createMock(Client::class); - $mockedClient->method('status') - ->willReturn(GitHubStatus::UNKNOWN); + $client = new Client(function () { + return json_encode(['status' => ['indicator' => 'none']]); + }); - $this->assertSame(GitHubStatus::UNKNOWN, $mockedClient->status()); + $this->assertSame(GitHubStatus::UNKNOWN, $client->status(Carbon::parse('2018-12-06 17:00'))); } }