func yarn2InstallModules()

in cmd/nodejs/yarn/main.go [228:283]


func yarn2InstallModules(ctx *gcp.Context, pjs *nodejs.PackageJSON) error {
	if err := ar.GenerateYarnConfig(ctx); err != nil {
		return fmt.Errorf("generating Artifact Registry credentials: %w", err)
	}

	cmd := []string{"yarn", "install", "--immutable"}
	yarnCacheExists, err := ctx.FileExists(ctx.ApplicationRoot(), ".yarn", "cache")
	if err != nil {
		return err
	}
	// In Plug'n'Play mode (https://yarnpkg.com/features/pnp) all dependencies must be included in
	// the Yarn cache. The --immutable-cache option will abort the install with an error if anything
	// is missing or out of date.
	if yarnCacheExists {
		cmd = append(cmd, "--immutable-cache")
	}
	if _, err := ctx.Exec(cmd, gcp.WithUserAttribution); err != nil {
		return err
	}

	if gcpBuild := nodejs.HasGCPBuild(pjs); gcpBuild {
		if _, err := ctx.Exec([]string{"yarn", "run", "gcp-build"}, gcp.WithUserAttribution); err != nil {
			return err
		}
	}
	if appHostingBuildScript, ok := os.LookupEnv(nodejs.AppHostingBuildEnv); ok {
		if _, err := ctx.Exec(strings.Split(appHostingBuildScript, " "), gcp.WithUserAttribution); err != nil {
			return err
		}
	}

	// If there are no devDependencies, there is nothing to prune. We are done.
	if !nodejs.HasDevDependencies(pjs) {
		return nil
	}

	nodeEnv := nodejs.NodeEnv()
	if nodeEnv != nodejs.EnvProduction {
		ctx.Logf("Retaining devDependencies because NODE_ENV=%q", nodeEnv)
		return nil
	}
	hasWorkPlugin, err := nodejs.HasYarnWorkspacePlugin(ctx)
	if err != nil {
		return err
	}
	if !hasWorkPlugin {
		ctx.Warnf("Keeping devDependencies because the Yarn workspace-tools plugin is not installed. You can add it to your project by running 'yarn plugin import workspace-tools'")
		return nil
	}
	// For Yarn2, dependency pruning is via the workspaces plugin.
	ctx.Logf("Pruning devDependencies")
	if _, err := ctx.Exec([]string{"yarn", "workspaces", "focus", "--all", "--production"}, gcp.WithUserAttribution); err != nil {
		return err
	}
	return nil
}