dotnet-affected icon indicating copy to clipboard operation
dotnet-affected copied to clipboard

Ability to distinguish between changed and affected projects

Open AlexeyRaga opened this issue 1 year ago • 9 comments

Currently the tool helpfully reports all the changed or affected projects, both in .proj and in json. One thing that is missing is to be able to know what project have actually changed and what are affected by the change.

Reason

This information is extremely useful in certain CI/CD scenarious. For example, when we want to automatically bump the major version for the project that were actually changed, but the affected projects would probably get only a patch version bump.

Possible implementation

I see that internally the tool does have all this information, and I think that it'd be beneficial to propagate it into the output.

Json output can contain a new State field:

[
  {
    "Name": "Project1",
    "FilePath": "/path/to/project1.csproj",
    "State": "Changed"
  },
  {
    "Name": "Project2",
    "FilePath": "/path/to/project2.csproj",
    "State": "Affected"
  },
]

And for MSBuild we can have two item groups (Changed and Affected):

<Project Sdk="Microsoft.Build.Traversal/3.0.3">
  <ItemGroup Label="Changed">
    <ProjectReference Include="/path/to/project1.csproj" />
  </ItemGroup>
  <ItemGroup Label="Affected">
    <ProjectReference Include="/path/to/project2.csproj" />
  </ItemGroup>
</Project>

AlexeyRaga avatar Jun 14 '23 03:06 AlexeyRaga

Hi @AlexeyRaga I agree with the proposal and I think being able to differentiate from Changed vs Affected projects on the output is useful :+1:

Would you be willing to give it a go implementing it?

leonardochaia avatar Jun 14 '23 12:06 leonardochaia

I may give it a try. Let's see what I can come up with. My first thought would be to add ProjectStatus into IProjectInfo and start from there...

AlexeyRaga avatar Jun 14 '23 12:06 AlexeyRaga

Hmmm, what do you think if we modify the IOutputFormatter.Execute to receive both lists of changed and affected projects?

I think that would be easier to implement, since this is only a formatting concern instead of the affected core logic. The core logic already keep two separate list for affected and changed, but they are joined together just for the output formatting part:

https://github.com/leonardochaia/dotnet-affected/blob/206f946bcca1e0886f2bc1f77b675301281b44d7/src/dotnet-affected/Commands/AffectedRootCommand.cs#L48-L63

So I think it would be best for the IOutputFormatterExecutor and its IOutputFormatters to receive both lists and they can decide how to output them.

In the case of the JSON formatter, it needs to compose the output you've mentioned in your issue, so we need to work a bit in the output data structure (new class with the Changed state also implementing IProjectInfo perhaps?)

The Traversal formatter having the two list separate would be easier to achieve the proposal

And we also need to define what/how to do the text formatter, but I haven't thought about it yet.

Let me know if you hit a road block and we'll see what we can do, feel free to ask :+1:

leonardochaia avatar Jun 14 '23 13:06 leonardochaia

Thanks for the suggestion, I will see into it! I will probably need some help at some point because it looks like the project is a bit Windows-oriented and I have some troubles with running it on MacOS, but I'll have a look if I can work it around (or can rely on CI for QA)

AlexeyRaga avatar Jun 14 '23 22:06 AlexeyRaga

Hi @AlexeyRaga , it should work on MacOS, we actually have CI tests that cover that.

I personally develop on Linux. Let me know if I can be of any help :)

leonardochaia avatar Jun 14 '23 22:06 leonardochaia

Sorry @AlexeyRaga did not mean to close the issue. Fat fingers.

leonardochaia avatar Jun 15 '23 02:06 leonardochaia

Hi @AlexeyRaga, I was thinking about this last night and played a bit with the code. I still don't have a functioning prototype but wanted to leave some notes here:

dotnet-affected changes to existing output formatters:

  1. traversal (single file, separated by ItemGroup metadata)
  2. json (single file, separated by project object property)
  3. text (single file, no separation) (no changes)

dotnet-affected new formatters:

  1. json-split (affected.json, changed.json, excluded.json)
  2. traversal-split (affected.proj, changed.proj, excluded.proj)
  3. text-split (affected.txt, changed.txt, excluded.txt)

Some notes

  1. Not sure if the split should generate the excluded.json or not.
  2. Should we prefix all files with a well-known prefix/suffix for easier deletion? (rm *-affected.*)

leonardochaia avatar Jun 16 '23 12:06 leonardochaia

Hi, good ideas!

I am not sure whether excluded* files would be useful, but why not have them for completeness? I guess, it won't be hard to generate them.

I like the idea about prefix/suffix, too (except that I would use . as a separator and not -).

Common suffix is nice for deletion, because it can be just rm *.affected.json Common prefix is nice for files to be displayed together in a files list in IDE or ls, etc.

Maybe both them? Something like...

split-changes.affected.json
split-affected.affected.json
split-excluded.affected.json

Or, maybe, when split format is in play, we treat output-name as a directory and generate 3 files (changes.json, affected.json, excluded.json) in such a folder? It won't "pollute" the files list this way, and it would be easy to gitignore/remove...

AlexeyRaga avatar Jun 16 '23 14:06 AlexeyRaga