diff --git a/CHANGELOG.md b/CHANGELOG.md index c0e9aa01..41684330 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.18.1](https://github.com/nx-dotnet/nx-dotnet/compare/v1.18.0...v1.18.1) (2023-01-26) + +### Bug Fixes + +- **core:** build intermediates need to be captured by cache for DTE / parallel builds ([#596](https://github.com/nx-dotnet/nx-dotnet/issues/596)) ([cdea76e](https://github.com/nx-dotnet/nx-dotnet/commit/cdea76e4b52e85071d7354bf3580bac742e68353)) +- **core:** resolve startupAssembly to ensure it is always an absolute path ([#595](https://github.com/nx-dotnet/nx-dotnet/issues/595)) ([2ea2570](https://github.com/nx-dotnet/nx-dotnet/commit/2ea25704b65c0079bfc363f3d470b35bccfbca68)) + # [1.18.0](https://github.com/nx-dotnet/nx-dotnet/compare/v1.17.0...v1.18.0) (2023-01-17) ### Features diff --git a/Directory.Build.props b/Directory.Build.props index 47a2f8c2..9fef819e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,6 +9,8 @@ $([MSBuild]::MakeRelative($(RepoRoot), $(MSBuildProjectDirectory))) $(RepoRoot)dist/$(ProjectRelativePath) $(BaseOutputPath) + $(RepoRoot)dist/intermediates/$(ProjectRelativePath)/obj + $(BaseIntermediateOutputPath) true diff --git a/demo/apps/web-frontend/project.json b/demo/apps/web-frontend/project.json index 024c5b39..ab46304d 100644 --- a/demo/apps/web-frontend/project.json +++ b/demo/apps/web-frontend/project.json @@ -1,6 +1,6 @@ { "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "name": "demo-web-frontend", + "name": "demo-frontend", "sourceRoot": "demo/apps/web-frontend/src", "projectType": "application", "targets": { diff --git a/demo/apps/webapi/Controllers/WeatherForecastController.cs b/demo/apps/webapi/Controllers/WeatherForecastController.cs index 8c61cfb4..6bec5d18 100644 --- a/demo/apps/webapi/Controllers/WeatherForecastController.cs +++ b/demo/apps/webapi/Controllers/WeatherForecastController.cs @@ -14,7 +14,7 @@ public class WeatherForecastController : ControllerBase private readonly ILogger _logger; public WeatherForecastController(ILogger logger) - { + { _logger = logger; } diff --git a/demo/apps/webapi/NxDotnet.Test.Webapi.csproj b/demo/apps/webapi/NxDotnet.Test.Webapi.csproj index eabe5f5b..d162b757 100644 --- a/demo/apps/webapi/NxDotnet.Test.Webapi.csproj +++ b/demo/apps/webapi/NxDotnet.Test.Webapi.csproj @@ -1,20 +1,15 @@ - - net6.0 - enable - enable - - ../../../dist/demo/apps/webapi - + - - - + + + + + - \ No newline at end of file diff --git a/demo/apps/webapi/project.json b/demo/apps/webapi/project.json index e70f6a92..2399904a 100644 --- a/demo/apps/webapi/project.json +++ b/demo/apps/webapi/project.json @@ -1,12 +1,15 @@ { "$schema": "../../../node_modules/nx/schemas/project-schema.json", - "name": "demo-apps-webapi", + "name": "demo-webapi", "projectType": "application", "sourceRoot": "demo/apps/webapi", "targets": { "build": { "executor": "@nx-dotnet/core:build", - "outputs": ["{workspaceRoot}/dist/demo/apps/webapi"], + "outputs": [ + "{workspaceRoot}/dist/demo/apps/webapi", + "{workspaceRoot}/dist/intermediates/demo/apps/webapi" + ], "options": { "configuration": "Debug", "noDependencies": true diff --git a/demo/libs/csharp-models/Class1.cs b/demo/libs/csharp-models/Class1.cs new file mode 100644 index 00000000..b49d7328 --- /dev/null +++ b/demo/libs/csharp-models/Class1.cs @@ -0,0 +1,5 @@ +namespace NxDotnet.Demo.Libs.CsharpModels; +public class Class1 +{ + +} diff --git a/demo/libs/csharp-models/NxDotnet.Demo.Libs.CsharpModels.csproj b/demo/libs/csharp-models/NxDotnet.Demo.Libs.CsharpModels.csproj new file mode 100644 index 00000000..bafd05b1 --- /dev/null +++ b/demo/libs/csharp-models/NxDotnet.Demo.Libs.CsharpModels.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + enable + + + diff --git a/demo/libs/csharp-models/project.json b/demo/libs/csharp-models/project.json new file mode 100644 index 00000000..b896ba36 --- /dev/null +++ b/demo/libs/csharp-models/project.json @@ -0,0 +1,28 @@ +{ + "name": "demo-csharp-models", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "demo/libs/csharp-models", + "targets": { + "build": { + "executor": "@nx-dotnet/core:build", + "outputs": [ + "{workspaceRoot}/dist/demo/libs/csharp-models", + "{workspaceRoot}/dist/intermediates/demo/libs/csharp-models/obj" + ], + "options": { + "configuration": "Debug", + "noDependencies": true + }, + "configurations": { + "production": { + "configuration": "Release" + } + } + }, + "lint": { + "executor": "@nx-dotnet/core:format" + } + }, + "tags": [] +} diff --git a/demo/libs/generated/webapi-swagger/project.json b/demo/libs/generated/webapi-swagger/project.json index 796208e1..02d582b7 100644 --- a/demo/libs/generated/webapi-swagger/project.json +++ b/demo/libs/generated/webapi-swagger/project.json @@ -15,5 +15,5 @@ } } }, - "implicitDependencies": ["demo-apps-webapi"] + "implicitDependencies": ["demo-webapi"] } diff --git a/nx.json b/nx.json index 2ac3b67d..4aa06d79 100644 --- a/nx.json +++ b/nx.json @@ -63,7 +63,9 @@ "{workspaceRoot}/tsconfig.base.json", "{workspaceRoot}/tslint.json", "{workspaceRoot}/nx.json", - "{workspaceRoot}/babel.config.json" + "{workspaceRoot}/babel.config.json", + "{workspaceRoot}/Directory.Build.props", + "{workspaceRoot}/Directory.Build.targets" ], "production": [ "default", diff --git a/package.json b/package.json index 0ee2df4b..44b5f7dc 100644 --- a/package.json +++ b/package.json @@ -131,5 +131,5 @@ "type": "git", "url": "https://github.com/nx-dotnet/nx-dotnet.git" }, - "version": "1.18.0" + "version": "1.18.1" } diff --git a/packages/core/migrations.json b/packages/core/migrations.json index b775c657..fce3a9d8 100644 --- a/packages/core/migrations.json +++ b/packages/core/migrations.json @@ -17,6 +17,12 @@ "description": "update-1.8.0-beta.0", "cli": "nx", "implementation": "./src/migrations/1.8.0/remove-output-option" + }, + "update-1.18.1-add-outputs": { + "version": "1.18.1-beta.0", + "description": "Adds build intermediates to Nx outputs arrays s.t. nx cloud is more effective.", + "cli": "nx", + "implementation": "./src/migrations/update-1.18.1/add-intermediate-outputs" } } } diff --git a/packages/core/package.json b/packages/core/package.json index 6e1b2a37..a1afe46b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -44,5 +44,5 @@ "@nx-dotnet/dotnet" ] }, - "version": "1.18.0" + "version": "1.18.1" } diff --git a/packages/core/src/executors/update-swagger/executor.ts b/packages/core/src/executors/update-swagger/executor.ts index e7a370f8..c208c549 100644 --- a/packages/core/src/executors/update-swagger/executor.ts +++ b/packages/core/src/executors/update-swagger/executor.ts @@ -8,7 +8,7 @@ import { import { existsSync } from 'fs'; import { ensureDirSync } from 'fs-extra'; -import { dirname, join } from 'path'; +import { dirname, join, resolve } from 'path'; import { DotNetClient, dotnetFactory } from '@nx-dotnet/dotnet'; import { @@ -99,7 +99,7 @@ export default async function runExecutor( 'tofile', '--output', options.output, - options.startupAssembly, + resolve(options.startupAssembly), options.swaggerDoc, ]); diff --git a/packages/core/src/generators/init/templates/root/Directory.Build.props__tmpl__ b/packages/core/src/generators/init/templates/root/Directory.Build.props__tmpl__ index 47a2f8c2..9fef819e 100644 --- a/packages/core/src/generators/init/templates/root/Directory.Build.props__tmpl__ +++ b/packages/core/src/generators/init/templates/root/Directory.Build.props__tmpl__ @@ -9,6 +9,8 @@ $([MSBuild]::MakeRelative($(RepoRoot), $(MSBuildProjectDirectory))) $(RepoRoot)dist/$(ProjectRelativePath) $(BaseOutputPath) + $(RepoRoot)dist/intermediates/$(ProjectRelativePath)/obj + $(BaseIntermediateOutputPath) true diff --git a/packages/core/src/generators/project-reference/generator.spec.ts b/packages/core/src/generators/project-reference/generator.spec.ts index 7e9a58fa..a54a8c1a 100644 --- a/packages/core/src/generators/project-reference/generator.spec.ts +++ b/packages/core/src/generators/project-reference/generator.spec.ts @@ -3,6 +3,10 @@ import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; import { DotNetClient } from '@nx-dotnet/dotnet'; +jest.mock('@nx-dotnet/utils/src/lib/utility-functions/glob', () => ({ + getProjectFileForNxProject: () => Promise.resolve('my.csproj'), +})); + import generator from './generator'; import { NxDotnetGeneratorSchema } from './schema'; diff --git a/packages/core/src/generators/project-reference/generator.ts b/packages/core/src/generators/project-reference/generator.ts index 3af5cd43..419302b8 100644 --- a/packages/core/src/generators/project-reference/generator.ts +++ b/packages/core/src/generators/project-reference/generator.ts @@ -20,7 +20,7 @@ export default async function ( getProjectFileForNxProject(sourceProject), ]); } catch { - console.warn('Unable to find project files to add dependency!'); + throw new Error('Unable to find project files to add dependency!'); } client.addProjectReference(hostProjectFile, sourceProjectFile); diff --git a/packages/core/src/generators/project-reference/schema.json b/packages/core/src/generators/project-reference/schema.json index 63cb594c..c0b4a861 100644 --- a/packages/core/src/generators/project-reference/schema.json +++ b/packages/core/src/generators/project-reference/schema.json @@ -13,7 +13,8 @@ "$source": "argv", "index": 0 }, - "x-prompt": "Which project should the reference be attached to?" + "x-prompt": "Which project should the reference be attached to?", + "x-dropdown": "projects" }, "reference": { "type": "string", @@ -22,7 +23,8 @@ "$source": "argv", "index": 1 }, - "x-prompt": "Which project should the reference point to?" + "x-prompt": "Which project should the reference point to?", + "x-dropdown": "projects" } }, "required": ["project", "reference"] diff --git a/packages/core/src/generators/utils/generate-project.spec.ts b/packages/core/src/generators/utils/generate-project.spec.ts index b87e7536..0c297441 100644 --- a/packages/core/src/generators/utils/generate-project.spec.ts +++ b/packages/core/src/generators/utils/generate-project.spec.ts @@ -82,9 +82,11 @@ describe('nx-dotnet project generator', () => { await GenerateProject(appTree, options, dotnetClient, 'application'); const config = readProjectConfiguration(appTree, 'test'); const outputPath = config.targets?.build.outputs || []; - expect(outputPath.length).toBe(1); expect(outputPath[0]).toEqual('{workspaceRoot}/dist/apps/test'); + expect(outputPath[1]).toEqual( + '{workspaceRoot}/dist/intermediates/apps/test', + ); }); it('should include serve target for applications', async () => { diff --git a/packages/core/src/graph/infer-project.spec.ts b/packages/core/src/graph/infer-project.spec.ts index 7373d9b5..5b7f2820 100644 --- a/packages/core/src/graph/infer-project.spec.ts +++ b/packages/core/src/graph/infer-project.spec.ts @@ -52,6 +52,7 @@ describe('infer-project', () => { }, "outputs": Array [ "{workspaceRoot}/dist/libs/api", + "{workspaceRoot}/dist/intermediates/libs/api", ], } `); diff --git a/packages/core/src/migrations/update-1.18.1/add-intermediate-outputs.ts b/packages/core/src/migrations/update-1.18.1/add-intermediate-outputs.ts new file mode 100644 index 00000000..c0ffe870 --- /dev/null +++ b/packages/core/src/migrations/update-1.18.1/add-intermediate-outputs.ts @@ -0,0 +1,132 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { + formatFiles, + getProjects, + logger, + ProjectConfiguration, + readNxJson, + Tree, + updateProjectConfiguration, + writeJson, +} from '@nrwl/devkit'; +import { TargetDefaults } from 'nx/src/config/nx-json'; +import { gt } from 'semver'; +import { XmlDocument } from 'xmldoc'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const nxVersion = require('nx/package.json').version; + +export default function update(host: Tree) { + const projects = getProjects(host); + const directoryBuildPropsExists = host.exists('Directory.Build.props'); + const directoryBuildPropsUpdated = + directoryBuildPropsExists && updateDirectoryBuildProps(host); + + for (const [project, configuration] of projects) { + const changed = updateTargetOutputs( + directoryBuildPropsUpdated, + configuration, + ); + if (changed) { + updateProjectConfiguration(host, project, configuration); + } + } + + updateTargetDefaults(host, directoryBuildPropsUpdated); + + formatFiles(host); +} + +function updateDirectoryBuildProps(host: Tree): boolean { + const contents = host.read('Directory.Build.props', 'utf-8'); + if (!contents) { + logger.warn('Unable to read "Directory.Build.props"'); + return false; + } + const xml = new XmlDocument(contents); + const propertyGroups = xml.childrenNamed('PropertyGroup'); + const outputManipulationGroup = propertyGroups.find((group) => + group.childNamed('OutputPath'), + ); + if (!outputManipulationGroup) { + logger.warn( + 'Unable to find property group containing output manipulation in Directory.Build.props', + ); + return false; + } + outputManipulationGroup.children.push( + new XmlDocument( + `$(RepoRoot)dist/intermediates/$(ProjectRelativePath)/obj`, + ), + ); + outputManipulationGroup.children.push( + new XmlDocument( + `$(BaseIntermediateOutputPath)`, + ), + ); + host.write('Directory.Build.props', xml.toString()); + return true; +} + +function updateTargetOutputs( + directoryBuildPropsUpdated: boolean, + configuration: ProjectConfiguration, +): boolean { + let changed = false; + + const targets = Object.values(configuration.targets ?? {}).filter( + (x) => x.executor === '@nx-dotnet/core:build', + ); + + for (const target of targets) { + if (directoryBuildPropsUpdated) { + if (!target.outputs?.some((x) => x.includes('intermediates'))) { + const prefix = gt(nxVersion, '15.0.0-beta.0') ? '{workspaceRoot}/' : ''; + target.outputs?.push( + prefix + `dist/intermediates/${configuration.root}`, + ); + changed = true; + } + } else { + if (!target.outputs?.some((x) => x.includes('obj'))) { + const prefix = gt(nxVersion, '15.0.0-beta.0') + ? '{projectRoot}/' + : `${configuration.root}/`; + target.outputs?.push(prefix + `obj`); + changed = true; + } + } + } + return changed; +} + +function updateTargetDefaults(host: Tree, directoryBuildPropsUpdated: boolean) { + let changed = false; + const nxJson = readNxJson(); + const targetDefaults: TargetDefaults | undefined = nxJson.targetDefaults; + + if (!targetDefaults) { + return; + } + + const configuration = targetDefaults['@nx-dotnet/core:build']; + if (configuration) { + if (directoryBuildPropsUpdated) { + if (!configuration.outputs?.some((x) => x.includes('intermediates'))) { + configuration.outputs?.push( + `{workspaceRoot}/dist/intermediates/{projectRoot}`, + ); + changed = true; + } + } else { + if (!configuration.outputs?.some((x) => x.includes('obj'))) { + configuration.outputs?.push(`{projectRoot}/obj`); + changed = true; + } + } + } + + if (changed) { + writeJson(host, 'nx.json', nxJson); + } +} diff --git a/packages/core/src/models/build-executor-configuration.ts b/packages/core/src/models/build-executor-configuration.ts index c744a986..7f3d8959 100644 --- a/packages/core/src/models/build-executor-configuration.ts +++ b/packages/core/src/models/build-executor-configuration.ts @@ -11,13 +11,16 @@ export function GetBuildExecutorConfiguration( // eslint-disable-next-line @typescript-eslint/no-var-requires const nxVersion = require('nx/package.json').version; - const outputDirectory = - (lt(nxVersion, '15.0.0-beta.0') ? '' : '{workspaceRoot}/') + - `dist/${projectRoot}`; + const outputs = lt(nxVersion, '15.0.0-beta.0') + ? [`dist/${projectRoot}`, `dist/intermediates/${projectRoot}`] + : [ + `{workspaceRoot}/dist/${projectRoot}`, + `{workspaceRoot}/dist/intermediates/${projectRoot}`, + ]; return { executor: '@nx-dotnet/core:build', - outputs: [outputDirectory], + outputs, options: { configuration: 'Debug', noDependencies: true, diff --git a/packages/dotnet/package.json b/packages/dotnet/package.json index c11ca575..d5dd6856 100644 --- a/packages/dotnet/package.json +++ b/packages/dotnet/package.json @@ -20,5 +20,5 @@ "url": "https://github.com/nx-dotnet/nx-dotnet" }, "homepage": "https://nx-dotnet.com/", - "version": "1.18.0" + "version": "1.18.1" } diff --git a/packages/nx-ghpages/package.json b/packages/nx-ghpages/package.json index ac0c5f8e..b4932ad8 100644 --- a/packages/nx-ghpages/package.json +++ b/packages/nx-ghpages/package.json @@ -24,5 +24,5 @@ "url": "https://github.com/nx-dotnet/nx-dotnet" }, "homepage": "https://nx-dotnet.com/", - "version": "1.18.0" + "version": "1.18.1" } diff --git a/packages/nxdoc/package.json b/packages/nxdoc/package.json index 4ddeb6c7..0e63d00d 100644 --- a/packages/nxdoc/package.json +++ b/packages/nxdoc/package.json @@ -24,5 +24,5 @@ "type": "git", "url": "https://github.com/nx-dotnet/nx-dotnet" }, - "version": "1.18.0" + "version": "1.18.1" } diff --git a/packages/utils/package.json b/packages/utils/package.json index c884bb2b..7628fbf5 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -24,5 +24,5 @@ "url": "https://github.com/nx-dotnet/nx-dotnet" }, "homepage": "https://nx-dotnet.com/", - "version": "1.18.0" + "version": "1.18.1" }