Summary
FalloutBuild.RootDirectory is resolved purely from the process's current working directory
(Constants.TryGetRootDirectoryFrom(EnvironmentInfo.WorkingDirectory)), not from the location of the
executing _build.csproj. When a repository contains a nested Fallout root (e.g. a repo root plus a
sub-directory such as SampleService/ that has its own .slnx/build project), this causes two
related problems.
Problem 1 - silent misresolution of the root when CWD is ambiguous
If the shell's working directory happens to sit inside a different, but also valid, Fallout root (e.g.
the repo root instead of the intended sub-root), RootDirectory silently resolves to that other root
instead of failing loudly. There is no validation that the resolved root actually matches the
_build.csproj that is running, so the wrong .slnx can be loaded without any warning.
Problem 2 - poor failure mode when a Solution.* project shortcut isn't found
Because the wrong solution got loaded, a [Solution(GenerateProjects = true)] generated project
shortcut (e.g. Solution.Sample_Specs) that does not exist in that solution returns null instead
of throwing a descriptive "project not found" error. The null Project is then implicitly
converted to AbsolutePath via Fallout.Solutions.Project.op_Implicit, which throws an unhelpful
NullReferenceException deep inside Fallout, with no indication of the real cause.
Repro
A repository contains Root.slnx at the repo root and Sub/Sub.slnx in a nested Fallout root
(Sub/ has its own .fallout/build project). Running the sub-project's build.ps1 (e.g.
Sub/build.ps1 RunUnitTests) from the repo root (CWD = repo root) instead of from Sub/ resolves
RootDirectory to the repo root, binds Solution.Sub_Specs against Root.slnx (which has no such
project), gets null, and crashes with NullReferenceException in
Fallout.Solutions.Project.op_Implicit when the shortcut is later used (e.g. implicitly converted to
an AbsolutePath).
Suggested fix
- Derive
RootDirectory from the location of the executing _build.csproj (or an explicit root
parameter) instead of solely from the process's current working directory, so nested Fallout roots
cannot be silently confused with each other.
- Make generated
Solution.* project shortcuts throw a clear, descriptive exception (e.g. "Project 'X'
not found in solution 'Y.slnx'") when the named project cannot be found, instead of returning null
and deferring to an opaque NullReferenceException at the point of implicit conversion to
AbsolutePath.
Workaround
In our repository we pinned the CI step's workingDirectory to the sub-project's directory before
invoking its build.ps1, so the correct Fallout root is always resolved. This avoids the symptom but
does not fix the underlying ambiguity or the unhelpful failure mode in Fallout itself.
Summary
FalloutBuild.RootDirectoryis resolved purely from the process's current working directory(
Constants.TryGetRootDirectoryFrom(EnvironmentInfo.WorkingDirectory)), not from the location of theexecuting
_build.csproj. When a repository contains a nested Fallout root (e.g. a repo root plus asub-directory such as
SampleService/that has its own.slnx/build project), this causes tworelated problems.
Problem 1 - silent misresolution of the root when CWD is ambiguous
If the shell's working directory happens to sit inside a different, but also valid, Fallout root (e.g.
the repo root instead of the intended sub-root),
RootDirectorysilently resolves to that other rootinstead of failing loudly. There is no validation that the resolved root actually matches the
_build.csprojthat is running, so the wrong.slnxcan be loaded without any warning.Problem 2 - poor failure mode when a Solution.* project shortcut isn't found
Because the wrong solution got loaded, a
[Solution(GenerateProjects = true)]generated projectshortcut (e.g.
Solution.Sample_Specs) that does not exist in that solution returnsnullinsteadof throwing a descriptive "project not found" error. The
nullProjectis then implicitlyconverted to
AbsolutePathviaFallout.Solutions.Project.op_Implicit, which throws an unhelpfulNullReferenceExceptiondeep inside Fallout, with no indication of the real cause.Repro
A repository contains
Root.slnxat the repo root andSub/Sub.slnxin a nested Fallout root(
Sub/has its own.fallout/build project). Running the sub-project'sbuild.ps1(e.g.Sub/build.ps1 RunUnitTests) from the repo root (CWD = repo root) instead of fromSub/resolvesRootDirectoryto the repo root, bindsSolution.Sub_SpecsagainstRoot.slnx(which has no suchproject), gets
null, and crashes withNullReferenceExceptioninFallout.Solutions.Project.op_Implicitwhen the shortcut is later used (e.g. implicitly converted toan
AbsolutePath).Suggested fix
RootDirectoryfrom the location of the executing_build.csproj(or an explicit rootparameter) instead of solely from the process's current working directory, so nested Fallout roots
cannot be silently confused with each other.
Solution.*project shortcuts throw a clear, descriptive exception (e.g. "Project 'X'not found in solution 'Y.slnx'") when the named project cannot be found, instead of returning
nulland deferring to an opaque
NullReferenceExceptionat the point of implicit conversion toAbsolutePath.Workaround
In our repository we pinned the CI step's
workingDirectoryto the sub-project's directory beforeinvoking its
build.ps1, so the correct Fallout root is always resolved. This avoids the symptom butdoes not fix the underlying ambiguity or the unhelpful failure mode in Fallout itself.