Multi-module project created from sources not fully configured

Issue #2293 resolved
Mark Mindenhall created an issue

As stated in other issues, our team chose to use a git monorepo for our org, and for reasons I no longer remember, we structure the repo as follows:

  1. The project root is not a DX project (i.e., no sfdx-project.json file)
  2. Most (but not all) top-level folders are DX projects (i.e., with a sfdx-project.json file) that contain a single DX package. We have 29 of these folders so far, and they all exist as IC2 modules within a single IDEA project.

Here are the steps I follow to get started on this project with IJ/IC2, and the observed results.

Step 1: Create the project

  1. Clone the git monorepo
  2. Select File → New → Project from Existing Sources…, and step through the project creation wizard, accepting all defaults.

After the project is created, I see all 29 DX project/package folders have been created as IC2 modules.

In the Notifications pane, there’s an entry for each module that looks like this:

Also in this initial state, the Tools → Illuminated Cloud submenu looks like this (there are a lot of missing items, including “Configure Project…”):

At this initial state, each DX project/package folder has an .iml file that looks like this (except packages without code don’t have the entry on line 8):

<?xml version="1.0" encoding="UTF-8"?>
<module type="IlluminatedCloud" version="4">
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/config" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/force-app/main/default" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/force-app/test/apex/classes" isTestSource="false" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
</module>

Step 2: Resolve the Notification for a single module

When I click “Resolve” on the Notification for a module (followed by “Ok” in a dialog), I see the following:

This is the Configure Project view, but the only module listed is the one for which I clicked “Resolve”. I can now click on the Connection column for the module, and select a scratch org previously created. I’m prompted to “Rebuild Caches and Indices”, and the project reloads. Now, the Tools → Illuminated Cloud submenu looks like this:

And the .iml file for the resolved module looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<module type="IlluminatedCloud" version="4">
  <component name="FacetManager">
    <facet type="IlluminatedCloud" name="Illuminated Cloud">
      <configuration>
        <option name="connectionName" value="mmscratch03" />
        <option name="connectionType" value="SFDX" />
        <option name="moduleContents">
          <ModuleContents>
            <option name="contentSelectionType" value="SELECTED" />
          </ModuleContents>
        </option>
      </configuration>
    </facet>
  </component>
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/config" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/force-app/main/default" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/unpackaged-metadata" isTestSource="false" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
</module>

However, the module is not fully resolved, as there’s still a Notification:

I was not expecting to see the “should exclude” messages for the .sfdx and .sf directories, as you said you had fixed that. But perhaps this is going through a different path?

Step 3: Resolve the Notification again

I clicked “Resolve” on the new Notification, clicked “Ok” on 3 dialogs, then “Yes” on “Rebuild Caches and Indices”, and the project reloaded. Now when the modules are validated, there’s no Notification for the selected module, and the .iml file now looks correct:

<?xml version="1.0" encoding="UTF-8"?>
<module type="IlluminatedCloud" version="4">
  <component name="FacetManager">
    <facet type="IlluminatedCloud" name="Illuminated Cloud">
      <configuration>
        <option name="connectionName" value="mmscratch03" />
        <option name="connectionType" value="SFDX" />
        <option name="moduleContents">
          <ModuleContents>
            <option name="contentSelectionType" value="SELECTED" />
          </ModuleContents>
        </option>
      </configuration>
    </facet>
  </component>
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/config" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/force-app/main/default" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/unpackaged-metadata" isTestSource="false" />
      <excludeFolder url="file://$MODULE_DIR$/.sfdx" />
      <excludeFolder url="file://$MODULE_DIR$/.sf" />
    </content>
    <orderEntry type="jdk" jdkName="IlluminatedCloud (sfdc-org-4/mmscratch03)" jdkType="IlluminatedCloud" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
</module>

To get everything resolved, I have repeat the above steps (clicking “Resolve” twice) for each of our other 28 modules. Since this is tedious (and since I like writing little tools to solve common problems), I wrote a python script that does the following for each module:

  • sets the defaultusername (if not already set)
  • via a series of steps, transforms the .iml file from the initial state to something nearly identical to the final state just above.

Desired behavior

The desired behavior here is to be able to accomplish all of this with basically a single step. Here are a couple of ways that might work.

  1. Keep things as they are in the project create wizard, except at the end after the project is created, automatically resolve what can be done automatically (excluded folders, Illuminated Cloud facet), and ensure that in the initial project state, the “Configure Project” dialog is populated with all modules. So when I click “Resolve” on a module or select “Configure Project” from the menu, I can select a Connection for a module, and get the prompt allowing me to choose to apply the Connection to all modules. Having selected “All”, the Connection, defaultusername, and associated SDK should be set for each module. Then when the project reloads after "Rebuild Caches and Indices", all modules should pass validation.
  2. I’m not sure if it’s possible to do with the “Project from Existing Sources…” flow, but another option would be to add a configuration step to that wizard before it completes. E.g., allow the user to configure a Connection, then show the “Configure Project” dialog with all modules populated, and allow the user to configure Connections (optionally choosing to apply a single Connection to all modules). The once the wizard completes and the project opens, everything should pass validation.

Comments (3)

  1. Scott Wells repo owner

    Mark, I'm going to resolve this one as there's another one from you that remains open asking for a stanadalone example of such a monorepo -- even with just a few stubbed files -- that exhibits the behaviors you're seeing against which I could try to corral things into desired shape (or minimally see what's going on). Let's use that one for further work on all of the monorepo-related behaviors.

  2. Log in to comment