Fix npm build perms during upgrade
This commit is contained in:
@@ -185,21 +185,29 @@ class UpgradeCommand extends Command
|
|||||||
try {
|
try {
|
||||||
$this->ensureCommandAvailable('npm');
|
$this->ensureCommandAvailable('npm');
|
||||||
$this->ensureNpmCacheDirectory();
|
$this->ensureNpmCacheDirectory();
|
||||||
$npmInstall = File::exists($this->basePath.'/package-lock.json') ? 'npm ci' : 'npm install';
|
$this->ensureNodeModulesPermissions();
|
||||||
$installResult = $this->executeCommand($npmInstall, 1200);
|
if (! $this->isNodeModulesWritable()) {
|
||||||
if ($installResult['exitCode'] !== 0) {
|
$this->warn('Skipping frontend build because node_modules is not writable by the current user.');
|
||||||
throw new Exception($installResult['output'] ?: 'npm install failed.');
|
$this->warn('Run: sudo chown -R www-data:www-data '.$this->getNodeModulesPath());
|
||||||
}
|
} else {
|
||||||
if ($installResult['output'] !== '') {
|
$npmInstall = File::exists($this->basePath.'/package-lock.json') ? 'npm ci' : 'npm install';
|
||||||
$this->line($installResult['output']);
|
$installResult = $this->executeCommand($npmInstall, 1200);
|
||||||
}
|
if ($installResult['exitCode'] !== 0) {
|
||||||
|
throw new Exception($installResult['output'] ?: 'npm install failed.');
|
||||||
|
}
|
||||||
|
if ($installResult['output'] !== '') {
|
||||||
|
$this->line($installResult['output']);
|
||||||
|
}
|
||||||
|
|
||||||
$buildResult = $this->executeCommand('npm run build', 1200);
|
$buildResult = $this->executeCommand('npm run build', 1200);
|
||||||
if ($buildResult['exitCode'] !== 0) {
|
if ($buildResult['exitCode'] !== 0) {
|
||||||
throw new Exception($buildResult['output'] ?: 'npm build failed.');
|
throw new Exception($buildResult['output'] ?: 'npm build failed.');
|
||||||
}
|
}
|
||||||
if ($buildResult['output'] !== '') {
|
if ($buildResult['output'] !== '') {
|
||||||
$this->line($buildResult['output']);
|
$this->line($buildResult['output']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->ensureNodeModulesPermissions();
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$this->error('Asset build failed: '.$e->getMessage());
|
$this->error('Asset build failed: '.$e->getMessage());
|
||||||
@@ -428,6 +436,7 @@ class UpgradeCommand extends Command
|
|||||||
$paths = [
|
$paths = [
|
||||||
$this->basePath.'/database',
|
$this->basePath.'/database',
|
||||||
$this->basePath.'/storage',
|
$this->basePath.'/storage',
|
||||||
|
$this->getNodeModulesPath(),
|
||||||
$this->getNpmCacheDir(),
|
$this->getNpmCacheDir(),
|
||||||
$this->getPuppeteerCacheDir(),
|
$this->getPuppeteerCacheDir(),
|
||||||
$this->getXdgCacheDir(),
|
$this->getXdgCacheDir(),
|
||||||
@@ -465,11 +474,56 @@ class UpgradeCommand extends Command
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function ensureNodeModulesPermissions(): void
|
||||||
|
{
|
||||||
|
$nodeModules = $this->getNodeModulesPath();
|
||||||
|
|
||||||
|
if (! File::isDirectory($nodeModules)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isRunningAsRoot() && $this->userExists('www-data')) {
|
||||||
|
$escaped = escapeshellarg($nodeModules);
|
||||||
|
$this->executeCommand("chgrp -R www-data {$escaped}");
|
||||||
|
$this->executeCommand("chmod -R g+rwX {$escaped}");
|
||||||
|
$this->executeCommand("find {$escaped} -type d -exec chmod g+s {} +");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->executeCommand('chmod -R u+rwX '.escapeshellarg($nodeModules));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isNodeModulesWritable(): bool
|
||||||
|
{
|
||||||
|
$nodeModules = $this->getNodeModulesPath();
|
||||||
|
|
||||||
|
if (! File::isDirectory($nodeModules)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$binPath = $nodeModules.'/.bin';
|
||||||
|
if (! is_writable($nodeModules)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File::isDirectory($binPath) && ! is_writable($binPath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getNpmCacheDir(): string
|
protected function getNpmCacheDir(): string
|
||||||
{
|
{
|
||||||
return $this->basePath.'/storage/npm-cache';
|
return $this->basePath.'/storage/npm-cache';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getNodeModulesPath(): string
|
||||||
|
{
|
||||||
|
return $this->basePath.'/node_modules';
|
||||||
|
}
|
||||||
|
|
||||||
protected function getPuppeteerCacheDir(): string
|
protected function getPuppeteerCacheDir(): string
|
||||||
{
|
{
|
||||||
return $this->basePath.'/storage/puppeteer-cache';
|
return $this->basePath.'/storage/puppeteer-cache';
|
||||||
|
|||||||
@@ -132,6 +132,10 @@ class UpgradeCommandTest extends TestCase
|
|||||||
$paths = [
|
$paths = [
|
||||||
base_path().'/database',
|
base_path().'/database',
|
||||||
base_path().'/storage',
|
base_path().'/storage',
|
||||||
|
base_path().'/node_modules',
|
||||||
|
base_path().'/storage/npm-cache',
|
||||||
|
base_path().'/storage/puppeteer-cache',
|
||||||
|
base_path().'/storage/.cache',
|
||||||
base_path().'/bootstrap/cache',
|
base_path().'/bootstrap/cache',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user