Skip to content
Merged
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
36 changes: 25 additions & 11 deletions src/fosslight_dependency/package_manager/Yarn.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# SPDX-License-Identifier: Apache-2.0

import os
import re
import logging
import subprocess
import json
Expand Down Expand Up @@ -56,28 +57,41 @@ def start_license_checker(self):

self.detect_yarn_version()

# For Yarn Berry (2+), check if using PnP mode
# For Yarn Berry (2+), PnP is the default mode.
# Only treat as non-PnP if .yarnrc.yml explicitly sets nodeLinker to node-modules or pnpm.
is_pnp_mode = False
if self.yarn_version and self.yarn_version >= 2:
# Check if .pnp.cjs exists (PnP mode indicator)
if os.path.exists('.pnp.cjs') or os.path.exists('.pnp.js'):
is_pnp_mode = True
is_pnp_mode = True
yarnrc_path = '.yarnrc.yml'
if os.path.exists(yarnrc_path):
with open(yarnrc_path, 'r', encoding='utf-8') as f:
yarnrc_content = f.read()
match = re.search(r'^\s*nodeLinker\s*:\s*(\S+)', yarnrc_content, re.MULTILINE)
if match:
node_linker = match.group(1).strip('"\'')
if node_linker in ('node-modules', 'pnpm'):
is_pnp_mode = False
logger.info(f"Detected Yarn Berry with nodeLinker: {node_linker} (non-PnP mode)")
if is_pnp_mode:
logger.info("Detected Yarn Berry with PnP mode")

if not os.path.isdir(node_modules):
logger.info("node_modules directory does not exist.")
self.flag_tmp_node_modules = True

# For PnP mode, try to force node_modules creation
if is_pnp_mode:
logger.info("Attempting to create node_modules for PnP project...")
yarn_install_cmd = 'YARN_NODE_LINKER=node-modules yarn install --production --ignore-scripts'
logger.info(f"Executing: {yarn_install_cmd}")
yarn_install_env = None
if self.yarn_version and self.yarn_version >= 2:
if is_pnp_mode:
# Force node-modules linker via env (cross-platform; avoids POSIX shell VAR=val syntax)
logger.info("Attempting to create node_modules for PnP project using YARN_NODE_LINKER=node-modules...")
yarn_install_env = os.environ.copy()
yarn_install_env['YARN_NODE_LINKER'] = 'node-modules'
yarn_install_cmd = 'yarn install --mode=skip-build'
else:
yarn_install_cmd = 'yarn install --production --ignore-scripts'
logger.info(f"Executing: {yarn_install_cmd}")
logger.info(f"Executing: {yarn_install_cmd}")

result = subprocess.run(yarn_install_cmd, shell=True, capture_output=True, text=True)
result = subprocess.run(yarn_install_cmd, shell=True, capture_output=True, text=True, env=yarn_install_env)
if result.returncode != 0:
logger.error(f"{yarn_install_cmd} failed")
if is_pnp_mode:
Expand Down
Loading