@nx/maven 22.6.4 → 22.6.5

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.
Binary file
@@ -1,4 +1,9 @@
1
1
  import { MavenAnalysisData, MavenPluginOptions } from './types';
2
+ /**
3
+ * Cancel any in-flight Maven analysis process.
4
+ * Safe to call even if nothing is running.
5
+ */
6
+ export declare function cancelPendingMavenAnalysis(): void;
2
7
  /**
3
8
  * Run Maven analysis using our Kotlin analyzer plugin
4
9
  */
@@ -1 +1 @@
1
- {"version":3,"file":"maven-analyzer.d.ts","sourceRoot":"","sources":["../../src/plugins/maven-analyzer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGhE;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAyH5B"}
1
+ {"version":3,"file":"maven-analyzer.d.ts","sourceRoot":"","sources":["../../src/plugins/maven-analyzer.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAQhE;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAKjD;AAaD;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CA4J5B"}
@@ -1,12 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cancelPendingMavenAnalysis = cancelPendingMavenAnalysis;
3
4
  exports.runMavenAnalysis = runMavenAnalysis;
4
5
  const path_1 = require("path");
5
6
  const fs_1 = require("fs");
6
7
  const child_process_1 = require("child_process");
7
8
  const devkit_1 = require("@nx/devkit");
9
+ const devkit_internals_1 = require("nx/src/devkit-internals");
8
10
  const cache_directory_1 = require("nx/src/utils/cache-directory");
9
11
  const detect_maven_executable_1 = require("../utils/detect-maven-executable");
12
+ const treeKill = require('tree-kill');
13
+ const DEFAULT_ANALYSIS_TIMEOUT_SECONDS = (0, devkit_internals_1.isCI)() ? 600 : 120;
14
+ let currentAbortController;
15
+ /**
16
+ * Cancel any in-flight Maven analysis process.
17
+ * Safe to call even if nothing is running.
18
+ */
19
+ function cancelPendingMavenAnalysis() {
20
+ if (currentAbortController) {
21
+ currentAbortController.abort('cancelled');
22
+ currentAbortController = undefined;
23
+ }
24
+ }
25
+ function getAnalysisTimeoutMs() {
26
+ const envTimeout = process.env.NX_MAVEN_ANALYSIS_TIMEOUT;
27
+ if (envTimeout) {
28
+ const parsed = Number(envTimeout);
29
+ if (!Number.isNaN(parsed) && parsed > 0) {
30
+ return parsed * 1000;
31
+ }
32
+ }
33
+ return DEFAULT_ANALYSIS_TIMEOUT_SECONDS * 1000;
34
+ }
10
35
  /**
11
36
  * Run Maven analysis using our Kotlin analyzer plugin
12
37
  */
@@ -40,64 +65,97 @@ async function runMavenAnalysis(workspaceRoot, options) {
40
65
  if (isVerbose) {
41
66
  console.error(`Running Maven analyzer with verbose logging: ${mavenExecutable} ${mavenArgs.join(' ')}`);
42
67
  }
68
+ // Cancel any in-flight Maven process from a previous call, then create a fresh controller.
69
+ cancelPendingMavenAnalysis();
70
+ const controller = new AbortController();
71
+ currentAbortController = controller;
72
+ const signal = controller.signal;
73
+ const timeoutMs = getAnalysisTimeoutMs();
74
+ const timeoutSeconds = timeoutMs / 1000;
75
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
43
76
  // Run Maven plugin
44
77
  devkit_1.logger.verbose(`[Maven Analyzer] Spawning Maven process...`);
45
- await new Promise((resolve, reject) => {
46
- const child = (0, child_process_1.spawn)(mavenExecutable, mavenArgs, {
47
- cwd: workspaceRoot,
48
- windowsHide: true,
49
- shell: true,
50
- stdio: 'pipe', // Always use pipe so we can control output
51
- });
52
- devkit_1.logger.verbose(`[Maven Analyzer] Process spawned with PID: ${child.pid}`);
53
- let stdout = '';
54
- let stderr = '';
55
- // In verbose mode, forward output to console in real-time
56
- if (isVerbose) {
57
- child.stdout?.on('data', (data) => {
58
- const text = data.toString();
59
- stdout += text;
60
- process.stdout.write(text); // Forward to stdout
61
- });
62
- child.stderr?.on('data', (data) => {
63
- const text = data.toString();
64
- stderr += text;
65
- process.stderr.write(text); // Forward to stderr
66
- });
67
- }
68
- else {
69
- child.stdout?.on('data', (data) => {
70
- const text = data.toString();
71
- stdout += text;
72
- devkit_1.logger.verbose(`[Maven Analyzer] Stdout chunk: ${text.trim()}`);
78
+ try {
79
+ await new Promise((resolve, reject) => {
80
+ const child = (0, child_process_1.spawn)(mavenExecutable, mavenArgs, {
81
+ cwd: workspaceRoot,
82
+ windowsHide: true,
83
+ shell: true,
84
+ stdio: 'pipe', // Always use pipe so we can control output
73
85
  });
74
- child.stderr?.on('data', (data) => {
75
- const text = data.toString();
76
- stderr += text;
77
- devkit_1.logger.verbose(`[Maven Analyzer] Stderr chunk: ${text.trim()}`);
78
- });
79
- }
80
- child.on('close', (code) => {
81
- devkit_1.logger.verbose(`[Maven Analyzer] Process closed with code: ${code}`);
82
- if (code === 0) {
83
- devkit_1.logger.verbose(`[Maven Analyzer] Maven analysis completed successfully`);
84
- resolve();
86
+ // Use tree-kill on abort to kill the entire process tree
87
+ const onAbort = () => {
88
+ if (child.pid) {
89
+ treeKill(child.pid);
90
+ }
91
+ };
92
+ signal.addEventListener('abort', onAbort, { once: true });
93
+ devkit_1.logger.verbose(`[Maven Analyzer] Process spawned with PID: ${child.pid}`);
94
+ let stdout = '';
95
+ let stderr = '';
96
+ // In verbose mode, forward output to console in real-time
97
+ if (isVerbose) {
98
+ child.stdout?.on('data', (data) => {
99
+ const text = data.toString();
100
+ stdout += text;
101
+ process.stdout.write(text); // Forward to stdout
102
+ });
103
+ child.stderr?.on('data', (data) => {
104
+ const text = data.toString();
105
+ stderr += text;
106
+ process.stderr.write(text); // Forward to stderr
107
+ });
85
108
  }
86
109
  else {
87
- let errorMsg = `Maven analysis failed with code ${code}`;
88
- if (stderr)
89
- errorMsg += `\nStderr: ${stderr}`;
90
- if (stdout && !isVerbose)
91
- errorMsg += `\nStdout: ${stdout}`;
92
- console.error(`[Maven Analyzer] Error: ${errorMsg}`);
93
- reject(new Error(errorMsg));
110
+ child.stdout?.on('data', (data) => {
111
+ const text = data.toString();
112
+ stdout += text;
113
+ devkit_1.logger.verbose(`[Maven Analyzer] Stdout chunk: ${text.trim()}`);
114
+ });
115
+ child.stderr?.on('data', (data) => {
116
+ const text = data.toString();
117
+ stderr += text;
118
+ devkit_1.logger.verbose(`[Maven Analyzer] Stderr chunk: ${text.trim()}`);
119
+ });
94
120
  }
121
+ child.on('close', (code) => {
122
+ signal.removeEventListener('abort', onAbort);
123
+ devkit_1.logger.verbose(`[Maven Analyzer] Process closed with code: ${code}`);
124
+ if (code === 0) {
125
+ devkit_1.logger.verbose(`[Maven Analyzer] Maven analysis completed successfully`);
126
+ resolve();
127
+ }
128
+ else {
129
+ let errorMsg = `Maven analysis failed with code ${code}`;
130
+ if (stderr)
131
+ errorMsg += `\nStderr: ${stderr}`;
132
+ if (stdout && !isVerbose)
133
+ errorMsg += `\nStdout: ${stdout}`;
134
+ console.error(`[Maven Analyzer] Error: ${errorMsg}`);
135
+ reject(new Error(errorMsg));
136
+ }
137
+ });
138
+ child.on('error', (error) => {
139
+ signal.removeEventListener('abort', onAbort);
140
+ console.error(`[Maven Analyzer] Process error: ${error.message}`);
141
+ reject(new Error(`Failed to spawn Maven process: ${error.message}`));
142
+ });
95
143
  });
96
- child.on('error', (error) => {
97
- console.error(`[Maven Analyzer] Process error: ${error.message}`);
98
- reject(new Error(`Failed to spawn Maven process: ${error.message}`));
99
- });
100
- });
144
+ }
145
+ catch (e) {
146
+ if (signal.reason === 'cancelled') {
147
+ throw new Error('Maven analysis was cancelled');
148
+ }
149
+ if (signal.aborted) {
150
+ throw new Error(`Maven analysis timed out after ${timeoutSeconds} ${timeoutSeconds === 1 ? 'second' : 'seconds'}.\n` +
151
+ ` 1. If the issue persists, set the environment variable NX_MAVEN_ANALYSIS_TIMEOUT to a higher value (in seconds) to increase the timeout.\n` +
152
+ ` 2. If the issue still persists, set NX_MAVEN_DISABLE=true to disable the Maven plugin entirely.`);
153
+ }
154
+ throw e;
155
+ }
156
+ finally {
157
+ clearTimeout(timer);
158
+ }
101
159
  // Read and parse the JSON output
102
160
  devkit_1.logger.verbose(`[Maven Analyzer] Checking for output file: ${outputFile}`);
103
161
  if (!(0, fs_1.existsSync)(outputFile)) {
@@ -1 +1 @@
1
- {"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../../src/plugins/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,aAAa,EAAa,MAAM,YAAY,CAAC;AAE3E,OAAO,EAAmB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAW9D;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC,kBAAkB,CAoEzD,CAAC"}
1
+ {"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../../src/plugins/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,aAAa,EAAa,MAAM,YAAY,CAAC;AAE3E,OAAO,EAAmB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAW9D;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC,kBAAkB,CA+EzD,CAAC"}
@@ -42,10 +42,20 @@ exports.createNodes = [
42
42
  let mavenData = isVerbose ? null : mavenCache.get(hash);
43
43
  // If no cached data or cache is stale, run fresh Maven analysis
44
44
  if (!mavenData) {
45
- mavenData = await (0, maven_analyzer_1.runMavenAnalysis)(context.workspaceRoot, {
46
- ...opts,
47
- verbose: isVerbose,
48
- });
45
+ try {
46
+ mavenData = await (0, maven_analyzer_1.runMavenAnalysis)(context.workspaceRoot, {
47
+ ...opts,
48
+ verbose: isVerbose,
49
+ });
50
+ }
51
+ catch (e) {
52
+ if (e instanceof Error &&
53
+ e.message === 'Maven analysis was cancelled') {
54
+ // Cancelled by a newer createNodes call — silently return empty
55
+ return [];
56
+ }
57
+ throw e;
58
+ }
49
59
  // Cache the results with the hash
50
60
  mavenCache.set(hash, mavenData);
51
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/maven",
3
- "version": "22.6.4",
3
+ "version": "22.6.5",
4
4
  "private": false,
5
5
  "description": "Nx plugin for Maven integration",
6
6
  "repository": {
@@ -46,8 +46,9 @@
46
46
  "author": "Victor Savkin",
47
47
  "license": "MIT",
48
48
  "dependencies": {
49
- "@nx/devkit": "22.6.4",
49
+ "@nx/devkit": "22.6.5",
50
50
  "@xmldom/xmldom": "^0.8.10",
51
+ "tree-kill": "^1.2.2",
51
52
  "tslib": "^2.3.0"
52
53
  },
53
54
  "devDependencies": {
@@ -56,7 +57,7 @@
56
57
  "@types/xmldom": "^0.1.34",
57
58
  "jest": "^30.0.2",
58
59
  "memfs": "^4.9.2",
59
- "nx": "22.6.4",
60
+ "nx": "22.6.5",
60
61
  "ts-jest": "^29.4.0",
61
62
  "typescript": "~5.9.2"
62
63
  },