Skip to content

Commit 019759a

Browse files
authored
chore: Improve error reporting in ResolveSqlProjAndInputs for MSBuild Full Framework failures (#35)
1 parent 7c99aaa commit 019759a

2 files changed

Lines changed: 103 additions & 3 deletions

File tree

src/JD.Efcpt.Build.Tasks/ResolveSqlProjAndInputs.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,12 @@ private bool ExecuteCore(TaskExecutionContext ctx)
300300
{
301301
var log = new BuildLog(ctx.Logger, "");
302302

303+
// Log runtime context for troubleshooting
304+
var runtime = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription;
305+
log.Detail($"MSBuild Runtime: {runtime}");
306+
log.Detail($"ProjectReferences Count: {ProjectReferences?.Length ?? 0}");
307+
log.Detail($"SolutionPath: {SolutionPath}");
308+
303309
Directory.CreateDirectory(OutputDir);
304310

305311
var resolutionState = BuildResolutionState(log);
@@ -356,8 +362,13 @@ private TargetContext DetermineMode(BuildLog log)
356362
WarnIfAutoDiscoveredConnectionStringExists(log);
357363
return new(false, "", sqlProjPath);
358364
}
359-
catch
365+
catch (Exception ex)
360366
{
367+
// Log detailed exception information to help users diagnose SQL project resolution issues.
368+
// This is intentionally more verbose than other catch blocks in this file because this
369+
// specific failure point is commonly reported by users and requires diagnostic context.
370+
log.Warn($"SQL project detection failed: {ex.Message}");
371+
log.Detail($"Exception details: {ex}");
361372
return null;
362373
}
363374
}
@@ -427,10 +438,12 @@ private ResolutionState BuildResolutionState(BuildLog log)
427438
.Require(state
428439
=> state.UseConnectionStringMode
429440
? string.IsNullOrWhiteSpace(state.ConnectionString)
430-
? "Connection string resolution failed"
441+
? "Connection string resolution failed. No connection string could be resolved from configuration."
431442
: null
432443
: string.IsNullOrWhiteSpace(state.SqlProjPath)
433-
? "SqlProj resolution failed"
444+
? "SqlProj resolution failed. No SQL project reference found. " +
445+
"Add a .sqlproj ProjectReference, set EfcptSqlProj property, or provide a connection string via " +
446+
"EfcptConnectionString/appsettings.json/app.config. Check build output for detailed error messages."
434447
: null)
435448
.Build(state => state);
436449
}

tests/JD.Efcpt.Build.Tests/ResolveSqlProjAndInputsTests.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,4 +698,91 @@ private static TaskResult ExecuteTaskSqlProjWithAutoDiscovery(SetupState setup)
698698
var success = task.Execute();
699699
return new TaskResult(setup, task, success);
700700
}
701+
702+
// ========== Error Reporting Tests ==========
703+
704+
[Scenario("Provides detailed error message when no SQL project is found")]
705+
[Fact]
706+
public async Task Provides_detailed_error_message_when_no_sqlproj()
707+
{
708+
await Given("project with no sqlproj reference", SetupNoSqlProjReference)
709+
.When("execute task", ExecuteTaskNoSqlProjReference)
710+
.Then("task fails", r => !r.Success)
711+
.And("errors are logged", r => r.Setup.Engine.Errors.Count > 0)
712+
.And("error contains helpful guidance", r =>
713+
r.Setup.Engine.Errors.Any(e => e.Message?.Contains("No SQL project reference found") == true) &&
714+
r.Setup.Engine.Errors.Any(e => e.Message?.Contains("Add a .sqlproj ProjectReference") == true ||
715+
e.Message?.Contains("EfcptConnectionString") == true))
716+
.Finally(r => r.Setup.Folder.Dispose())
717+
.AssertPassed();
718+
}
719+
720+
[Scenario("Logs warning with exception details when SQL project detection fails")]
721+
[Fact]
722+
public async Task Logs_warning_with_exception_details_on_detection_failure()
723+
{
724+
await Given("project with invalid solution path", SetupInvalidSolutionPath)
725+
.When("execute task with solution scan", ExecuteTaskInvalidSolutionPath)
726+
.Then("task fails", r => !r.Success)
727+
.And("warnings logged about detection failure", r =>
728+
r.Setup.Engine.Warnings.Any(w => w.Message?.Contains("SQL project detection failed") == true))
729+
.Finally(r => r.Setup.Folder.Dispose())
730+
.AssertPassed();
731+
}
732+
733+
private static SetupState SetupNoSqlProjReference()
734+
{
735+
var folder = new TestFolder();
736+
var projectDir = folder.CreateDir("src");
737+
var csproj = folder.WriteFile("src/App.csproj", "<Project />");
738+
739+
var engine = new TestBuildEngine();
740+
return new SetupState(folder, engine, projectDir, csproj, "", "", "", "", "");
741+
}
742+
743+
private static TaskResult ExecuteTaskNoSqlProjReference(SetupState setup)
744+
{
745+
var task = new ResolveSqlProjAndInputs
746+
{
747+
BuildEngine = setup.Engine,
748+
ProjectFullPath = Path.Combine(setup.ProjectDir, "App.csproj"),
749+
ProjectDirectory = setup.ProjectDir,
750+
Configuration = "Debug",
751+
ProjectReferences = [], // No SQL project references
752+
OutputDir = Path.Combine(setup.ProjectDir, "obj", "efcpt"),
753+
DefaultsRoot = TestPaths.DefaultsRoot
754+
};
755+
756+
var success = task.Execute();
757+
return new TaskResult(setup, task, success);
758+
}
759+
760+
private static SetupState SetupInvalidSolutionPath()
761+
{
762+
var folder = new TestFolder();
763+
var projectDir = folder.CreateDir("src");
764+
var csproj = folder.WriteFile("src/App.csproj", "<Project />");
765+
766+
var engine = new TestBuildEngine();
767+
return new SetupState(folder, engine, projectDir, csproj, "", "", "", "", "");
768+
}
769+
770+
private static TaskResult ExecuteTaskInvalidSolutionPath(SetupState setup)
771+
{
772+
var task = new ResolveSqlProjAndInputs
773+
{
774+
BuildEngine = setup.Engine,
775+
ProjectFullPath = Path.Combine(setup.ProjectDir, "App.csproj"),
776+
ProjectDirectory = setup.ProjectDir,
777+
Configuration = "Debug",
778+
ProjectReferences = [],
779+
OutputDir = Path.Combine(setup.ProjectDir, "obj", "efcpt"),
780+
SolutionPath = Path.Combine(setup.ProjectDir, "NonExistent.sln"), // Invalid path
781+
ProbeSolutionDir = "true",
782+
DefaultsRoot = TestPaths.DefaultsRoot
783+
};
784+
785+
var success = task.Execute();
786+
return new TaskResult(setup, task, success);
787+
}
701788
}

0 commit comments

Comments
 (0)