Skip to content

Commit 2afb320

Browse files
committed
feat(maven): parse TaskGraph JSON into typed Kotlin data classes
1 parent c98b1b6 commit 2afb320

File tree

3 files changed

+155
-22
lines changed

3 files changed

+155
-22
lines changed

packages/maven/batch-runner/src/main/kotlin/dev/nx/maven/cli/ArgParser.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import com.google.gson.Gson
44
import com.google.gson.reflect.TypeToken
55
import dev.nx.maven.data.MavenBatchOptions
66
import dev.nx.maven.data.MavenBatchTask
7-
import java.io.File
7+
import dev.nx.maven.data.TaskGraph
88

99
object ArgParser {
1010
private val gson = Gson()
@@ -57,6 +57,17 @@ object ArgParser {
5757
// Read task graph from stdin
5858
val taskGraphJson = System.`in`.bufferedReader().readText()
5959

60+
// Parse task graph JSON
61+
val taskGraph = if (taskGraphJson.isNotEmpty() && taskGraphJson != "{}") {
62+
try {
63+
gson.fromJson(taskGraphJson, TaskGraph::class.java)
64+
} catch (e: Exception) {
65+
throw IllegalArgumentException("Failed to parse task graph JSON", e)
66+
}
67+
} else {
68+
null
69+
}
70+
6071
// Parse tasks JSON
6172
val tasksMap = if (tasksJson.isNotEmpty()) {
6273
try {
@@ -106,7 +117,7 @@ object ArgParser {
106117
resultsFile = cleanResultsFile,
107118
quiet = quiet,
108119
verbose = verbose,
109-
taskGraph = taskGraphJson
120+
taskGraph = taskGraph
110121
)
111122
}
112123
}

packages/maven/batch-runner/src/main/kotlin/dev/nx/maven/data/MavenBatchOptions.kt

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ data class MavenBatchOptions(
88
val workspaceDataDirectory: String = "",
99
val quiet: Boolean = false,
1010
val verbose: Boolean = false,
11-
val taskGraph: String = "{}"
11+
val taskGraph: TaskGraph? = null
1212
)
1313

1414
data class MavenBatchTask(
@@ -24,3 +24,138 @@ data class TaskResult(
2424
val success: Boolean,
2525
val terminalOutput: String
2626
)
27+
28+
/**
29+
* A representation of the invocation of an Executor
30+
*/
31+
data class Task(
32+
/**
33+
* Unique ID
34+
*/
35+
val id: String,
36+
37+
/**
38+
* Details about which project, target, and configuration to run.
39+
*/
40+
val target: TaskTarget,
41+
42+
/**
43+
* Overrides for the configured options of the target
44+
*/
45+
val overrides: Any,
46+
47+
/**
48+
* The outputs the task may produce
49+
*/
50+
val outputs: List<String>,
51+
52+
/**
53+
* Root of the project the task belongs to
54+
*/
55+
val projectRoot: String? = null,
56+
57+
/**
58+
* Hash of the task which is used for caching.
59+
*/
60+
val hash: String? = null,
61+
62+
/**
63+
* Details about the composition of the hash
64+
*/
65+
val hashDetails: TaskHashDetails? = null,
66+
67+
/**
68+
* Unix timestamp of when a Batch Task starts
69+
*/
70+
val startTime: Long? = null,
71+
72+
/**
73+
* Unix timestamp of when a Batch Task ends
74+
*/
75+
val endTime: Long? = null,
76+
77+
/**
78+
* Determines if a given task should be cacheable.
79+
*/
80+
val cache: Boolean? = null,
81+
82+
/**
83+
* Determines if a given task should be parallelizable.
84+
*/
85+
val parallelism: Boolean,
86+
87+
/**
88+
* This denotes if the task runs continuously
89+
*/
90+
val continuous: Boolean? = null
91+
)
92+
93+
/**
94+
* Details about which project, target, and configuration to run
95+
*/
96+
data class TaskTarget(
97+
/**
98+
* The project for which the task belongs to
99+
*/
100+
val project: String,
101+
102+
/**
103+
* The target name which the task should invoke
104+
*/
105+
val target: String,
106+
107+
/**
108+
* The configuration of the target which the task invokes
109+
*/
110+
val configuration: String? = null
111+
)
112+
113+
/**
114+
* Details about the composition of the hash
115+
*/
116+
data class TaskHashDetails(
117+
/**
118+
* Command of the task
119+
*/
120+
val command: String,
121+
122+
/**
123+
* Hashes of inputs used in the hash
124+
*/
125+
val nodes: Map<String, String>,
126+
127+
/**
128+
* Hashes of implicit dependencies which are included in the hash
129+
*/
130+
val implicitDeps: Map<String, String>? = null,
131+
132+
/**
133+
* Hash of the runtime environment which the task was executed
134+
*/
135+
val runtime: Map<String, String>? = null
136+
)
137+
138+
/**
139+
* Graph of Tasks to be executed
140+
*/
141+
data class TaskGraph(
142+
/**
143+
* IDs of Tasks which do not have any dependencies and are thus ready to execute immediately
144+
*/
145+
val roots: List<String>,
146+
147+
/**
148+
* Map of Task IDs to Tasks
149+
*/
150+
val tasks: Map<String, Task>,
151+
152+
/**
153+
* Map of Task IDs to IDs of tasks which the task depends on
154+
*/
155+
val dependencies: Map<String, List<String>>,
156+
157+
/**
158+
* Map of Task IDs to IDs of continuous dependency tasks
159+
*/
160+
val continuousDependencies: Map<String, List<String>>
161+
)

packages/maven/batch-runner/src/main/kotlin/dev/nx/maven/runner/MavenInvokerRunner.kt

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ class MavenInvokerRunner(private val options: MavenBatchOptions) {
6464

6565
// Create a fresh invoker for this thread
6666
val invoker = createInvoker()
67-
6867
// Collect output for this project
6968
val projectOutput = StringBuilder()
7069

@@ -112,36 +111,24 @@ class MavenInvokerRunner(private val options: MavenBatchOptions) {
112111
}
113112
}
114113

115-
private fun parseTaskGraph(): Map<*, *>? {
116-
return try {
117-
val gson = Gson()
118-
@Suppress("UNCHECKED_CAST")
119-
(gson.fromJson(options.taskGraph, Map::class.java) as Map<*, *>)
120-
} catch (e: Exception) {
121-
log.warn("Failed to parse task graph: ${e.message}")
122-
null
123-
}
124-
}
125-
126114
private fun getTaskExecutionOrder(): List<String> {
127115
return try {
128-
val taskGraph = parseTaskGraph()
116+
val taskGraph = options.taskGraph
129117

130118
if (taskGraph == null) {
131119
log.warn("Task graph is null, using all available tasks")
132120
options.tasks.keys.toList()
133121
} else {
134122
// Extract task IDs from the "tasks" field in the task graph
135-
val tasks = taskGraph["tasks"] as? Map<*, *>
136-
if (tasks != null) {
137-
tasks.keys.map { it.toString() }.toList()
123+
if (taskGraph.tasks.isNotEmpty()) {
124+
taskGraph.tasks.keys.toList()
138125
} else {
139-
log.warn("No tasks field in task graph, using all available tasks")
126+
log.warn("No tasks in task graph, using all available tasks")
140127
options.tasks.keys.toList()
141128
}
142129
}
143130
} catch (e: Exception) {
144-
log.warn("Failed to parse task graph: ${e.message}, using all available tasks")
131+
log.warn("Failed to access task graph: ${e.message}, using all available tasks")
145132
options.tasks.keys.toList()
146133
}
147134
}
@@ -191,7 +178,7 @@ class MavenInvokerRunner(private val options: MavenBatchOptions) {
191178
// Add Nx Maven record goal after user goals
192179
request.goals.add("dev.nx.maven:nx-maven-plugin:record")
193180

194-
request.isRecursive = true
181+
request.isRecursive = false
195182

196183
log.info("Executing ${request.goals.joinToString(", ")} goals for project: $project")
197184

0 commit comments

Comments
 (0)