GitLab CI中PHPUnit测试偶发CouldNotLoadImage异常求助
GitLab CI中PHPUnit测试偶尔失败:Spatie Media Library无法加载临时图片
异常信息
Spatie\Image\Exceptions\CouldNotLoadImage: Could not load image at path `/builds/api/storage/media-library/temp/u9hn06FL7CIz4gDf3PClKfiCsP6CCNEn/eKb9zA0BzpXjZg1CDSityXjDUcewN0yfthumb-xs.jpeg` /builds/api/vendor/spatie/image/src/Exceptions/CouldNotLoadImage.php:11 /builds/api/vendor/spatie/image/src/Drivers/Gd/GdDriver.php:92 /builds/api/vendor/spatie/image/src/Image.php:49 /builds/api/vendor/spatie/laravel-medialibrary/src/Conversions/Actions/PerformManipulationsAction.php:34 /builds/api/vendor/spatie/laravel-medialibrary/src/Conversions/Actions/PerformConversionAction.php:30 /builds/api/vendor/spatie/laravel-medialibrary/src/Conversions/FileManipulator.php:71 /builds/api/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php:240 /builds/api/vendor/spatie/laravel-medialibrary/src/Conversions/FileManipulator.php:70 /builds/api/vendor/spatie/laravel-medialibrary/src/Conversions/Jobs/PerformConversionsJob.php:30 /builds/api/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:36 /builds/api/vendor/laravel/framework/src/Illuminate/Container/Util.php:41 /builds/api/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:93 /builds/api/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:35 /builds/api/vendor/laravel/framework/src/Illuminate/Container/Container.php:662 /builds/api/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php:128 /builds/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:144 /builds/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:119 /builds/api/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php:132 /builds/api/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php:123 /builds/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:144 /builds/api/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:119 /builds/api/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php:122 /builds/api/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php:70 /builds/api/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php:102 /builds/api/vendor/laravel/framework/src/Illuminate/Queue/SyncQueue.php:43 /builds/api/vendor/laravel/framework/src/Illuminate/Queue/Queue.php:59 /builds/api/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php:247 /builds/api/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php:230 /builds/api/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php:77 /builds/api/vendor/laravel/framework/src/Illuminate/Foundation/Bus/PendingDispatch.php:193 /builds/api/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php:388 /builds/api/vendor/spatie/laravel-medialibrary/src/Conversions/FileManipulator.php:98 /builds/api/vendor/spatie/laravel-medialibrary/src/Conversions/FileManipulator.php:40 /builds/api/vendor/spatie/laravel-medialibrary/src/MediaCollections/Filesystem.php:37 /builds/api/vendor/spatie/laravel-medialibrary/src/MediaCollections/FileAdder.php:438 /builds/api/vendor/spatie/laravel-medialibrary/src/MediaCollections/FileAdder.php:420 /builds/api/vendor/spatie/laravel-medialibrary/src/MediaCollections/FileAdder.php:339 /builds/api/database/factories/ProjectPool/ProjectFactory.php:88 /builds/api/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:713 /builds/api/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php:240 /builds/api/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:712 /builds/api/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php:240 /builds/api/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:711 /builds/api/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:289 /builds/api/tests/Feature/API/Mutations/ProjectPool/UpdateProjectTest.php:107
已知环境与问题特征
- 本地测试无异常,GitLab CI流水线偶尔出现失败,无固定失败用例
- 本地和CI环境均使用Minio作为Laravel文件存储磁盘
- Spatie Laravel Media Library版本:v11.4.7
- 推测核心原因:文件从Minio复制到本地临时目录失败,但组件未校验复制结果
排查与解决步骤
1. 增加文件复制后的校验逻辑
重写Media Library的Filesystem类中的copyFromRemote方法,添加本地文件存在性与可读性校验:
use Spatie\MediaLibrary\MediaCollections\Filesystem as BaseFilesystem; class CustomFilesystem extends BaseFilesystem { public function copyFromRemote(string $sourcePath, string $targetPath): void { parent::copyFromRemote($sourcePath, $targetPath); // 校验文件是否存在且可读 if (!file_exists($targetPath) || !is_readable($targetPath)) { throw new \Exception("Failed to copy file from Minio to local path: {$targetPath}"); } } }
然后在AppServiceProvider中替换绑定:
public function register() { $this->app->bind(\Spatie\MediaLibrary\MediaCollections\Filesystem::class, CustomFilesystem::class); }
2. 调整CI环境临时目录权限
在GitLab CI脚本中添加权限配置,确保测试进程对临时目录有读写权限:
before_script: - chmod -R 775 /builds/api/storage/media-library/temp - chown -R gitlab-runner:gitlab-runner /builds/api/storage/media-library/temp
3. 切换测试环境队列驱动
将同步队列改为数组队列,避免文件未完全复制就触发转换任务:
在phpunit.xml中修改:
<env name="QUEUE_CONNECTION" value="array"/>
或者在测试类中临时切换:
use Illuminate\Support\Facades\Queue; protected function setUp(): void { parent::setUp(); Queue::fake(); }
4. 优化Minio客户端配置
在config/filesystems.php的Minio磁盘配置中增加超时与重试机制:
'disks' => [ 'minio' => [ 'driver' => 's3', 'key' => env('MINIO_ACCESS_KEY'), 'secret' => env('MINIO_SECRET_KEY'), 'region' => env('MINIO_REGION'), 'bucket' => env('MINIO_BUCKET'), 'url' => env('MINIO_URL'), 'endpoint' => env('MINIO_ENDPOINT'), 'use_path_style_endpoint' => true, 'options' => [ 'timeout' => 30, 'connect_timeout' => 10, 'retries' => 3, ], ], ],
5. 启用详细日志排查
在CI环境中开启Laravel debug日志,同时在测试代码中添加文件状态日志:
// 在Factory或者测试类中添加 \Log::info('Copying file to temp', [ 'source' => $sourcePath, 'target' => $targetPath, 'target_exists' => file_exists($targetPath), 'target_readable' => is_readable($targetPath), ]);
内容的提问来源于stack exchange,提问作者Christian Holländer
相关产品推荐
相关产品推荐

