node-gradle / gradle-node-plugin

Gradle plugin for integrating NodeJS in your build. :rocket:
Apache License 2.0
601 stars 117 forks source link

You can't pass dynamic environment to npm run #242

Open kicktipp opened 2 years ago

kicktipp commented 2 years ago

I know I can add environment variables like this:

task verify(type: NpmTask) {
    environment = ['CYPRESS_BASE_URL' : "http://localhost:9999"]
    args = ['run', 'verify']
}

But in my case the environment variable is only set later on from a custom plugin called "backendServer". So I tried to add environment in doFirst:

verify.doFirst {
    def randomPort = backendServer.getLocalPort()
    environment = ['CYPRESS_BASE_URL' : "http://localhost:" + randomPort]
}

But this does not work as environment is immutable.

deepy commented 2 years ago

environment when set is a MapProperty so in the case of doFirst environment.put('CYPRESS_BASE_URL', 'http://localhost:" + randomPort] might work better.

Or if you can turn the randomPort part into a provider instead then it should be resolved at the right time and you shouldn't need doFirst

kicktipp commented 2 years ago

Using environment.put does not help as "'environment' is final and cannot be changed any further."

I will try the provider option.

deepy commented 2 years ago

https://docs.gradle.org/current/userguide/build_services.html might be of interest as well

kicktipp commented 2 years ago

I implemented the provider option for me. It works fine. But the build service looks promising too. Thank you so much.

uwolfer commented 2 years ago

@kicktipp: I would appreciate if you could share the relevant change required for getting it working with a provider in your case.

kicktipp commented 2 years ago

I used a provider like this:

task verify(type: NpxTask) {
    inputs.files(fileTree('tests/e2e'))
    command = 'cypress'
    args = ['run', '--browser', 'chrome']
    environment = ['CYPRESS_BASE_URL' : project(':backend').backendServer.baseUrl.get()]
}

and in my gradle java plugin:

@NonNullApi
public abstract class BackendServerPluginExtension {
     ...
    @Internal
    final Provider<Integer> runningPort = getPort().map(this::resolvePort);

    @Internal
    final Provider<String> baseUrl = getPort().map(this::baseUrl);

If you can't figure it out, I can send you the complete code by mail.