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
168 changes: 168 additions & 0 deletions .github/workflows/magento-compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,90 @@ jobs:
echo "Test Inspector status command:"
bin/magento mageforge:theme:inspector status

- name: Test npm Sync Validation
working-directory: magento2
run: |
echo "Setting up Node.js for npm testing..."
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

# Install Node.js if not available
if ! command -v node &> /dev/null; then
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install 20
nvm use 20
fi

echo "Node version: $(node --version)"
echo "npm version: $(npm --version)"

echo "Test npm sync validation with Magento/blank theme..."
THEME_PATH="app/design/frontend/Magento/blank"

# Create a simple package.json for testing
cat > ${THEME_PATH}/package.json << 'EOF'
{
"name": "magento-blank-theme",
"version": "1.0.0",
"description": "Test theme for npm sync validation",
"dependencies": {
"jquery": "^3.7.1"
}
}
EOF

echo "Initial npm install to create package-lock.json and node_modules..."
cd ${THEME_PATH}
npm install

echo "Verifying initial sync status (should be in sync)..."
if npm ls --depth=0 > /dev/null 2>&1; then
echo "✓ Initial state: node_modules in sync"
else
echo "✗ Initial state should be in sync"
exit 1
fi

echo "Simulating out-of-sync state by adding new dependency..."
# Add a new dependency to package.json that's not in node_modules
cat > package.json << 'EOF'
{
"name": "magento-blank-theme",
"version": "1.0.0",
"description": "Test theme for npm sync validation",
"dependencies": {
"jquery": "^3.7.1",
"lodash": "^4.17.21"
}
}
EOF

# Update lock file without installing (simulates a git pull with updated lock file)
npm install --package-lock-only

echo "Verifying out-of-sync state (should fail)..."
if npm ls --depth=0 > /dev/null 2>&1; then
echo "✗ Should detect out-of-sync state"
exit 1
else
echo "✓ Correctly detected out-of-sync state (exit code: $?)"
fi

echo "Testing that npm ci fixes the sync issue..."
npm ci

if npm ls --depth=0 > /dev/null 2>&1; then
echo "✓ npm ci successfully synchronized node_modules"
else
echo "✗ npm ci failed to synchronize"
exit 1
fi

echo "✓ npm sync validation tests passed"
cd ../../../../../../

- name: Test Summary
run: |
echo "MageForge module compatibility test with Magento ${{ matrix.magento-version }} completed"
Expand Down Expand Up @@ -336,6 +420,90 @@ jobs:
echo "Test Inspector status command:"
bin/magento mageforge:theme:inspector status

- name: Test npm Sync Validation
working-directory: magento2
run: |
echo "Setting up Node.js for npm testing..."
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

# Install Node.js if not available
if ! command -v node &> /dev/null; then
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install 20
nvm use 20
fi

echo "Node version: $(node --version)"
echo "npm version: $(npm --version)"

echo "Test npm sync validation with Magento/blank theme..."
THEME_PATH="app/design/frontend/Magento/blank"

# Create a simple package.json for testing
cat > ${THEME_PATH}/package.json << 'EOF'
{
"name": "magento-blank-theme",
"version": "1.0.0",
"description": "Test theme for npm sync validation",
"dependencies": {
"jquery": "^3.7.1"
}
}
EOF

echo "Initial npm install to create package-lock.json and node_modules..."
cd ${THEME_PATH}
npm install

echo "Verifying initial sync status (should be in sync)..."
if npm ls --depth=0 > /dev/null 2>&1; then
echo "✓ Initial state: node_modules in sync"
else
echo "✗ Initial state should be in sync"
exit 1
fi

echo "Simulating out-of-sync state by adding new dependency..."
# Add a new dependency to package.json that's not in node_modules
cat > package.json << 'EOF'
{
"name": "magento-blank-theme",
"version": "1.0.0",
"description": "Test theme for npm sync validation",
"dependencies": {
"jquery": "^3.7.1",
"lodash": "^4.17.21"
}
}
EOF

# Update lock file without installing (simulates a git pull with updated lock file)
npm install --package-lock-only

echo "Verifying out-of-sync state (should fail)..."
if npm ls --depth=0 > /dev/null 2>&1; then
echo "✗ Should detect out-of-sync state"
exit 1
else
echo "✓ Correctly detected out-of-sync state (exit code: $?)"
fi

echo "Testing that npm ci fixes the sync issue..."
npm ci

if npm ls --depth=0 > /dev/null 2>&1; then
echo "✓ npm ci successfully synchronized node_modules"
else
echo "✗ npm ci failed to synchronize"
exit 1
fi

echo "✓ npm sync validation tests passed"
cd ../../../../../../

- name: Test Summary
run: |
echo "MageForge module compatibility test with Magento 2.4.8 completed"
46 changes: 43 additions & 3 deletions src/Service/NodePackageManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public function __construct(
* Install node modules in the specified directory
*
* Uses npm ci if package-lock.json exists, otherwise falls back to npm install
*
* @param string $path
* @param SymfonyStyle $io
* @param bool $isVerbose
* @return bool
*/
public function installNodeModules(string $path, SymfonyStyle $io, bool $isVerbose): bool
{
Expand Down Expand Up @@ -51,11 +56,46 @@ public function installNodeModules(string $path, SymfonyStyle $io, bool $isVerbo
}
}

/**
* Check if node_modules is in sync with package-lock.json
*
* Verifies that installed packages match the lock file by checking:
* 1. node_modules directory exists
* 2. package-lock.json exists
* 3. All packages are installed with correct versions (via npm ls)
*
* @param string $path
* @return bool
*/
public function isNodeModulesInSync(string $path): bool
{
if (!$this->fileDriver->isDirectory($path . '/node_modules')) {
return false;
}

if (!$this->fileDriver->isExists($path . '/package-lock.json')) {
return true;
}

$currentDir = getcwd();
chdir($path);

try {
$this->shell->execute('npm ls --depth=0 --json > /dev/null 2>&1');
chdir($currentDir);
return true;
} catch (\Exception $e) {
chdir($currentDir);
return false;
}
}

/**
* Check for outdated npm packages and report them
*
* Note: npm outdated returns non-zero exit code when packages are outdated,
* so exceptions are caught and ignored
* @param string $path
* @param SymfonyStyle $io
* @return void
*/
public function checkOutdatedPackages(string $path, SymfonyStyle $io): void
{
Expand All @@ -69,7 +109,7 @@ public function checkOutdatedPackages(string $path, SymfonyStyle $io): void
$io->writeln($outdated);
}
} catch (\Exception $e) {
// Ignore errors from npm outdated as it returns non-zero when packages are outdated
// npm outdated returns non-zero exit code when packages are outdated
}

chdir($currentDir);
Expand Down
6 changes: 3 additions & 3 deletions src/Service/ThemeBuilder/HyvaThemes/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,10 @@ public function autoRepair(string $themePath, SymfonyStyle $io, OutputInterface
{
$tailwindPath = rtrim($themePath, '/') . '/web/tailwind';

// Check for node_modules directory
if (!$this->fileDriver->isDirectory($tailwindPath . '/node_modules')) {
// Check if node_modules is in sync with package-lock.json
if (!$this->nodePackageManager->isNodeModulesInSync($tailwindPath)) {
if ($isVerbose) {
$io->warning('Node modules not found in tailwind directory. Installing...');
$io->warning('Node modules out of sync or missing. Installing dependencies...');
}
if (!$this->nodePackageManager->installNodeModules($tailwindPath, $io, $isVerbose)) {
return false;
Expand Down
6 changes: 3 additions & 3 deletions src/Service/ThemeBuilder/TailwindCSS/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ public function autoRepair(string $themePath, SymfonyStyle $io, OutputInterface
{
$tailwindPath = rtrim($themePath, '/') . '/web/tailwind';

// Check for node_modules directory
if (!$this->fileDriver->isDirectory($tailwindPath . '/node_modules')) {
// Check if node_modules is in sync with package-lock.json
if (!$this->nodePackageManager->isNodeModulesInSync($tailwindPath)) {
if ($isVerbose) {
$io->warning('Node modules not found in tailwind directory. Installing npm dependencies ...');
$io->warning('Node modules out of sync or missing. Installing npm dependencies...');
}
if (!$this->nodePackageManager->installNodeModules($tailwindPath, $io, $isVerbose)) {
return false;
Expand Down