Merge pull request #702 from flightphp/ci-add-multiple-OSs

Update workflow to support multiple OS environments
pull/704/head v3.18.3
n0nag0n 2 days ago committed by GitHub
commit 6b47c10192
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,23 +1,27 @@
name: Pull Request Check name: 🚀 Pull Request Check 🔍
on: [pull_request] on: [pull_request]
jobs: jobs:
unit-test: unit-test:
name: Unit testing name: 🧪 Unit Testing - PHP ${{ matrix.php }} on ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
php: [7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5] php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
runs-on: ubuntu-latest os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps: steps:
- name: Checkout repository - name: 📂 Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: shivammathur/setup-php@v2 - name: 🐘 Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with: with:
php-version: ${{ matrix.php }} php-version: ${{ matrix.php }}
extensions: curl, mbstring extensions: mbstring, pdo_sqlite, fileinfo
tools: composer:v2 tools: composer:v2
- run: composer install - name: 📦 Install dependencies and 🧪 Run tests
- run: composer test run: |
composer install --no-progress --no-ansi -n
composer test -- --colors=never --no-interaction

@ -45,6 +45,8 @@
} }
}, },
"require-dev": { "require-dev": {
"ext-mbstring": "*",
"ext-fileinfo": "*",
"ext-pdo_sqlite": "*", "ext-pdo_sqlite": "*",
"flightphp/container": "^1.3", "flightphp/container": "^1.3",
"flightphp/runway": "^1.2", "flightphp/runway": "^1.2",

@ -131,14 +131,15 @@ class UploadedFile
throw new Exception($this->getUploadErrorMessage($this->error)); throw new Exception($this->getUploadErrorMessage($this->error));
} }
if (is_writeable(dirname($targetPath)) === false) {
throw new Exception('Target directory is not writable');
}
// Prevent path traversal attacks // Prevent path traversal attacks
if (strpos($targetPath, '..') !== false) { if (strpos($targetPath, '..') !== false) {
throw new Exception('Invalid target path: contains directory traversal'); throw new Exception('Invalid target path: contains directory traversal');
} }
if (is_writeable(dirname($targetPath)) === false) {
throw new Exception('Target directory is not writable');
}
// Prevent absolute paths (basic check for Unix/Windows) // Prevent absolute paths (basic check for Unix/Windows)
if ($targetPath[0] === '/' || (strlen($targetPath) > 1 && $targetPath[1] === ':')) { if ($targetPath[0] === '/' || (strlen($targetPath) > 1 && $targetPath[1] === ':')) {
throw new Exception('Invalid target path: absolute paths not allowed'); throw new Exception('Invalid target path: absolute paths not allowed');

@ -29,8 +29,12 @@ class RenderTest extends TestCase
public function testRenderLayout(): void public function testRenderLayout(): void
{ {
$this->app->render('hello', ['name' => 'Bob'], 'content'); $this->app->render('hello', ['name' => 'Bob'], 'content');
ob_start();
$this->app->render('layouts/layout'); $this->app->render('layouts/layout');
$html = ob_get_clean();
$html = str_replace(["\r\n", "\n"], '', $html);
echo $html;
$this->expectOutputString("<body>Hello, Bob!</body>\n"); $this->expectOutputString("<body>Hello, Bob!</body>");
} }
} }

@ -171,9 +171,9 @@ class SimplePdoTest extends TestCase
$this->assertInstanceOf(Collection::class, $row); $this->assertInstanceOf(Collection::class, $row);
$this->assertSame('Alice', $row['name']); $this->assertSame('Alice', $row['name']);
} catch (PDOException $exception) { } catch (PDOException $exception) {
$this->assertSame( $this->assertStringContainsString(
'Prepare failed: near "RETURNING": syntax error', 'near "returning": syntax error',
$exception->getMessage(), strtolower($exception->getMessage()),
); );
} }
} }

@ -114,6 +114,10 @@ class UploadedFileTest extends TestCase
public function testMoveToSymlinkNonPost(): void public function testMoveToSymlinkNonPost(): void
{ {
if (PHP_OS === 'WINNT') {
$this->markTestSkipped('Symbolic links require special privileges on Windows.');
}
file_put_contents('real_file', 'test'); file_put_contents('real_file', 'test');
if (file_exists('tmp_symlink')) { if (file_exists('tmp_symlink')) {
unlink('tmp_symlink'); unlink('tmp_symlink');

@ -102,9 +102,13 @@ class ViewTest extends TestCase
$this->view->set('name', 'Bob'); $this->view->set('name', 'Bob');
$this->view->extension = '.html'; $this->view->extension = '.html';
ob_start();
$this->view->render('world'); $this->view->render('world');
$html = ob_get_clean();
$html = str_replace(["\r\n", "\n"], '', $html);
echo $html;
$this->expectOutputString("Hello world, Bob!\n"); $this->expectOutputString("Hello world, Bob!");
} }
public function testGetTemplateAbsolutePath(): void public function testGetTemplateAbsolutePath(): void

@ -123,8 +123,8 @@ PHP;
output; // phpcs:ignore output; // phpcs:ignore
$this->assertStringContainsString( $this->assertStringContainsString(
str_replace(PHP_EOL, '', $expected), str_replace(["\r\n", "\n"], '', $expected),
str_replace(PHP_EOL, '', $this->removeColors(file_get_contents(static::$ou))), str_replace(["\r\n", "\n"], '', $this->removeColors(file_get_contents(static::$ou))),
); );
} }

Loading…
Cancel
Save