fix(gradle): add build-ci target even if atomized=false (#31537)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> when atomized=false, it does not generate build-ci and check-ci targets ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> - when atomized=false, it should still generate build-ci and check-ci targets - upgrade dev.nx.gradle.project-graph version to 0.1.2 ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
b89ca32a01
commit
3aa546ffe3
@ -2076,6 +2076,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"migrations": {
|
"migrations": {
|
||||||
|
"/technologies/java/api/migrations/change-plugin-version-0-1-2": {
|
||||||
|
"description": "Change dev.nx.gradle.project-graph to version 0.1.2 in build file",
|
||||||
|
"file": "generated/packages/gradle/migrations/change-plugin-version-0-1-2.json",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "change-plugin-version-0-1-2",
|
||||||
|
"version": "21.3.0-beta.0",
|
||||||
|
"originalFilePath": "/packages/gradle",
|
||||||
|
"path": "/technologies/java/api/migrations/change-plugin-version-0-1-2",
|
||||||
|
"type": "migration"
|
||||||
|
},
|
||||||
"/technologies/java/api/migrations/change-plugin-version-0-1-0": {
|
"/technologies/java/api/migrations/change-plugin-version-0-1-0": {
|
||||||
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
|
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
|
||||||
"file": "generated/packages/gradle/migrations/change-plugin-version-0-1-0.json",
|
"file": "generated/packages/gradle/migrations/change-plugin-version-0-1-0.json",
|
||||||
|
|||||||
@ -2249,6 +2249,16 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"migrations": [
|
"migrations": [
|
||||||
|
{
|
||||||
|
"description": "Change dev.nx.gradle.project-graph to version 0.1.2 in build file",
|
||||||
|
"file": "generated/packages/gradle/migrations/change-plugin-version-0-1-2.json",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "change-plugin-version-0-1-2",
|
||||||
|
"version": "21.3.0-beta.0",
|
||||||
|
"originalFilePath": "/packages/gradle",
|
||||||
|
"path": "gradle/migrations/change-plugin-version-0-1-2",
|
||||||
|
"type": "migration"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
|
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
|
||||||
"file": "generated/packages/gradle/migrations/change-plugin-version-0-1-0.json",
|
"file": "generated/packages/gradle/migrations/change-plugin-version-0-1-0.json",
|
||||||
|
|||||||
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "change-plugin-version-0-1-2",
|
||||||
|
"version": "21.3.0-beta.0",
|
||||||
|
"cli": "nx",
|
||||||
|
"description": "Change dev.nx.gradle.project-graph to version 0.1.2 in build file",
|
||||||
|
"factory": "./src/migrations/21-3-0/change-plugin-version-0-1-2",
|
||||||
|
"implementation": "/packages/gradle/src/migrations/21-3-0/change-plugin-version-0-1-2.ts",
|
||||||
|
"aliases": [],
|
||||||
|
"hidden": false,
|
||||||
|
"path": "/packages/gradle",
|
||||||
|
"schema": null,
|
||||||
|
"type": "migration",
|
||||||
|
"examplesFile": "#### Change dev.nx.gradle.project-graph to version 0.1.2\n\nChange dev.nx.gradle.project-graph to version 0.1.2 in build file\n\n#### Sample Code Changes\n\n{% tabs %}\n{% tab label=\"Before\" %}\n\n```{% fileName=\"build.gradle\" %}\nplugins {\n\tid \"dev.nx.gradle.project-graph\" version \"0.1.0\"\n}\n```\n\n{% /tab %}\n{% tab label=\"After\" %}\n\n```{% fileName=\"build.gradle\" %}\nplugins {\n id \"dev.nx.gradle.project-graph\" version \"0.1.2\"\n}\n```\n\n{% /tab %}\n{% /tabs %}\n"
|
||||||
|
}
|
||||||
@ -35,6 +35,12 @@
|
|||||||
"cli": "nx",
|
"cli": "nx",
|
||||||
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
|
"description": "Change dev.nx.gradle.project-graph to version 0.1.0 in build file",
|
||||||
"factory": "./src/migrations/21-1-2/change-plugin-version-0-1-0"
|
"factory": "./src/migrations/21-1-2/change-plugin-version-0-1-0"
|
||||||
|
},
|
||||||
|
"change-plugin-version-0-1-2": {
|
||||||
|
"version": "21.3.0-beta.0",
|
||||||
|
"cli": "nx",
|
||||||
|
"description": "Change dev.nx.gradle.project-graph to version 0.1.2 in build file",
|
||||||
|
"factory": "./src/migrations/21-3-0/change-plugin-version-0-1-2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"packageJsonUpdates": {}
|
"packageJsonUpdates": {}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ plugins {
|
|||||||
|
|
||||||
group = "dev.nx.gradle"
|
group = "dev.nx.gradle"
|
||||||
|
|
||||||
version = "0.0.1-alpha.6"
|
version = "0.1.2"
|
||||||
|
|
||||||
repositories { mavenCentral() }
|
repositories { mavenCentral() }
|
||||||
|
|
||||||
|
|||||||
@ -12,10 +12,13 @@ private val testFileNameRegex =
|
|||||||
Regex("^(?!(abstract|fake)).*?(Test)(s)?\\d*", RegexOption.IGNORE_CASE)
|
Regex("^(?!(abstract|fake)).*?(Test)(s)?\\d*", RegexOption.IGNORE_CASE)
|
||||||
|
|
||||||
private val packageDeclarationRegex =
|
private val packageDeclarationRegex =
|
||||||
Regex("""package\s+([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)""")
|
Regex(
|
||||||
|
"""^\s*package\s+([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)""",
|
||||||
|
RegexOption.MULTILINE)
|
||||||
private val classDeclarationRegex =
|
private val classDeclarationRegex =
|
||||||
Regex("""^\s*(?:@[\w]+)?\s*(class|object)\s+([A-Za-z_][A-Za-z0-9_]*)""")
|
Regex(
|
||||||
private val privateClassRegex = Regex("""\bprivate\s+(class|object)\s+([A-Za-z_][A-Za-z0-9_]*)""")
|
"""^\s*(?:@[\w]+\s*)*(?:public|protected|internal|open|sealed|final|data|enum|annotation)?\s*(class)\s+([A-Za-z_][A-Za-z0-9_]*)""")
|
||||||
|
private val privateClassRegex = Regex("""\bprivate\s+class\s+([A-Za-z_][A-Za-z0-9_]*)""")
|
||||||
|
|
||||||
// Essential annotations (most common subset)
|
// Essential annotations (most common subset)
|
||||||
private val essentialTestAnnotations =
|
private val essentialTestAnnotations =
|
||||||
|
|||||||
@ -84,8 +84,8 @@ fun processTargetsForProject(
|
|||||||
|
|
||||||
val testTasks = project.getTasksByName("test", false)
|
val testTasks = project.getTasksByName("test", false)
|
||||||
val intTestTasks = project.getTasksByName("intTest", false)
|
val intTestTasks = project.getTasksByName("intTest", false)
|
||||||
val hasCiTestTarget = ciTestTargetName != null && testTasks.isNotEmpty()
|
val hasCiTestTarget = ciTestTargetName != null && testTasks.isNotEmpty() && atomized
|
||||||
val hasCiIntTestTarget = ciIntTestTargetName != null && intTestTasks.isNotEmpty()
|
val hasCiIntTestTarget = ciIntTestTargetName != null && intTestTasks.isNotEmpty() && atomized
|
||||||
|
|
||||||
project.tasks.forEach { task ->
|
project.tasks.forEach { task ->
|
||||||
try {
|
try {
|
||||||
@ -111,7 +111,7 @@ fun processTargetsForProject(
|
|||||||
|
|
||||||
targets[taskName] = target
|
targets[taskName] = target
|
||||||
|
|
||||||
if (hasCiTestTarget && task.name.startsWith("compileTest") && atomized) {
|
if (hasCiTestTarget && task.name.startsWith("compileTest")) {
|
||||||
addTestCiTargets(
|
addTestCiTargets(
|
||||||
task.inputs.sourceFiles,
|
task.inputs.sourceFiles,
|
||||||
projectBuildPath,
|
projectBuildPath,
|
||||||
@ -124,7 +124,7 @@ fun processTargetsForProject(
|
|||||||
ciTestTargetName!!)
|
ciTestTargetName!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasCiIntTestTarget && task.name.startsWith("compileIntTest") && atomized) {
|
if (hasCiIntTestTarget && task.name.startsWith("compileIntTest")) {
|
||||||
addTestCiTargets(
|
addTestCiTargets(
|
||||||
task.inputs.sourceFiles,
|
task.inputs.sourceFiles,
|
||||||
projectBuildPath,
|
projectBuildPath,
|
||||||
@ -137,23 +137,22 @@ fun processTargetsForProject(
|
|||||||
ciIntTestTargetName!!)
|
ciIntTestTargetName!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ciTestTargetName != null || ciIntTestTargetName != null) {
|
||||||
val ciCheckTargetName = targetNameOverrides.getOrDefault("ciCheckTargetName", "check-ci")
|
val ciCheckTargetName = targetNameOverrides.getOrDefault("ciCheckTargetName", "check-ci")
|
||||||
if (task.name == "check") {
|
if (task.name == "check") {
|
||||||
val replacedDependencies =
|
val replacedDependencies =
|
||||||
(target["dependsOn"] as? List<*>)?.map { dep ->
|
(target["dependsOn"] as? List<*>)?.map { dep ->
|
||||||
val dependsOn = dep.toString()
|
val dependsOn = dep.toString()
|
||||||
if (hasCiTestTarget && dependsOn == "${project.name}:$testTargetName" && atomized) {
|
if (hasCiTestTarget && dependsOn == "${project.name}:$testTargetName") {
|
||||||
"${project.name}:$ciTestTargetName"
|
"${project.name}:$ciTestTargetName"
|
||||||
} else if (hasCiIntTestTarget &&
|
} else if (hasCiIntTestTarget &&
|
||||||
dependsOn == "${project.name}:$intTestTargetName" &&
|
dependsOn == "${project.name}:$intTestTargetName") {
|
||||||
atomized) {
|
|
||||||
"${project.name}:$ciIntTestTargetName"
|
"${project.name}:$ciIntTestTargetName"
|
||||||
} else {
|
} else {
|
||||||
dep
|
dep
|
||||||
}
|
}
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
|
|
||||||
if (atomized) {
|
|
||||||
val newTarget: MutableMap<String, Any?> =
|
val newTarget: MutableMap<String, Any?> =
|
||||||
mutableMapOf(
|
mutableMapOf(
|
||||||
"dependsOn" to replacedDependencies,
|
"dependsOn" to replacedDependencies,
|
||||||
@ -165,21 +164,19 @@ fun processTargetsForProject(
|
|||||||
ensureTargetGroupExists(targetGroups, testCiTargetGroup)
|
ensureTargetGroupExists(targetGroups, testCiTargetGroup)
|
||||||
targetGroups[testCiTargetGroup]?.add(ciCheckTargetName)
|
targetGroups[testCiTargetGroup]?.add(ciCheckTargetName)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (task.name == "build") {
|
if (task.name == "build") {
|
||||||
val ciBuildTargetName = targetNameOverrides.getOrDefault("ciBuildTargetName", "build-ci")
|
val ciBuildTargetName = targetNameOverrides.getOrDefault("ciBuildTargetName", "build-ci")
|
||||||
val replacedDependencies =
|
val replacedDependencies =
|
||||||
(target["dependsOn"] as? List<*>)?.map { dep ->
|
(target["dependsOn"] as? List<*>)?.map { dep ->
|
||||||
val dependsOn = dep.toString()
|
val dependsOn = dep.toString()
|
||||||
if (dependsOn == "${project.name}:check" && atomized) {
|
if (dependsOn == "${project.name}:check") {
|
||||||
"${project.name}:$ciCheckTargetName"
|
"${project.name}:$ciCheckTargetName"
|
||||||
} else {
|
} else {
|
||||||
dep
|
dep
|
||||||
}
|
}
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
|
|
||||||
if (atomized) {
|
|
||||||
val newTarget: MutableMap<String, Any?> =
|
val newTarget: MutableMap<String, Any?> =
|
||||||
mutableMapOf(
|
mutableMapOf(
|
||||||
"dependsOn" to replacedDependencies,
|
"dependsOn" to replacedDependencies,
|
||||||
@ -199,5 +196,6 @@ fun processTargetsForProject(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info("Final targets in processTargetsForProject: $targets")
|
||||||
return GradleTargets(targets, targetGroups, externalNodes)
|
return GradleTargets(targets, targetGroups, externalNodes)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,10 @@ class ClassDetectionTest {
|
|||||||
fun `detects top-level and annotated nested classes only`() {
|
fun `detects top-level and annotated nested classes only`() {
|
||||||
val kotlinSource =
|
val kotlinSource =
|
||||||
"""
|
"""
|
||||||
|
import some.package
|
||||||
|
|
||||||
|
package real.package
|
||||||
|
|
||||||
class ClassA {
|
class ClassA {
|
||||||
@Nested
|
@Nested
|
||||||
class ClassB
|
class ClassB
|
||||||
@ -18,6 +22,10 @@ class ClassDetectionTest {
|
|||||||
private class ClassD
|
private class ClassD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class ClassU
|
||||||
|
|
||||||
|
public abstract class ClassV
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
class ClassX // not nested — should be ignored
|
class ClassX // not nested — should be ignored
|
||||||
|
|
||||||
@ -36,7 +44,11 @@ class ClassDetectionTest {
|
|||||||
val result = getAllVisibleClassesWithNestedAnnotation(tempFile)
|
val result = getAllVisibleClassesWithNestedAnnotation(tempFile)
|
||||||
|
|
||||||
// Expected output
|
// Expected output
|
||||||
val expected = mapOf("ClassAClassB" to "ClassA\$ClassB", "ClassZ" to "ClassZ")
|
val expected =
|
||||||
|
mapOf(
|
||||||
|
"ClassAClassB" to "real.package.ClassA\$ClassB",
|
||||||
|
"ClassU" to "real.package.ClassU",
|
||||||
|
"ClassZ" to "real.package.ClassZ")
|
||||||
|
|
||||||
assertEquals(expected, result)
|
assertEquals(expected, result)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package dev.nx.gradle.utils
|
package dev.nx.gradle.utils
|
||||||
|
|
||||||
import dev.nx.gradle.data.*
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
import org.gradle.testfixtures.ProjectBuilder
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
@ -11,7 +10,7 @@ class CreateNodeForProjectTest {
|
|||||||
fun `should return GradleNodeReport with targets and metadata`() {
|
fun `should return GradleNodeReport with targets and metadata`() {
|
||||||
// Arrange
|
// Arrange
|
||||||
val workspaceRoot = createTempDir("workspace").absolutePath
|
val workspaceRoot = createTempDir("workspace").absolutePath
|
||||||
val projectDir = createTempDir("project")
|
val projectDir = File(workspaceRoot, "project-a").apply { mkdirs() }
|
||||||
val project = ProjectBuilder.builder().withProjectDir(projectDir).build()
|
val project = ProjectBuilder.builder().withProjectDir(projectDir).build()
|
||||||
|
|
||||||
// Create a couple of dummy tasks
|
// Create a couple of dummy tasks
|
||||||
@ -51,104 +50,4 @@ class CreateNodeForProjectTest {
|
|||||||
assertTrue(result.dependencies.isEmpty(), "Expected no dependencies")
|
assertTrue(result.dependencies.isEmpty(), "Expected no dependencies")
|
||||||
assertTrue(result.externalNodes.isEmpty(), "Expected no external nodes")
|
assertTrue(result.externalNodes.isEmpty(), "Expected no external nodes")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `should not generate atomized targets when atomized is false`() {
|
|
||||||
// Arrange
|
|
||||||
val workspaceRoot = createTempDir("workspace").absolutePath
|
|
||||||
val projectDir = createTempDir("project")
|
|
||||||
val project = ProjectBuilder.builder().withProjectDir(projectDir).build()
|
|
||||||
|
|
||||||
// Create tasks that would normally trigger atomized targets
|
|
||||||
val testFile1 =
|
|
||||||
File(projectDir, "src/test/kotlin/MyFirstTest.kt").apply {
|
|
||||||
parentFile.mkdirs()
|
|
||||||
writeText("@Test class MyFirstTest")
|
|
||||||
}
|
|
||||||
|
|
||||||
val testTask =
|
|
||||||
project.task("test").apply {
|
|
||||||
group = "verification"
|
|
||||||
description = "Runs the tests"
|
|
||||||
inputs.files(project.files(testFile1))
|
|
||||||
}
|
|
||||||
project
|
|
||||||
.task("compileTestKotlin")
|
|
||||||
.dependsOn(testTask) // This task name triggers ci test target logic
|
|
||||||
|
|
||||||
val checkTask =
|
|
||||||
project.task("check").apply {
|
|
||||||
group = "verification"
|
|
||||||
description = "Runs all checks"
|
|
||||||
dependsOn(testTask)
|
|
||||||
}
|
|
||||||
project.task("build").apply {
|
|
||||||
group = "build"
|
|
||||||
description = "Assembles and tests"
|
|
||||||
dependsOn(checkTask)
|
|
||||||
}
|
|
||||||
|
|
||||||
val targetNameOverrides =
|
|
||||||
mapOf(
|
|
||||||
"ciTestTargetName" to "ci-test",
|
|
||||||
"ciCheckTargetName" to "ci-check",
|
|
||||||
"ciBuildTargetName" to "ci-build")
|
|
||||||
|
|
||||||
// Act
|
|
||||||
val result =
|
|
||||||
createNodeForProject(
|
|
||||||
project = project,
|
|
||||||
targetNameOverrides = targetNameOverrides,
|
|
||||||
workspaceRoot = workspaceRoot,
|
|
||||||
atomized = false) // Test with atomized = false
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
val projectRoot = project.projectDir.absolutePath
|
|
||||||
val projectNode = result.nodes[projectRoot]
|
|
||||||
assertNotNull(projectNode, "ProjectNode should not be null")
|
|
||||||
|
|
||||||
// Verify that individual atomized targets are NOT created
|
|
||||||
assertFalse(
|
|
||||||
projectNode.targets.containsKey("ci--MyFirstTest"),
|
|
||||||
"Expected ci--MyFirstTest target NOT to be present")
|
|
||||||
|
|
||||||
// Verify 'test' and 'check' targets are present but not their 'ci' counterparts if atomized is
|
|
||||||
// false
|
|
||||||
assertNotNull(projectNode.targets["test"], "Expected 'test' target to be present")
|
|
||||||
assertNotNull(projectNode.targets["check"], "Expected 'check' target to be present")
|
|
||||||
assertNotNull(projectNode.targets["build"], "Expected 'build' target to be present")
|
|
||||||
|
|
||||||
// Verify that 'ci-test', 'ci-check', 'ci-build' are not created as main targets if atomized is
|
|
||||||
// false
|
|
||||||
assertFalse(
|
|
||||||
projectNode.targets.containsKey("ci-test"),
|
|
||||||
"Expected ci-test target NOT to be present as a main target")
|
|
||||||
assertFalse(
|
|
||||||
projectNode.targets.containsKey("ci-check"),
|
|
||||||
"Expected ci-check target NOT to be present as a main target")
|
|
||||||
assertFalse(
|
|
||||||
projectNode.targets.containsKey("ci-build"),
|
|
||||||
"Expected ci-build target NOT to be present as a main target")
|
|
||||||
|
|
||||||
// Verify dependencies are NOT rewritten for 'check' and 'build' tasks
|
|
||||||
val checkTarget = projectNode.targets["check"]
|
|
||||||
assertNotNull(checkTarget, "Check target should exist")
|
|
||||||
val checkDependsOn = checkTarget["dependsOn"] as? List<*>
|
|
||||||
assertNotNull(checkDependsOn, "Check dependsOn should not be null")
|
|
||||||
assertTrue(
|
|
||||||
checkDependsOn.contains("${project.name}:test"), "Expected 'check' to depend on 'test'")
|
|
||||||
assertFalse(
|
|
||||||
checkDependsOn.contains("${project.name}:ci-test"),
|
|
||||||
"Expected 'check' NOT to depend on 'ci-test'")
|
|
||||||
|
|
||||||
val buildTarget = projectNode.targets["build"]
|
|
||||||
assertNotNull(buildTarget, "Build target should exist")
|
|
||||||
val buildDependsOn = buildTarget["dependsOn"] as? List<*>
|
|
||||||
assertNotNull(buildDependsOn, "Build dependsOn should not be null")
|
|
||||||
assertTrue(
|
|
||||||
buildDependsOn.contains("${project.name}:check"), "Expected 'build' to depend on 'check'")
|
|
||||||
assertFalse(
|
|
||||||
buildDependsOn.contains("${project.name}:ci-check"),
|
|
||||||
"Expected 'build' NOT to depend on 'ci-check'")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,226 @@
|
|||||||
|
package dev.nx.gradle.utils
|
||||||
|
|
||||||
|
import dev.nx.gradle.data.*
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.test.*
|
||||||
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
|
|
||||||
|
class ProcessTargetsForProjectTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should process targets correctly when atomized is true`() {
|
||||||
|
// Arrange
|
||||||
|
val workspaceRoot = createTempDir("workspace").absolutePath
|
||||||
|
val projectDir = File(workspaceRoot, "project-a").apply { mkdirs() }
|
||||||
|
val project = ProjectBuilder.builder().withProjectDir(projectDir).build()
|
||||||
|
|
||||||
|
// Create tasks that would normally trigger atomized targets
|
||||||
|
val testFile1 =
|
||||||
|
File(projectDir, "src/test/kotlin/MyFirstTest.kt").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
writeText("@Test class MyFirstTest")
|
||||||
|
}
|
||||||
|
|
||||||
|
val testTask =
|
||||||
|
project.task("test").apply {
|
||||||
|
group = "verification"
|
||||||
|
description = "Runs the tests"
|
||||||
|
inputs.files(project.files(testFile1))
|
||||||
|
}
|
||||||
|
project.task("compileTestKotlin").apply { inputs.files(project.files(testFile1)) }
|
||||||
|
|
||||||
|
val checkTask =
|
||||||
|
project.task("check").apply {
|
||||||
|
group = "verification"
|
||||||
|
description = "Runs all checks"
|
||||||
|
dependsOn(testTask)
|
||||||
|
}
|
||||||
|
project.task("build").apply {
|
||||||
|
group = "build"
|
||||||
|
description = "Assembles and tests"
|
||||||
|
dependsOn(checkTask)
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetNameOverrides =
|
||||||
|
mapOf(
|
||||||
|
"ciTestTargetName" to "ci-test",
|
||||||
|
"ciCheckTargetName" to "ci-check",
|
||||||
|
"ciBuildTargetName" to "ci-build")
|
||||||
|
|
||||||
|
val dependencies = mutableSetOf<Dependency>() // Empty for this test's scope
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val gradleTargets =
|
||||||
|
processTargetsForProject(
|
||||||
|
project = project,
|
||||||
|
dependencies = dependencies,
|
||||||
|
targetNameOverrides = targetNameOverrides,
|
||||||
|
workspaceRoot = workspaceRoot,
|
||||||
|
atomized = true)
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// Verify 'ci-test' should not be presented
|
||||||
|
// But 'ci-check' and 'ci-build' targets should be present in the returned targets
|
||||||
|
assertNull(
|
||||||
|
gradleTargets.targets["ci-test"],
|
||||||
|
"Expected ci-test target to NOT be present in processed targets")
|
||||||
|
assertNotNull(
|
||||||
|
gradleTargets.targets["ci-check"],
|
||||||
|
"Expected ci-check target to be present in processed targets")
|
||||||
|
assertNotNull(
|
||||||
|
gradleTargets.targets["ci-build"],
|
||||||
|
"Expected ci-build target to be present in processed targets")
|
||||||
|
|
||||||
|
// Verify dependencies are rewritten for 'check' and 'build' tasks in the returned targets
|
||||||
|
val checkTarget = gradleTargets.targets["check"]
|
||||||
|
assertNotNull(checkTarget, "Check target should exist in processed targets")
|
||||||
|
val checkDependsOn = checkTarget["dependsOn"] as? List<*>
|
||||||
|
assertNotNull(checkDependsOn, "Check dependsOn should not be null in processed targets")
|
||||||
|
assertTrue(
|
||||||
|
checkDependsOn.contains("${project.name}:test"),
|
||||||
|
"Expected 'check' to depend on 'test' in processed targets")
|
||||||
|
|
||||||
|
val checkCiTarget = gradleTargets.targets["ci-check"]
|
||||||
|
assertNotNull(checkCiTarget, "Check CI target should exist in processed targets")
|
||||||
|
val checkCiDependsOn = checkCiTarget["dependsOn"] as? List<*>
|
||||||
|
assertNotNull(checkCiDependsOn, "Check CI dependsOn should not be null in processed targets")
|
||||||
|
assertTrue(
|
||||||
|
checkCiDependsOn.contains("${project.name}:ci-test"),
|
||||||
|
"Expected 'ci-check' to depend on 'ci-test' in processed targets")
|
||||||
|
|
||||||
|
val buildTarget = gradleTargets.targets["build"]
|
||||||
|
assertNotNull(buildTarget, "Build target should exist in processed targets")
|
||||||
|
val buildDependsOn = buildTarget["dependsOn"] as? List<*>
|
||||||
|
assertNotNull(buildDependsOn, "Build dependsOn should not be null in processed targets")
|
||||||
|
assertTrue(
|
||||||
|
buildDependsOn.contains("${project.name}:check"),
|
||||||
|
"Expected 'build' to depend on 'check' in processed targets")
|
||||||
|
|
||||||
|
val buildCiTarget = gradleTargets.targets["ci-build"]
|
||||||
|
assertNotNull(buildCiTarget, "Build CI target should exist in processed targets")
|
||||||
|
val buildCiDependsOn = buildCiTarget["dependsOn"] as? List<*>
|
||||||
|
assertNotNull(buildCiDependsOn, "Build CI dependsOn should not be null in processed targets")
|
||||||
|
assertTrue(
|
||||||
|
buildCiDependsOn.contains("${project.name}:ci-check"),
|
||||||
|
"Expected 'ci-build' to depend on 'ci-check' in processed targets")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `should process targets correctly when atomized is false`() {
|
||||||
|
// Arrange
|
||||||
|
val workspaceRoot = createTempDir("workspace").absolutePath
|
||||||
|
val projectDir = File(workspaceRoot, "project-a").apply { mkdirs() }
|
||||||
|
val project = ProjectBuilder.builder().withProjectDir(projectDir).build()
|
||||||
|
|
||||||
|
// Create tasks that would normally trigger atomized targets
|
||||||
|
val testFile1 =
|
||||||
|
File(projectDir, "src/test/kotlin/MyFirstTest.kt").apply {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
writeText("@Test class MyFirstTest")
|
||||||
|
}
|
||||||
|
|
||||||
|
val testTask =
|
||||||
|
project.task("test").apply {
|
||||||
|
group = "verification"
|
||||||
|
description = "Runs the tests"
|
||||||
|
inputs.files(project.files(testFile1))
|
||||||
|
}
|
||||||
|
project
|
||||||
|
.task("compileTestKotlin")
|
||||||
|
.dependsOn(testTask) // This task name triggers ci test target logic
|
||||||
|
|
||||||
|
val checkTask =
|
||||||
|
project.task("check").apply {
|
||||||
|
group = "verification"
|
||||||
|
description = "Runs all checks"
|
||||||
|
dependsOn(testTask)
|
||||||
|
}
|
||||||
|
project.task("build").apply {
|
||||||
|
group = "build"
|
||||||
|
description = "Assembles and tests"
|
||||||
|
dependsOn(checkTask)
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetNameOverrides =
|
||||||
|
mapOf(
|
||||||
|
"ciTestTargetName" to "ci-test",
|
||||||
|
"ciCheckTargetName" to "ci-check",
|
||||||
|
"ciBuildTargetName" to "ci-build")
|
||||||
|
|
||||||
|
val dependencies = mutableSetOf<Dependency>() // Empty for this test's scope
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val gradleTargets =
|
||||||
|
processTargetsForProject(
|
||||||
|
project = project,
|
||||||
|
dependencies = dependencies,
|
||||||
|
targetNameOverrides = targetNameOverrides,
|
||||||
|
workspaceRoot = workspaceRoot,
|
||||||
|
atomized = false) // Test with atomized = false
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// Verify that individual atomized targets are NOT created
|
||||||
|
assertFalse(
|
||||||
|
gradleTargets.targets.containsKey("ci--MyFirstTest"),
|
||||||
|
"Expected ci--MyFirstTest target NOT to be present in processed targets")
|
||||||
|
|
||||||
|
// Verify 'test' and 'check' targets are present but not their 'ci' counterparts if atomized is
|
||||||
|
// false
|
||||||
|
assertNotNull(gradleTargets.targets["test"], "Expected 'test' target to be present")
|
||||||
|
assertNotNull(gradleTargets.targets["check"], "Expected 'check' target to be present")
|
||||||
|
assertNotNull(gradleTargets.targets["build"], "Expected 'build' target to be present")
|
||||||
|
|
||||||
|
// Verify that 'ci-test' is not created as main targets if atomized is false
|
||||||
|
// 'ci-check' and 'ci-build should still be presented if ciTestTargetName is presented
|
||||||
|
// regardless of atomized value
|
||||||
|
assertFalse(
|
||||||
|
gradleTargets.targets.containsKey("ci-test"),
|
||||||
|
"Expected ci-test target NOT to be present as a main target")
|
||||||
|
assertTrue(
|
||||||
|
gradleTargets.targets.containsKey("ci-check"),
|
||||||
|
"Expected ci-check target to be present as a main target")
|
||||||
|
assertTrue(
|
||||||
|
gradleTargets.targets.containsKey("ci-build"),
|
||||||
|
"Expected ci-build target to be present as a main target")
|
||||||
|
|
||||||
|
// Verify dependencies are NOT rewritten for 'check' and 'build' tasks
|
||||||
|
val checkTarget = gradleTargets.targets["check"]
|
||||||
|
assertNotNull(checkTarget, "Check target should exist")
|
||||||
|
val checkDependsOn = checkTarget["dependsOn"] as? List<*>
|
||||||
|
assertNotNull(checkDependsOn, "Check dependsOn should not be null")
|
||||||
|
assertTrue(
|
||||||
|
checkDependsOn.contains("${project.name}:test"), "Expected 'check' to depend on 'test'")
|
||||||
|
assertFalse(
|
||||||
|
checkDependsOn.contains("${project.name}:ci-test"),
|
||||||
|
"Expected 'check' NOT to depend on 'ci-test'")
|
||||||
|
|
||||||
|
val checkCiTarget = gradleTargets.targets["ci-check"]
|
||||||
|
assertNotNull(checkCiTarget, "Check CI target should exist in processed targets")
|
||||||
|
val checkCiDependsOn = checkCiTarget["dependsOn"] as? List<*>
|
||||||
|
assertNotNull(checkCiDependsOn, "Check CI dependsOn should not be null in processed targets")
|
||||||
|
assertFalse(
|
||||||
|
checkCiDependsOn.contains("${project.name}:ci-test"),
|
||||||
|
"Expected 'ci-check' to NOT depend on 'ci-test' in processed targets")
|
||||||
|
assertTrue(
|
||||||
|
checkCiDependsOn.contains("${project.name}:test"),
|
||||||
|
"Expected 'ci-check' to depend on 'test' in processed targets")
|
||||||
|
|
||||||
|
val buildTarget = gradleTargets.targets["build"]
|
||||||
|
assertNotNull(buildTarget, "Build target should exist")
|
||||||
|
val buildDependsOn = buildTarget["dependsOn"] as? List<*>
|
||||||
|
assertNotNull(buildDependsOn, "Build dependsOn should not be null")
|
||||||
|
assertTrue(
|
||||||
|
buildDependsOn.contains("${project.name}:check"), "Expected 'build' to depend on 'check'")
|
||||||
|
assertFalse(
|
||||||
|
buildDependsOn.contains("${project.name}:ci-check"),
|
||||||
|
"Expected 'build' NOT to depend on 'ci-check'")
|
||||||
|
|
||||||
|
val buildCiTarget = gradleTargets.targets["ci-build"]
|
||||||
|
assertNotNull(buildCiTarget, "Build CI target should exist in processed targets")
|
||||||
|
val buildCiDependsOn = buildCiTarget["dependsOn"] as? List<*>
|
||||||
|
assertNotNull(buildCiDependsOn, "Build CI dependsOn should not be null in processed targets")
|
||||||
|
assertTrue(
|
||||||
|
buildCiDependsOn.contains("${project.name}:ci-check"),
|
||||||
|
"Expected 'ci-build' to depend on 'ci-check' in processed targets")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
#### Change dev.nx.gradle.project-graph to version 0.1.2
|
||||||
|
|
||||||
|
Change dev.nx.gradle.project-graph to version 0.1.2 in build file
|
||||||
|
|
||||||
|
#### Sample Code Changes
|
||||||
|
|
||||||
|
{% tabs %}
|
||||||
|
{% tab label="Before" %}
|
||||||
|
|
||||||
|
```{% fileName="build.gradle" %}
|
||||||
|
plugins {
|
||||||
|
id "dev.nx.gradle.project-graph" version "0.1.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /tab %}
|
||||||
|
{% tab label="After" %}
|
||||||
|
|
||||||
|
```{% fileName="build.gradle" %}
|
||||||
|
plugins {
|
||||||
|
id "dev.nx.gradle.project-graph" version "0.1.2"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% /tab %}
|
||||||
|
{% /tabs %}
|
||||||
@ -0,0 +1,128 @@
|
|||||||
|
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||||
|
import { Tree } from '@nx/devkit';
|
||||||
|
import { FsTree } from 'nx/src/generators/tree';
|
||||||
|
import update from './change-plugin-version-0-1-2';
|
||||||
|
import { gradleProjectGraphPluginName } from '../../utils/versions';
|
||||||
|
|
||||||
|
describe('change-plugin-version-0-1-2 migration', () => {
|
||||||
|
let tempFs: TempFs;
|
||||||
|
let cwd: string;
|
||||||
|
let tree: Tree;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
tempFs = new TempFs('test');
|
||||||
|
cwd = process.cwd();
|
||||||
|
process.chdir(tempFs.tempDir);
|
||||||
|
tree = new FsTree(tempFs.tempDir, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetModules();
|
||||||
|
process.chdir(cwd);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update plugin version to 0.1.2 in Groovy DSL', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'nx.json': JSON.stringify({
|
||||||
|
plugins: ['@nx/gradle'],
|
||||||
|
}),
|
||||||
|
'proj/settings.gradle': '',
|
||||||
|
'proj/build.gradle': `plugins {
|
||||||
|
id 'java'
|
||||||
|
id "${gradleProjectGraphPluginName}" version "0.0.1"
|
||||||
|
}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
await update(tree);
|
||||||
|
|
||||||
|
const content = tree.read('proj/build.gradle', 'utf-8');
|
||||||
|
expect(content).toContain(
|
||||||
|
`id "${gradleProjectGraphPluginName}" version "0.1.2"`
|
||||||
|
);
|
||||||
|
expect(content).not.toContain('version "0.0.1"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update plugin version to 0.1.2 in Kotlin DSL', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'nx.json': JSON.stringify({
|
||||||
|
plugins: ['@nx/gradle'],
|
||||||
|
}),
|
||||||
|
'proj/settings.gradle.kts': '',
|
||||||
|
'proj/build.gradle.kts': `plugins {
|
||||||
|
id("java")
|
||||||
|
id("${gradleProjectGraphPluginName}") version("0.0.1")
|
||||||
|
}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
await update(tree);
|
||||||
|
|
||||||
|
const content = tree.read('proj/build.gradle.kts', 'utf-8');
|
||||||
|
expect(content).toContain(
|
||||||
|
`id("${gradleProjectGraphPluginName}") version("0.1.2")`
|
||||||
|
);
|
||||||
|
expect(content).not.toContain('version("0.0.1")');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not update if nx.json is missing', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'proj/settings.gradle': '',
|
||||||
|
'proj/build.gradle': `plugins {
|
||||||
|
id 'java'
|
||||||
|
id "${gradleProjectGraphPluginName}" version "0.0.1"
|
||||||
|
}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
await update(tree);
|
||||||
|
|
||||||
|
const content = tree.read('proj/build.gradle', 'utf-8');
|
||||||
|
expect(content).toContain('version "0.0.1"');
|
||||||
|
expect(content).not.toContain('version "0.1.2"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not update if Gradle plugin is not present', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'nx.json': JSON.stringify({}),
|
||||||
|
'proj/settings.gradle': '',
|
||||||
|
'proj/build.gradle': `plugins {
|
||||||
|
id 'java'
|
||||||
|
}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
await update(tree);
|
||||||
|
|
||||||
|
const content = tree.read('proj/build.gradle', 'utf-8');
|
||||||
|
expect(content).not.toContain(gradleProjectGraphPluginName);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle multiple build.gradle files', async () => {
|
||||||
|
await tempFs.createFiles({
|
||||||
|
'nx.json': JSON.stringify({
|
||||||
|
plugins: ['@nx/gradle'],
|
||||||
|
}),
|
||||||
|
'proj1/settings.gradle': '',
|
||||||
|
'proj1/build.gradle': `plugins {
|
||||||
|
id 'java'
|
||||||
|
id "${gradleProjectGraphPluginName}" version "0.0.1"
|
||||||
|
}`,
|
||||||
|
'proj2/settings.gradle': '',
|
||||||
|
'proj2/build.gradle': `plugins {
|
||||||
|
id 'java'
|
||||||
|
id "${gradleProjectGraphPluginName}" version "0.0.1"
|
||||||
|
}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
await update(tree);
|
||||||
|
|
||||||
|
const proj1Content = tree.read('proj1/build.gradle', 'utf-8');
|
||||||
|
const proj2Content = tree.read('proj2/build.gradle', 'utf-8');
|
||||||
|
|
||||||
|
expect(proj1Content).toContain(
|
||||||
|
`id "${gradleProjectGraphPluginName}" version "0.1.2"`
|
||||||
|
);
|
||||||
|
expect(proj2Content).toContain(
|
||||||
|
`id "${gradleProjectGraphPluginName}" version "0.1.2"`
|
||||||
|
);
|
||||||
|
expect(proj1Content).not.toContain('version "0.0.1"');
|
||||||
|
expect(proj2Content).not.toContain('version "0.0.1"');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { Tree, readNxJson } from '@nx/devkit';
|
||||||
|
import { hasGradlePlugin } from '../../utils/has-gradle-plugin';
|
||||||
|
import { addNxProjectGraphPlugin } from '../../generators/init/gradle-project-graph-plugin-utils';
|
||||||
|
|
||||||
|
/* Change the plugin version to 0.1.2
|
||||||
|
*/
|
||||||
|
export default async function update(tree: Tree) {
|
||||||
|
const nxJson = readNxJson(tree);
|
||||||
|
if (!nxJson) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hasGradlePlugin(tree)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await addNxProjectGraphPlugin(tree, '0.1.2');
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user