Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions .github/workflows/acceptance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,17 @@ jobs:
- name: Run acceptance tests
run: php vendor/bin/testo --suite=Acceptance

# rr against the real GitHub: about 6 API requests per job with a cold DLoad cache, 5 with a warm one
live:
name: Live GitHub, ${{ matrix.os }}
if: github.event_name == 'workflow_dispatch'
name: Live GitHub
runs-on: ${{ matrix.os }}
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
env:
DLOAD_CACHE_DIR: ${{ github.workspace }}/runtime/dload-cache
steps:
- name: Checkout
uses: actions/checkout@v7
Expand All @@ -74,8 +76,30 @@ jobs:
with:
dependency-versions: highest

# Release metadata only, no binaries or tokens. A cache key is never overwritten,
# so every run saves its own registry and the next run starts from the newest one.
- name: Restore DLoad version registry
uses: actions/cache@v6
with:
path: runtime/dload-cache
key: dload-registry-${{ runner.os }}-${{ github.run_id }}
restore-keys: dload-registry-${{ runner.os }}-

- name: GitHub API usage before
run: gh api rate_limit --jq '.resources.core | "used \(.used) of \(.limit)"'
shell: bash
env:
GH_TOKEN: ${{ github.token }}

- name: Run live tests
run: php vendor/bin/testo --suite=Live
env:
RR_CLI_LIVE_TESTS: '1'
GITHUB_TOKEN: ${{ github.token }}

- name: GitHub API usage after
if: always()
run: gh api rate_limit --jq '.resources.core | "used \(.used) of \(.limit)"'
shell: bash
env:
GH_TOKEN: ${{ github.token }}
53 changes: 45 additions & 8 deletions tests/Live/GitHubTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@
use Testo\Test;

/**
* `rr get` against the real GitHub. The suite is registered only when RR_CLI_LIVE_TESTS is set.
* `rr` against the real GitHub. The suite is registered only when RR_CLI_LIVE_TESTS is set.
*
* New RoadRunner releases must not break these tests: they pin a release line that is complete,
* or check what holds for any release.
*/
#[Test]
final class GitHubTest
{
/**
* Passed through to `rr`: a token lifts the rate limit, and a shared DLoad cache spares the requests
* for release pages already seen.
*/
private const PASSED_ENV = ['GITHUB_TOKEN', 'DLOAD_CACHE_DIR'];

private Workdir $dir;

#[BeforeTest]
Expand All @@ -36,15 +45,43 @@ public function cleanup(): void
#[DataSet(['windows', 'amd64', 'rr.exe'])]
public function downloadsRealBinary(string $os, string $arch, string $binary): void
{
$rr = new Rr($this->dir->path, null);
$token = \getenv('GITHUB_TOKEN');
if (\is_string($token) && $token !== '') {
$rr = $rr->withEnv('GITHUB_TOKEN', $token);
}

$result = $rr->run(['get', '--filter=2025.*', "--os=$os", "--arch=$arch", '--no-config']);
$result = $this->rr()->run(['get', '--filter=2025.*', "--os=$os", "--arch=$arch", '--no-config']);

Assert::same($result->exitCode, 0, (string) $result);
Assert::int((int) \filesize($this->dir->file($binary)))->greaterThan(1_000_000);
}

public function downloadsSemverReleaseByDefault(): void
{
$result = $this->rr()->run(['get', '--os=linux', '--arch=amd64', '--no-config']);

Assert::same($result->exitCode, 0, (string) $result);
Assert::int((int) \filesize($this->dir->file('rr')))->greaterThan(1_000_000);
Assert::same(\preg_match('/\brr \(v?(\d+)\.\d+\.\d+[^)]*\) has been installed/', $result->output(), $match), 1, (string) $result);
// Calendar versions (2023.x-2025.x) are older than 3.x and must lose to it
Assert::int((int) $match[1])->greaterThanOrEqual(3)->lessThan(2000);
}

public function listsReleasesWithCompatibility(): void
{
$result = $this->rr()->run(['versions', '--os=linux', '--arch=amd64']);

Assert::same($result->exitCode, 0, (string) $result);
Assert::string($result->stdout)
->matchesRegex('/^\s*3\.\d+\.\d+\s+stable\s+鉁揬s+\(\d+\)\s+鉁揬s*$/mu')
->matchesRegex('/^\s*2025\.1\.15\s+stable\s+.*\(reason: incompatible version\)/mu');
}

private function rr(): Rr
{
$rr = new Rr($this->dir->path, null);
foreach (self::PASSED_ENV as $name) {
$value = \getenv($name);
if (\is_string($value) && $value !== '') {
$rr = $rr->withEnv($name, $value);
}
}

return $rr;
}
}
Loading