diff --git a/demo/apps/webapi/NxDotnet.Test.Webapi.csproj b/demo/apps/webapi/NxDotnet.Test.Webapi.csproj index 7e997117..7a2b77bb 100644 --- a/demo/apps/webapi/NxDotnet.Test.Webapi.csproj +++ b/demo/apps/webapi/NxDotnet.Test.Webapi.csproj @@ -1,6 +1,6 @@ - net6.0 + net7.0 enable enable diff --git a/demo/apps/webapi/Program.cs b/demo/apps/webapi/Program.cs index 16dcb223..d2b07bba 100644 --- a/demo/apps/webapi/Program.cs +++ b/demo/apps/webapi/Program.cs @@ -3,7 +3,7 @@ // Add services to the container. builder.Services.AddControllers(); -// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +// Learn more about configuring Swagger at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); @@ -11,8 +11,8 @@ // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) -{ - app.UseSwagger(); +{ + app.UseSwagger(); app.UseSwaggerUI(); } diff --git a/demo/libs/csharp-models/NxDotnet.Demo.Libs.CsharpModels.csproj b/demo/libs/csharp-models/NxDotnet.Demo.Libs.CsharpModels.csproj index bafd05b1..4658cbfe 100644 --- a/demo/libs/csharp-models/NxDotnet.Demo.Libs.CsharpModels.csproj +++ b/demo/libs/csharp-models/NxDotnet.Demo.Libs.CsharpModels.csproj @@ -1,7 +1,7 @@ - net6.0 + net7.0 enable enable diff --git a/global.json b/global.json deleted file mode 100644 index ca480f0d..00000000 --- a/global.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "sdk": { - "rollForward": "latestMinor", - "version": "6.0.400" - } -} diff --git a/packages/core/src/executors/build/executor.ts b/packages/core/src/executors/build/executor.ts index e410583d..9a3a2604 100644 --- a/packages/core/src/executors/build/executor.ts +++ b/packages/core/src/executors/build/executor.ts @@ -1,11 +1,17 @@ -import { ExecutorContext, workspaceRoot } from '@nrwl/devkit'; +import { + ExecutorContext, + ProjectConfiguration, + workspaceRoot, +} from '@nrwl/devkit'; -import { resolve } from 'path'; +import { rmSync, statSync } from 'fs'; +import { join, resolve } from 'path'; import { DotNetClient, dotnetFactory } from '@nx-dotnet/dotnet'; import { getExecutedProjectConfiguration, getProjectFileForNxProject, + inlineNxTokens, } from '@nx-dotnet/utils'; import { BuildExecutorSchema } from './schema'; @@ -16,6 +22,8 @@ export default async function runExecutor( dotnetClient: DotNetClient = new DotNetClient(dotnetFactory()), ) { const nxProjectConfiguration = getExecutedProjectConfiguration(context); + removeOldArtifacts(context, nxProjectConfiguration); + dotnetClient.cwd = resolve(workspaceRoot, nxProjectConfiguration.root); dotnetClient.printSdkVersion(); const projectFilePath = resolve( @@ -35,3 +43,46 @@ export default async function runExecutor( success: true, }; } + +function removeOldArtifacts( + context: ExecutorContext, + projectConfiguration: ProjectConfiguration, +) { + const outputs = context.target?.outputs?.map((output) => + join(context.root, inlineNxTokens(output, projectConfiguration)), + ); + if ( + !outputs && + Object.values(context.nxJsonConfiguration?.tasksRunnerOptions ?? {}).some( + (runnerOptions) => + runnerOptions.options?.cacheableOperations?.includes( + context.targetName, + ), + ) + ) { + throw new Error(`[nx-dotnet] ${context.projectGraph}:${context.targetName} is cacheable, but has no outputs listed. + +This will result in cache hits not retrieving build artifacts, only terminal outputs. + +See: https://nx.dev/reference/project-configuration#outputs`); + } + for (const output of outputs || []) { + if ( + // No reason to clear build intermediates, just makes the resulting build command slower. + !output.includes('intermediates') && + !output.endsWith('obj') && + // Prevent exceptions from trying to rmdirSync(globPattern) + getStatsOrNull(output)?.isDirectory() + ) { + rmSync(output, { recursive: true }); + } + } +} + +function getStatsOrNull(f: string) { + try { + return statSync(f); + } catch { + return null; + } +} diff --git a/packages/core/src/generators/utils/get-path-to-startup-assembly.ts b/packages/core/src/generators/utils/get-path-to-startup-assembly.ts index 91be9f9e..c4a3b0f3 100644 --- a/packages/core/src/generators/utils/get-path-to-startup-assembly.ts +++ b/packages/core/src/generators/utils/get-path-to-startup-assembly.ts @@ -37,8 +37,8 @@ export function buildStartupAssemblyPath( /(?:\.csproj|\.vbproj|\.fsproj)$/, '.dll', ); - const foundDll = sync(`**/${dllName}`, { cwd: outputDirectory })[0]; - if (!foundDll) { + const matchingDlls = sync(`**/${dllName}`, { cwd: outputDirectory }); + if (!matchingDlls.length) { throw new Error( `[nx-dotnet] Unable to locate ${dllName} in ${relative( workspaceRoot, @@ -46,10 +46,15 @@ export function buildStartupAssemblyPath( )}`, ); } - return joinPathFragments( - outputDirectory, - sync(`**/${dllName}`, { cwd: outputDirectory })[0], - ); + if (matchingDlls.length > 1) { + throw new Error( + `[nx-dotnet] Located multiple matching dlls for ${projectName}. + +You may need to clean old build artifacts from your outputs, or manually +specify the path to the output assembly within ${project.root}/project.json.`, + ); + } + return joinPathFragments(outputDirectory, matchingDlls[0]); } function findBuildTarget( diff --git a/packages/utils/src/lib/utility-functions/workspace.ts b/packages/utils/src/lib/utility-functions/workspace.ts index 272cec31..37ac991f 100644 --- a/packages/utils/src/lib/utility-functions/workspace.ts +++ b/packages/utils/src/lib/utility-functions/workspace.ts @@ -8,6 +8,7 @@ import { } from '@nrwl/devkit'; import { readFileSync } from 'fs'; +import { NX_PREFIX } from 'nx/src/utils/logger'; import { dirname, isAbsolute, relative, resolve } from 'path'; import { XmlDocument, XmlElement } from 'xmldoc'; @@ -135,3 +136,16 @@ export function getProjectFilesForProject( function normalizePath(p: string): string { return nxNormalizePath(p).split('\\').join('/'); } + +export function inlineNxTokens(value: string, project: ProjectConfiguration) { + if (value.startsWith('{workspaceRoot}/')) { + value = value.replace(/^\{workspaceRoot\}\//, ''); + } + if (value.includes('{workspaceRoot}')) { + throw new Error( + `${NX_PREFIX} The {workspaceRoot} token is only valid at the beginning of an output.`, + ); + } + value = value.replace('{projectRoot}', project.root); + return value.replace('{projectName}', project.name as string); +}