-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Properly report HasLoggedErrors when converting errors into warnings #6912
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
Conversation
…errors when logging an error
IBuildEngine be = host.TaskInstance.BuildEngine; | ||
if (taskReturned && !taskResult && !taskLoggingContext.HasLoggedErrors && (be is TaskHost th ? th.BuildRequestsSucceeded : false) && (be is IBuildEngine7 be7 ? !be7.AllowFailureWithoutError : true)) | ||
{ | ||
if (_continueOnError == ContinueOnError.WarnAndContinue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not log a warning here? The idea was to convert the error into a warning, not to ignore it completely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The message is redundant in the case that the error was turned into the warning. Though it's worth noting that this hides a real issue where a task sets WarnAndContinue but truly doesn't log an error and returns false. Need to think about this some more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In practice, this says that if ContinueOnError is set, we don't log MSB4181, period, no matter what they did. HasLoggedErrors can (and should) be set if they tried to log an error but converted it into a warning; a lot of tasks return !HasLoggedErrors anyway. I don't feel at all bad about logging two warnings for a poorly-constructed task, but it is bad to not log anything when a task returns false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading this = 💡
Is the fix here really just...making sure RemoveDir returns !HasLoggedErrors? It straight up returns whether it actually deleted the file 🤦♂️
In the implementation of RemoveDir, it returns true or false based on whether or not it actually deleted the directory. However we want our typical task to return true as long as it successfully did something, otherwise it logs an error and reports whether it did. The issue with RemoveDir is it doesn't follow that structure. I think we need to change the logic of how RemoveDir works and add an Output parameter similar to copy's "DidActuallyWriteAFile".
RemoveDir for reference: https://github.com/dotnet/msbuild/blob/main/src/Tasks/RemoveDir.cs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is probably a good idea to change RemoveDir to use the !Log.HasLoggedErrors
pattern that we recommend. But I'm not sure it's wrong to just never log this malformed-task error in the presence of ContinueOnErrors. It is definitely wrong to report it when the task tried to log an error but was prevented.
I agree that the other change in this PR is the critical one. IIRC when we were talking about this I wanted to do this as well but I can't remember exactly why.
Let's do this: please add a new test task (or find a configuration that does this): ReturnFailureAfterLoggingErrorTask
, and add a test for it (doesn't log the supplemental error when logging an error that gets converted). That should fail against main
and pass with the TaskHost change alone. And maybe that's sufficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't already have it, I think it would also be nice to have a separate task that does not attempt to log an error but returns false, then verify that with ContinueOnError.WarnAndContinue, MSB4181 is still displayed, just as a warning.
_taskLoggingContext.LoggingService.LogBuildEvent(e); | ||
_taskLoggingContext.HasLoggedErrors = true; | ||
} | ||
_taskLoggingContext.HasLoggedErrors = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this fail the build? If someone want to "WarnAndContinue," we probably shouldn't, but this does seem like the change that would prevent 4181.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: spacing.
Co-authored-by: Forgind <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC there was a request for a new test scenario, right?
_taskLoggingContext.LoggingService.LogBuildEvent(e); | ||
_taskLoggingContext.HasLoggedErrors = true; | ||
} | ||
_taskLoggingContext.HasLoggedErrors = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: spacing.
@rainersigwald Fixed. Added the deleted test back and a new test to ensure:
|
53bc1a3
to
a055191
Compare
Fixes #6275
Context
When a task logs an error, its logging helper properly realizes that it logged an error. The overall build, however, converts that error into a warning. This leads to very confusing scenarios where a task can return "I logged an error" that the TaskBuilder recognizes, but doesn't see that an error was logged because it was turned into a warning.
Changes Made
When a taskhost logs an error, even if it was converted into a warning, it understands that an error was logged but does not fail the build.
Testing
Notes