90%的ci中“permission denied”是vendor/、composer.lock或~/.composer/cache属主非当前runner用户所致,需用ls -ld定位后执行sudo chown -r $user:$user修复,禁用chmod 777和sudo composer install。

CI里composer install报Permission denied,90%是属主错配
不是chmod不够,也不是缺sudo,而是vendor/、composer.lock或~/.composer/cache的owner不是当前运行用户。GitHub Actions默认用runner用户执行命令,但若之前某步用sudo写过文件,或缓存被污染,后续composer install就会在写autoload.php、解压zip时卡住。
快速确认方法:在run步骤开头加ls -ld vendor/ composer.lock $(composer config --global cache-dir)。只要任一输出第三列不是$RUNNER_USER(通常是runner),就该修所有权了。
- 修复项目级路径:
sudo chown -R $USER:$USER vendor/ composer.lock - 修复全局缓存:
sudo chown -R $USER:$USER $(composer config --global cache-dir) - 别碰
chmod 777——它会让vendor/bin/下可执行文件被CI安全策略拒绝
GitHub Actions中必须显式控制工作目录和PHP环境
actions/checkout@v4之后,当前目录是空的${{ github.workspace }},composer.json根本不在当前路径。不切目录就跑composer install,等于对空文件夹操作,必然报“Could not find composer.json”。
两种等效写法,选一个坚持用:
- 所有
run前加working-directory: ${{ github.workspace }} - 在
run里第一行写cd ${{ github.workspace }} && composer install ...
同时,Ubuntu runner默认没PHP,也没ext-zip、ext-xml——composer install启动就校验这些扩展,缺一个直接退出。必须用shivammathur/setup-php@v2显式声明php-version和extensions,比如:mbstring, xml, zip, curl。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
缓存策略错了,权限问题会反复出现
缓存vendor/看着省事,但跨job或跨workflow复用时,容易因UID不一致导致权限继承异常;缓存~/.composer/cache更稳,但它只管下载包,不解决vendor目录写入问题——两者得一起配,缺一不可。
正确缓存组合:
- 先缓存
~/.composer/cache,key用${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - 再缓存
vendor/,key加PHP版本:${{ runner.os }}-vendor-${{ hashFiles('**/composer.lock') }}-${{ matrix.php-version }} - 禁用
cache: composer这种setup-php内置缓存——它不支持自定义key,易与手动缓存冲突
CI中永远不要用sudo composer install
这条命令会把整个vendor/设为root属主,后续任何非root步骤(比如php artisan migrate)都会因无法读取autoload.php而失败。而且一旦发生,chown -R都救不全——部分子目录可能已由不同UID进程创建。
真正需要sudo的,只有归还所有权那一步。其他所有composer命令,包括global require,都应在普通用户上下文中完成。如果composer global require失败,优先查COMPOSER_HOME是否被设成/root/.composer——这是环境变量污染,不是权限问题。
复杂点在于:所有权修复必须分层做,不能只扫一遍vendor/就完事;auth.json、.composer-cache、甚至~/.composer本身,都可能是静默的权限陷阱。










