AffectedModuleDetector icon indicating copy to clipboard operation
AffectedModuleDetector copied to clipboard

AffectedModuleDetector.isProjectAffected doss not work correctly on windows

Open mrguamos opened this issue 5 years ago • 9 comments

Noob question, how do I use the api? I want to build (not test) affected modules only.

mrguamos avatar Dec 04 '20 08:12 mrguamos

Can you give me an example of your use case. I don't think compilation avoidance is possible. Consider the following 2 examples.

Make a change in a base module - app module gets affected by the change and you'll need to compile app and base

Make a change in app module - app module will need to compile base module since you cannot compile only app module.

Let me know your use case. I might have missed something

digitalbuddha avatar Dec 04 '20 14:12 digitalbuddha

Note, in the case of changing app module, you won't need to recompile the base module if it's previously been compiled and is cached. Gradle will do this by default, so no need to rely on AffectedModuleDetector for that.

wclausen avatar Dec 04 '20 14:12 wclausen

I have a multi module java project and jenkins for CI

parent(build) ——common lib ——app1 ——app2 ——app3

Each apps can be built and published(docker image) separately. Is it possible to run gradle tasks for affected modules only?

For ex i made changes from app1. task should only apply to app1

Note: I always run tasks with “clean” task.

mrguamos avatar Dec 05 '20 20:12 mrguamos

I think managed to make it work using this block

task affectedModule(dependsOn: 'build') {
     println("Is ${project.name} Affected? : "+ 
     com.dropbox.affectedmoduledetector.AffectedModuleDetector.isProjectAffected(project))
}

but isProjectAffected always returns false.

output log result

[INFO] [amd] Couldn't find containing project for filesapp1/src/main/resources/application.properties
. Adding to unknownFiles.
[INFO] [amd] checking whether I should include :commons and my answer is false
[INFO] [amd] checking whether I should include :app1 and my answer is false
[INFO] [amd] checking whether I should include :app2 and my answer is false

Update:

I tried it on my MAC and it worked. I think it has something to do with File.separatorChar on Windows OS

mrguamos avatar Dec 07 '20 08:12 mrguamos

Oh interesting. Any chance you have a reproducible sample to share?

digitalbuddha avatar Dec 08 '20 14:12 digitalbuddha

Thanks for the report @materia2021! We use Mac and Linux here, so you may be the first to try it on a Windows machine :)

We'd gladly review a PR if you have time to submit a change.

chris-mitchell avatar Dec 10 '20 17:12 chris-mitchell

I stumbled upon this issue and here's what I noticed, hopefully this is useful in diagnosing the issue.

Apologies for the poor redaction but hopefully this gives you enough information to see the file separator character mismatch.

image

I'm on Windows and the Java File.separator character is being returned as "\". Which makes sense for Windows. However val sections = filePath.split(File.separatorChar) is then not going to split the filePath into multiple sections - only a single one. This appears to place the affected file in a list of unknown files and as a result the appropriate Gradle project is not considered in scope.

If I manually change the filePath variable whilst debugging (F2) and swap "/" for "\" (or really "\\" because you have to escape backlashes.... sigh) then I get the correct number of sections.

image

It still doesn't work still but what is interesting is that the init { } block of ProjectGraph also has a File.separator reference to do something similar with the relativePath: val sections = relativePath.split(File.separatorChar). Here the relativePath looks correct without any extra debug fiddling from me.

I got to the stage where Node::find wasn't returning anything (well it was returning null) but I got a bit lost from there 🤕 .

mezpahlan avatar Sep 02 '21 15:09 mezpahlan

A bit more debugging leads me to believe that on Windows (well at least mine and @mrguamos 's machines) there is a mismatch between what Gradle is spitting out in terms of file paths and what the Git client is.

image

RealCommandRunner::executeAndParse looks like it is is trying sanitise the output of the execute(command) by removing the line separator. However as you can see the line separator for my system is being returned as "\r\n" but such a character doesn't exist in the output from Git. Instead there is a line separator that looks like "\n".

So I'm thinking that whilst Gradle and the JVM is correctly returning Windows platform constants, Git is returning the Unix like ones only....... 🤔 .

Edit: At least for the above case this can be worked around by doing this:

val normalisedLineEnd = "\n"
execute(command).replace(System.lineSeparator(), normalisedLineEnd).split(normalisedLineEnd).filterNot { it.isEmpty() }

But there's probably a lot more than just this to investigate. How would I go about contributing to the repo? The version of AMD I am using is 0.1.2 but I don't see the same sources in main.

mezpahlan avatar Sep 02 '21 16:09 mezpahlan

Just to let you know, I'm working on a patch for this 😃

mezpahlan avatar Sep 05 '21 06:09 mezpahlan

This should probably be closed now after we have merged #172 :+1:

mezpahlan avatar Mar 03 '23 14:03 mezpahlan