Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Serve Executor Doesn't Respect Configurations #159

Open
tommyc38 opened this issue Oct 14, 2023 · 6 comments
Open

Custom Serve Executor Doesn't Respect Configurations #159

tommyc38 opened this issue Oct 14, 2023 · 6 comments
Labels
enhancement New feature or request

Comments

@tommyc38
Copy link

I have configurations for serve, watch, and the firebase targets. My configs for each are dev, prod, and local. The problem I am facing is that the serve target/executor doesn't respect any configurations under it. Is this by design or a bug?

@simondotm
Copy link
Owner

Hi @tommyc38 , thanks for reporting this.
It was tricky adding the custom executor as I imagined folks would inevitably customise some of their projects and so compatibility was hard to predict.

Could you share an example of your project.json with your extra configs here? That way I can look at making the executor more compatible.

@tommyc38
Copy link
Author

@simondotm below is a contrived example that resembles my project. Please don't hesitate to ask any questions and thank you for writing this lib!

Project Structure:

workspace/
  firebase/
  firebase-functions/
  ui/
    env/
      - local.ts
      - dev.ts
      - prod.ts
  - firebase.dev.json
  - firebase.local.json
  - firebase.json
  - .firebaserc
// firebase/project.json
{
  ...

  "firebase": {
    "executor": "nx:run-commands",
    "options": {
      "command": "firebase --config=firebase.json --project=dev"
    },
    // I want my dev and prod environments to be the same in terms of everything in the firebase project.
    // However, when I run the emulator I need to serve the app from their respective build folders
    // (e.g. dist/ui (prod), dist/ui-local, dist/ui-dev) so all of the firebase.<env>.json are exactly the same
    // except for the hosting.public property pointing to the aforementioned dist directories.
    "configurations": {
      "prod": {
        "command": "firebase --config=firebase.json --project=prod"
      },
      "dev": {
        "command": "firebase --config=firebase.dev.json --project=dev"
      },
      "local": {
        "command": "firebase --config=firebase.local.json --project=dev"
      }
    },
  },
  "watch": {
    "executor": "nx:run-commands",
    "options": {
      "command": "nx run-many --targets=build --projects=tag:firebase:dep:firebase --parallel=100 --watch"
    },
    // Both projects, ui and firebase-functions, have the tag "firebase:dep:firebase" so they are both built in watch mode
    "configurations": {
      "prod": {
        "command": "nx run-many --targets=build:prod --projects=tag:firebase:dep:firebase --parallel=100 --watch"
      },
      "dev": {
        "command": "nx run-many --targets=build:dev --projects=tag:firebase:dep:firebase --parallel=100 --watch"
      },
      "local": {
        "command": "nx run-many --targets=build:local --projects=tag:firebase:dep:firebase --parallel=100 --watch"
      }
    }
  },
  "emulate": {
    "executor": "nx:run-commands",
    "options": {
      "commands": [
        "nx run firebase:killports",
        "nx run firebase:firebase emulators:start --import=firebase/.emulators --export-on-exit"
      ],
      "parallel": false
    },
    "configurations": {
      "prod": {
        "commands": [
          "nx run firebase:killports",
          "nx run firebase:firebase:prod emulators:start --import=firebase/.emulators --export-on-exit"
        ]
      },
      "dev": {
        "commands": [
          "nx run firebase:killports",
          "nx run firebase:firebase:dev emulators:start --import=firebase/.emulators --export-on-exit"
        ]
      },
      "local": {
        "commands": [
          "nx run firebase:killports",
          "nx run firebase:firebase:local emulators:start --import=firebase/.emulators --export-on-exit"
        ]
      }
    }
  },
  "serve": {
    "executor": "@simondotm/nx-firebase:serve",
    "options": {
      "commands": [
        "nx run firebase:watch",
        "nx run firebase:emulate"
      ]
    },
    "configurations": {
      "prod": {
        "commands": [
          "nx run firebase:watch:prod",
          "nx run firebase:emulate:prod"
        ]
      },
      "dev": {
        "commands": [
          "nx run firebase:watch:dev",
          "nx run firebase:emulate:dev"
        ]
      },
      "local": {
        "commands": [
          "nx run firebase:watch:local",
          "nx run firebase:emulate:local"
        ]
      }
    }
  },
}

@tommyc38
Copy link
Author

tommyc38 commented Oct 14, 2023

The problem is this command:

function getCommandFromTarget(
  project: ProjectConfiguration,
  targetName: ValidTarget,
  commandGrep: string,
) {
  const target = project.targets[targetName] as NxRunCommandsTargetConfiguration
  if (!target) {
    throw new Error(
      `Could not find target '${targetName}' in project '${project.name}'`,
    )
  }
  const commands: string[] = [
    ...(target.options.command ? [target.options.command] : []),
    ...(target.options.commands ? target.options.commands : []),
  ].filter((cmd) => cmd.includes(commandGrep))

  if (commands.length === 0) {
    throw new Error(
      `Could not find a command in target '${targetName}' that matches '${commandGrep}'`,
    )
  }

  if (commands.length !== 1) {
    logger.warn(
      `Found multiple commands in target '${targetName}' that match '${commandGrep}', using first match`,
    )
  }
  return commands[0]
}

Then you call like this where you are effectively hard coding the target and the command in:

  const watchCommand = getCommandFromTarget(
      project,
      'watch',
      'nx run-many --targets=build',
    )

I've just briefly looked at the code but it looks like we need to call the actual ExecutiveContext properties (e.g. target and target configuration) rather than the hard coded target and target options.

Here is a link to the ExecutorContext Interface.

@simondotm simondotm added the enhancement New feature or request label Oct 15, 2023
@simondotm
Copy link
Owner

@tommyc38 I'll take a look at this when I get a spare moment over the next week or so. 👍

@tommyc38
Copy link
Author

@simondotm have you had a chance to take a look at this?

@simondotm
Copy link
Owner

@tommyc38 not yet unfortunately, slammed with work atm. On my radar though

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants