@nx/dotnet 23.3.0-beta.0 → 23.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,7 @@ export interface AnalysisSuccessResult {
11
11
  refs: string[];
12
12
  sourceConfigFile: string;
13
13
  }>;
14
+ evaluationInputs?: string[];
14
15
  }
15
16
  export interface AnalysisErrorResult {
16
17
  error: Error;
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer-client.d.ts","sourceRoot":"","sources":["../../src/analyzer/analyzer-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAmBpB,eAAO,MAAM,0BAA0B,+BAA+B,CAAC;AAIvE;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAS7C;AAED,MAAM,WAAW,qBAAqB;IAEpC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAElD,gBAAgB,EAAE,MAAM,CACtB,MAAM,EACN;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAC7C,CAAC;CACH;AACD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,KAAK,CAAC;CACd;AACD,MAAM,MAAM,cAAc,GAAG,qBAAqB,GAAG,mBAAmB,CAAC;AAEzE;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA4MD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,cAAc,CAAC,CA+DzB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,cAAc,CASzD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,GACrB,MAAM,IAAI,mBAAmB,CAE/B;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,cAAc,GACrB,MAAM,IAAI,qBAAqB,CAEjC"}
1
+ {"version":3,"file":"analyzer-client.d.ts","sourceRoot":"","sources":["../../src/analyzer/analyzer-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAmBpB,eAAO,MAAM,0BAA0B,+BAA+B,CAAC;AAIvE;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAS7C;AAED,MAAM,WAAW,qBAAqB;IAEpC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAElD,gBAAgB,EAAE,MAAM,CACtB,MAAM,EACN;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAC7C,CAAC;IAIF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AACD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,KAAK,CAAC;CACd;AACD,MAAM,MAAM,cAAc,GAAG,qBAAqB,GAAG,mBAAmB,CAAC;AAEzE;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA0OD;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,cAAc,CAAC,CAoEzB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,cAAc,CASzD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,GACrB,MAAM,IAAI,mBAAmB,CAE/B;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,cAAc,GACrB,MAAM,IAAI,qBAAqB,CAEjC"}
@@ -66,6 +66,22 @@ function getAnalyzerPath() {
66
66
  async function calculateProjectFilesHash(files) {
67
67
  return await (0, internal_1.hashWithWorkspaceContext)(devkit_1.workspaceRoot, files);
68
68
  }
69
+ /**
70
+ * Hash of the files a previous evaluation reported reading. Empty when the
71
+ * result carries none, so a result from an older analyzer never matches and
72
+ * is re-run once.
73
+ */
74
+ async function calculateEvaluationInputsHash(result) {
75
+ const inputs = result.evaluationInputs ?? [];
76
+ return inputs.length === 0
77
+ ? ''
78
+ : await (0, internal_1.hashWithWorkspaceContext)(devkit_1.workspaceRoot, inputs);
79
+ }
80
+ async function isStillValid(entry) {
81
+ return (entry?.result !== undefined &&
82
+ isAnalysisSuccessResult(entry.result) &&
83
+ entry.inputsHash === (await calculateEvaluationInputsHash(entry.result)));
84
+ }
69
85
  /**
70
86
  * Run the msbuild-analyzer and return the results.
71
87
  * Uses stdin for large file lists to avoid ARG_MAX issues.
@@ -210,36 +226,40 @@ async function runAnalyzer(files, options) {
210
226
  */
211
227
  async function analyzeProjects(files, options) {
212
228
  const filesHash = await calculateProjectFilesHash(files);
213
- // Return cached results if the hash matches
229
+ // Return cached results if the glob-matched files and the files the
230
+ // previous evaluation imported are both unchanged.
214
231
  if (cache &&
215
232
  cache.hash === filesHash &&
216
233
  // NOTE: We don't read from the cache here if it's an error result,
217
234
  // to allow retrying analysis in case of transient errors or errors fixed
218
235
  // that may not be reflected in the hash (like setting an env var).
219
- isAnalysisSuccessResult(cache.result)) {
236
+ isAnalysisSuccessResult(cache.result) &&
237
+ (await isStillValid({ result: cache.result, inputsHash: cache.inputsHash }))) {
220
238
  return cache.result;
221
239
  }
222
240
  const optionsHash = (0, internal_1.hashObject)(options);
223
241
  const analyzerCache = new internal_1.PluginCache((0, node_path_1.join)(internal_1.workspaceDataDirectory, `dotnet-${optionsHash}.hash`));
224
- const cachedResult = analyzerCache.get(filesHash);
225
- if (cachedResult) {
226
- // Update cache
242
+ const persisted = analyzerCache.get(filesHash);
243
+ if (await isStillValid(persisted)) {
227
244
  cache = {
228
245
  hash: filesHash,
229
- result: cachedResult,
246
+ inputsHash: persisted.inputsHash,
247
+ result: persisted.result,
230
248
  };
231
- return cachedResult;
249
+ return persisted.result;
232
250
  }
233
251
  // Run the analyzer
234
252
  try {
235
253
  const result = await runAnalyzer(files, options);
254
+ const inputsHash = await calculateEvaluationInputsHash(result);
236
255
  // Update local cache
237
256
  cache = {
238
257
  hash: filesHash,
258
+ inputsHash,
239
259
  result,
240
260
  };
241
261
  // Update persistent cache
242
- analyzerCache.set(filesHash, result);
262
+ analyzerCache.set(filesHash, { result, inputsHash });
243
263
  analyzerCache.writeToDisk();
244
264
  return result;
245
265
  }
@@ -258,6 +278,7 @@ async function analyzeProjects(files, options) {
258
278
  if (err.message !== exports.ANALYZER_CANCELLED_MESSAGE) {
259
279
  cache = {
260
280
  hash: filesHash,
281
+ inputsHash: '',
261
282
  result: errorResult,
262
283
  };
263
284
  }
@@ -0,0 +1,35 @@
1
+ version: 2.1
2
+
3
+ orbs:
4
+ nx: nrwl/nx@1.6.2
5
+
6
+ env:
7
+ NX_BATCH_MODE: true
8
+
9
+ jobs:
10
+ main:
11
+ docker:
12
+ - image: mcr.microsoft.com/dotnet/sdk:10.0
13
+ steps:
14
+ - checkout
15
+
16
+ # This enables task distribution via Nx Cloud
17
+ # Run this command as early as possible, before dependencies are installed
18
+ # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
19
+ <% if (connectedToCloud) { %># Uncomment this line to enable task distribution<% } else { %># Connect your workspace by running "nx connect" and uncomment this line to enable task distribution<% } %>
20
+ # - run: ./nx start-ci-run --distribute-on="3 linux-medium-dotnet" --stop-agents-after="build"
21
+
22
+ - nx/set-shas:
23
+ main-branch-name: '<%= mainBranch %>'
24
+ <% for (const command of commands) { %><% if (command.comments) { %><% for (const comment of command.comments) { %>
25
+ # <%- comment %><% } %><% } %><% if (command.command) { %>
26
+ - run:
27
+ command: <%= command.command %><% if (command.alwaysRun) { %>
28
+ when: always<% } %><% } %><% } %>
29
+
30
+ workflows:
31
+ version: 2
32
+
33
+ <%= workflowFileName %>:
34
+ jobs:
35
+ - main
@@ -0,0 +1,39 @@
1
+ name: <%= workflowName %>
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - <%= mainBranch %>
7
+ pull_request:
8
+
9
+ permissions:
10
+ actions: read
11
+ contents: read
12
+
13
+ env:
14
+ NX_BATCH_MODE: true
15
+
16
+ jobs:
17
+ main:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ with:
22
+ fetch-depth: 0
23
+
24
+ # This enables task distribution via Nx Cloud
25
+ # Run this command as early as possible, before dependencies are installed
26
+ # Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
27
+ <% if (connectedToCloud) { %># Uncomment this line to enable task distribution<% } else { %># Connect your workspace by running "nx connect" and uncomment this line to enable task distribution<% } %>
28
+ # - run: ./nx start-ci-run --distribute-on="3 linux-medium-dotnet" --stop-agents-after="build"
29
+
30
+ - name: Setup .NET
31
+ uses: actions/setup-dotnet@v4
32
+ with:
33
+ dotnet-version: '10.x'
34
+
35
+ - uses: nrwl/nx-set-shas@v4
36
+ <% for (const command of commands) { %><% if (command.comments) { %><% for (const comment of command.comments) { %>
37
+ # <%- comment %><% } %><% } %><% if (command.command) { %>
38
+ - run: <%= command.command %><% if (command.alwaysRun) { %>
39
+ if: always()<% } %><% } %><% } %>
Binary file
Binary file
@@ -7,6 +7,7 @@
7
7
  "version": "8.0.0"
8
8
  },
9
9
  "configProperties": {
10
+ "System.GC.Server": true,
10
11
  "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
11
12
  "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
12
13
  }
@@ -4,15 +4,15 @@ exports.createNodesV2 = exports.createNodes = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
5
  const analyzer_client_1 = require("../analyzer/analyzer-client");
6
6
  const internal_1 = require("@nx/devkit/internal");
7
- // MSBuild auto-imports Directory.Build.props/.targets from each ancestor of a project file,
8
- // reads Directory.Build.rsp from ancestors during CLI builds, applies Directory.Solution.*
9
- // when building a .sln, and reads Directory.Packages.props from the nearest ancestor when
10
- // Central Package Management is in use. Matching them here causes createNodesV2 to re-run
11
- // (and the analyzer's cache to invalidate) when any of them change, and gives us the file
12
- // list to hand to the analyzer so it can declare per-project ancestor inputs.
13
- // The analyzer partitions matched paths into project vs directory files by filename, so we
14
- // don't have to repeat that classification on this side.
15
- const dotnetProjectGlob = '**/{*.{csproj,fsproj,vbproj},Directory.Build.{props,targets,rsp},Directory.Solution.{props,targets},Directory.Packages.props}';
7
+ // Every file matched here re-runs createNodes and enters the analyzer's cache key when
8
+ // it changes. Project files and the ancestor-scoped files MSBuild, the SDK resolver, NuGet
9
+ // and the analyzers read on their own (Directory.*, global.json, nuget.config,
10
+ // .editorconfig) are also handed to the analyzer so it can declare per-project inputs.
11
+ // Any other .props/.targets is matched only so an edit to a file a project imports by
12
+ // name invalidates the graph; the analyzer discovers which ones matter by evaluating and
13
+ // reports them back as evaluationInputs, which covers imports with other extensions.
14
+ // The analyzer partitions matched paths by filename, so nothing is classified here.
15
+ const dotnetProjectGlob = '**/{*.{csproj,fsproj,vbproj,props,targets},Directory.Build.rsp,global.json,nuget.config,NuGet.config,NuGet.Config,.editorconfig}';
16
16
  /**
17
17
  * Merge user-specified target configurations with the generated targets from the analyzer
18
18
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/dotnet",
3
- "version": "23.3.0-beta.0",
3
+ "version": "23.3.0-beta.1",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for .NET containing graph support for working with .NET projects in an Nx workspace.",
6
6
  "keywords": [
@@ -49,7 +49,7 @@
49
49
  "dependencies": {
50
50
  "tslib": "^2.3.0",
51
51
  "ignore": "^7.0.5",
52
- "@nx/devkit": "23.3.0-beta.0"
52
+ "@nx/devkit": "23.3.0-beta.1"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@types/jest": "30.0.0",
@@ -58,7 +58,7 @@
58
58
  "memfs": "^4.9.2",
59
59
  "ts-jest": "^29.4.7",
60
60
  "typescript": "~6.0.3",
61
- "nx": "23.3.0-beta.0"
61
+ "nx": "23.3.0-beta.1"
62
62
  },
63
63
  "publishConfig": {
64
64
  "access": "public"