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

Allow void entry point when calling BuildRunner.Execute. #69

Merged
merged 2 commits into from
Oct 7, 2024

Conversation

adampoit
Copy link
Contributor

@adampoit adampoit commented Oct 7, 2024

There are two primary motivations for this change:

  1. Enable unit testing Faithlife.Build in this repository. It is likely that we'd want to have test coverage for code in this repository, but disallowing void return entry points makes this challenging. By allowing void entry points we can write rich unit tests that validate behavior and prevent regressions.
  2. Enable unit testing projects that depend on Faithlife.Build. It is not uncommon for us to ship common targets in a NuGet package that can be consumed by various projects. It would be very nice for us to be able to test those targets in a similar fashion. This is why I have chosen to publicly expose BuildRunnerSettings, instead of making it internal only.

I'm definitely open to feedback on whether this is the correct approach and API design.

/// <returns>The exit code for the build.</returns>
public static int Execute(string[] args, Action<BuildApp> initialize) =>
ExecuteAsync(args, initialize).GetAwaiter().GetResult();
public static int Execute(string[] args, Action<BuildApp> initialize, BuildRunnerSettings? settings = null) =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically a binary breaking change. Would we prefer to add method overloads, or perhaps a method with a different name to allow void entry point execution?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the only use case here is unit testing, consider an internal overload.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid the binary breaking change, yes.

I don't mind BuildRunnerSettings if we want to maintain both behaviors.

@adampoit adampoit requested a review from ejball October 7, 2024 20:07
ArgumentNullException.ThrowIfNull(args);
ArgumentNullException.ThrowIfNull(initialize);

if (Assembly.GetEntryAssembly()?.EntryPoint?.ReturnType == typeof(void))
if (!settings.AllowVoidEntrypoint && Assembly.GetEntryAssembly()?.EntryPoint?.ReturnType == typeof(void))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should just delete this surprising behavior. I forgot I added it. Long term, an analyzer would be a better solution to the problem of forgetting to return the exit code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleting the behavior would certainly remove any API changes and allow more flexibility in other repositories. If we're comfortable with that, that would likely be my preferred direction.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine by me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, I'm going to drop the API changes from this proposal.

/// <returns>The exit code for the build.</returns>
public static int Execute(string[] args, Action<BuildApp> initialize) =>
ExecuteAsync(args, initialize).GetAwaiter().GetResult();
public static int Execute(string[] args, Action<BuildApp> initialize, BuildRunnerSettings? settings = null) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid the binary breaking change, yes.

I don't mind BuildRunnerSettings if we want to maintain both behaviors.

public void FailsOnMissingTarget()
{
using var error = new StringWriter();
Console.SetError(error);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love the non-parallelizable tests, but I guess we don't have a choice.

I'm surprised they aren't being run in parallel, but maybe that's not the default.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option would be to pass stdout/stderr streams via BuildRunnerSettings and have it prefer those over Console if they're present.

Copy link
Contributor Author

@adampoit adampoit Oct 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to this, there is no parallel execution in NUnit by default: https://docs.nunit.org/articles/nunit/writing-tests/attributes/parallelizable.html

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That could work for direct Faithlife.Build output, but not for the apps that targets run, which could be confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing as parallel execution is not the default in NUnit, I am going to say the Console redirection is fine as is.

Remove API changes to configure it, since it was surprising behavior.
@adampoit adampoit merged commit 480a139 into Faithlife:master Oct 7, 2024
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants