Farfetch/garment

Garment finds incorrect project with files option when there are projects with similar names

stephan-noel opened this issue · 4 comments

Issue Report

I have two projects in my monorepo section-product and section-product-carousel. When I do garment lint - - files <workspace_root>\section\product-carousel\src\modules\product-carousel\ProductCarousel.js the actionGraph is empty and so nothing is executed.

Expected Behavior

It should return the correct project, section-product-carousel and execute the task. Both getPath and getPaths probably should be changed to make sure it only checks complete segments of the path.

Actual Behavior

I traced the problem to this method.

image

It returns section-product as the project associated with the file instead of section-product-carousel because technically they both start with the file path. When I debugged and changed it to the correct project, the task executed properly.

Steps to Reproduce the Issue

Have two projects in which the path of one is a substring of the other.

I can take this and add some unit tests for projectRegistry.

@stephan-noel Thanks for reporting! As always, help is welcomed :) But I can also try to find time soon to fix it

Hey @beshanoe no prob. Yea, sorry I haven't been having too much time lately. If you could, that would be cool 👍

Just a heads up, when this is done, there are other instances where startsWith is used that should be replaced as well. For example, it's also used in mapChangesToSubscriptions in garment.js for example, and it could potentially lead to similar problems.

@stephan-noel I've reviewed your problem and found out that garment takes first project from schema and tries to run a task. It seems there is no lint task in your "root" project. That's why lint task is not executed.

Here is the schema I was testing

{
  "$schema": "./node_modules/@garment/workspace/schemas/config.schema.json",
  "presets": {},
  "projects": {
    "root": {
      "path": "packages/root",
      "tasks": {
        "build": {
          "input": "{{projectDir}}/**/*.*",
          "runner": "ts",
        }
      }
    },
    "package-a": {
      "path": "packages/root/src/packages/package-a",
      "tasks": {
        "lint": {
          "input": "{{projectDir}}/**/*.*",
          "runner": "eslint"
        }
      }
    }
  },
  "schematics": []
}

And after running garment lint /path/to/package-a/index.js garment takes root project first and doesn't run lint task as it doesn't exist in the root project definition.

Probably, you want to have different configurations for lint task in "child" projects and I have two solutions for you.

  1. Reorder your project definition in garment.json as it is shown below
{
  "$schema": "./node_modules/@garment/workspace/schemas/config.schema.json",
  "presets": {},
  "projects": {
    "package-a": {
      "path": "packages/root/src/packages/package-a",
      "tasks": {
        "lint": {
          "input": "{{projectDir}}/**/*.*",
          "runner": "eslint"
        }
      }
    },
    "root": {
      "path": "packages/root",
      "tasks": {
        "build": {
          "input": "{{projectDir}}/**/*.*",
          "runner": "ts",
        }
      }
    }
  },
  "schematics": []
}
  1. Or define lint task in root project. You can also specify different configurations for different paths
{
  "$schema": "./node_modules/@garment/workspace/schemas/config.schema.json",
  "presets": {},
  "projects": {
    "root": {
      "path": "packages/root",
      "tasks": {
        "lint": [
            {
              "input": "{{projectDir}}/**/package-b/**/*.*",
              "runner": "eslint",
              "options": {
                "configFile": "{{projectDir}}/src/packages/package-b/.eslintrc.json"
              }
            },
            {
              "input": "{{projectDir}}/**/package-a/**/*.*",
              "runner": "eslint"
            }
        ]
      }
    }
  },
  "schematics": ["@garment/schematics"]
}

In the example above, there are package-a and package-b with different eslint configurations.

Please, let me know if it solves your problem