Skip to content

Commit 2d9315f

Browse files
1.25.0: add Remigrate task
1 parent d66a1fb commit 2d9315f

File tree

8 files changed

+201
-1
lines changed

8 files changed

+201
-1
lines changed

CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
33
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
44

5+
## 1.25.0
6+
7+
### Added
8+
9+
- `Remigrate` task type to run re-runnable migrations on a project or several projects.
10+
11+
### Changed
12+
13+
- Extensions now use `--plugin-root` command line argument of backends, requiring backend versions 1.15.0 or above.
14+
515
## 1.24.0
616

717
### Changed

api/mps-gradle-plugin.api

+12
Original file line numberDiff line numberDiff line change
@@ -378,3 +378,15 @@ public abstract class de/itemis/mps/gradle/tasks/MpsMigrate : org/gradle/api/Def
378378
public final fun getProjectDirectories ()Lorg/gradle/api/file/ConfigurableFileCollection;
379379
}
380380

381+
public class de/itemis/mps/gradle/tasks/Remigrate : org/gradle/api/tasks/JavaExec {
382+
public fun <init> (Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;)V
383+
public fun exec ()V
384+
public final fun getAdditionalClasspath ()Lorg/gradle/api/file/ConfigurableFileCollection;
385+
protected final fun getAllProjectFiles ()Lorg/gradle/api/provider/Provider;
386+
public final fun getFolderMacros ()Lorg/gradle/api/provider/MapProperty;
387+
public final fun getMpsHome ()Lorg/gradle/api/file/DirectoryProperty;
388+
public final fun getMpsVersion ()Lorg/gradle/api/provider/Property;
389+
public final fun getPluginRoots ()Lorg/gradle/api/file/ConfigurableFileCollection;
390+
public final fun getProjectDirectories ()Lorg/gradle/api/file/ConfigurableFileCollection;
391+
}
392+

build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ plugins {
2424
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.13.2"
2525
}
2626

27-
val baseVersion = "1.24.0"
27+
val baseVersion = "1.25.0"
2828

2929
group = "de.itemis.mps"
3030

docs/tasks/Remigrate.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## `Remigrate` Task Type
2+
3+
Execute re-runnable migrations and project migrations on a project or several projects.
4+
5+
### Usage
6+
7+
```groovy
8+
import de.itemis.mps.gradle.tasks.Remigrate
9+
10+
plugins {
11+
// Required in order to use the task
12+
id("de.itemis.mps.gradle.common")
13+
}
14+
15+
tasks.register('remigrate', Remigrate) {
16+
mpsHome = mpsHomeDir
17+
18+
// Remigrate task can run migrations on multiple projects
19+
projectDirectories.from(projectDir1)
20+
projectDirectories.from(projectDir2)
21+
}
22+
```
23+
24+
Parameters:
25+
26+
* `mpsHome` - the home directory of the MPS distribution (or RCP) to use for testing.
27+
* `mpsVersion` - the MPS version, such as "2021.3". Autodetected by reading `$mpsHome/build.properties` by default.
28+
* `projectDirectories` - project directories to migrate.
29+
* `folderMacros` - path variables/macros that are necessary to open the project. Path macros are not considered part of
30+
Gradle build cache key.
31+
* `pluginRoots` - directories that will be searched (recursively) for additional plugins to load.
32+
33+
### Operation
34+
35+
The task will execute re-runnable migrations and project migrations on the specified projects.

src/main/kotlin/de/itemis/mps/gradle/BackendConfigurations.kt

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ internal object BackendConfigurations {
44
internal const val GENERATE_BACKEND_CONFIGURATION_NAME = "generateBackend"
55
internal const val MODELCHECK_BACKEND_CONFIGURATION_NAME = "modelcheckBackend"
66
internal const val EXECUTE_BACKEND_CONFIGURATION_NAME = "executeBackend"
7+
internal const val REMIGRATE_BACKEND_CONFIGURATION_NAME = "remigrateBackend"
78
}

src/main/kotlin/de/itemis/mps/gradle/common.gradle.kts

+7
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,10 @@ generateBackend.defaultDependencies {
2020
executeBackend.defaultDependencies {
2121
add(dependencies.create("de.itemis.mps.build-backends:execute:${MPS_BUILD_BACKENDS_VERSION}"))
2222
}
23+
24+
configurations.create(BackendConfigurations.REMIGRATE_BACKEND_CONFIGURATION_NAME) {
25+
isCanBeConsumed = false
26+
defaultDependencies {
27+
add(project.dependencies.create("de.itemis.mps.build-backends:remigrate:[0,2)"))
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package de.itemis.mps.gradle.tasks
2+
3+
import de.itemis.mps.gradle.BackendConfigurations
4+
import de.itemis.mps.gradle.TaskGroups
5+
import de.itemis.mps.gradle.launcher.MpsBackendBuilder
6+
import de.itemis.mps.gradle.launcher.MpsVersionDetection
7+
import org.gradle.api.Incubating
8+
import org.gradle.api.file.ConfigurableFileCollection
9+
import org.gradle.api.file.Directory
10+
import org.gradle.api.file.DirectoryProperty
11+
import org.gradle.api.model.ObjectFactory
12+
import org.gradle.api.provider.MapProperty
13+
import org.gradle.api.provider.Property
14+
import org.gradle.api.provider.ProviderFactory
15+
import org.gradle.api.tasks.*
16+
import org.gradle.kotlin.dsl.mapProperty
17+
import org.gradle.kotlin.dsl.newInstance
18+
import org.gradle.kotlin.dsl.property
19+
import org.gradle.process.CommandLineArgumentProvider
20+
import javax.inject.Inject
21+
22+
@Incubating
23+
@UntrackedTask(because = "Operates 'in place'")
24+
open class Remigrate @Inject constructor(
25+
objectFactory: ObjectFactory,
26+
providerFactory: ProviderFactory
27+
) : JavaExec() {
28+
29+
@get:Internal
30+
val mpsHome: DirectoryProperty = objectFactory.directoryProperty()
31+
32+
@get:Input
33+
@get:Optional
34+
val mpsVersion: Property<String> = objectFactory.property<String>()
35+
.convention(MpsVersionDetection.fromMpsHome(project.layout, providerFactory, mpsHome.asFile))
36+
37+
@get:Internal("covered by allProjectFiles")
38+
val projectDirectories: ConfigurableFileCollection = objectFactory.fileCollection()
39+
40+
@get:InputFiles
41+
@get:SkipWhenEmpty
42+
@get:IgnoreEmptyDirectories
43+
protected val allProjectFiles = providerFactory.provider { projectDirectories.flatMap { objectFactory.fileTree().from(it) } }
44+
45+
@get:Internal("Folder macros are ignored for the purposes of up-to-date checks and caching")
46+
val folderMacros: MapProperty<String, Directory> = objectFactory.mapProperty()
47+
48+
@get:Classpath
49+
val pluginRoots: ConfigurableFileCollection = objectFactory.fileCollection()
50+
51+
@get:Internal
52+
val additionalClasspath: ConfigurableFileCollection =
53+
objectFactory.fileCollection().from(initialBackendClasspath())
54+
55+
56+
init {
57+
val backendBuilder: MpsBackendBuilder = project.objects.newInstance(MpsBackendBuilder::class)
58+
backendBuilder.withMpsHomeDirectory(mpsHome).withMpsVersion(mpsVersion).configure(this)
59+
60+
val backendConfig = project.configurations.named(BackendConfigurations.REMIGRATE_BACKEND_CONFIGURATION_NAME)
61+
dependsOn(backendConfig)
62+
63+
argumentProviders.add(CommandLineArgumentProvider {
64+
val result = mutableListOf<String>()
65+
66+
for (dir in projectDirectories) {
67+
result.add("--project=$dir")
68+
}
69+
70+
addPluginRoots(result, pluginRoots)
71+
addLogLevel(result)
72+
addFolderMacros(result, folderMacros)
73+
result.add("--plugin=de.itemis.mps.buildbackends.remigrate::" +
74+
backendConfig.get().files(backendConfig.get().dependencies.first()).first())
75+
76+
result
77+
})
78+
79+
group = TaskGroups.MIGRATION
80+
81+
classpath(backendConfig)
82+
classpath(additionalClasspath)
83+
84+
mainClass.set("de.itemis.mps.gradle.remigrate.MainKt")
85+
}
86+
87+
@TaskAction
88+
override fun exec() {
89+
for (dir in projectDirectories) {
90+
checkProjectLocation(dir)
91+
}
92+
super.exec()
93+
}
94+
95+
private fun initialBackendClasspath() = mpsHome.asFileTree.matching {
96+
include("lib/**/*.jar")
97+
}
98+
}

src/test/kotlin/test/migration/RunMigrationsTest.kt

+37
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,43 @@ class RunMigrationsTest {
211211
assertEquals(TaskOutcome.SUCCESS, result.task(":migrate")?.outcome)
212212
}
213213

214+
@Test
215+
fun `Remigrate task works`() {
216+
buildFile.writeText(
217+
"""
218+
import de.itemis.mps.gradle.tasks.Remigrate
219+
220+
plugins {
221+
id("de.itemis.mps.gradle.common")
222+
}
223+
224+
repositories {
225+
mavenCentral()
226+
maven("https://artifacts.itemis.cloud/repository/maven-mps")
227+
}
228+
229+
val mps = configurations.create("mps")
230+
dependencies {
231+
mps("com.jetbrains:mps:2021.3.2")
232+
}
233+
234+
val resolveMps by tasks.registering(Sync::class) {
235+
from(Callable { zipTree(mps.singleFile) })
236+
into(layout.buildDirectory.dir("mps"))
237+
}
238+
239+
val remigrate by tasks.registering(Remigrate::class) {
240+
projectDirectories.from("$mpsTestPrjLocation")
241+
mpsHome.set(layout.dir(resolveMps.map { it.destinationDir }))
242+
}
243+
""".trimIndent()
244+
)
245+
246+
val result = gradleRunner().withArguments("remigrate").forwardOutput().build()
247+
248+
assertEquals(TaskOutcome.SUCCESS, result.task(":remigrate")?.outcome)
249+
}
250+
214251
private fun gradleRunner(): GradleRunner = GradleRunner.create()
215252
.withProjectDir(testProjectDir.root)
216253
.withPluginClasspath()

0 commit comments

Comments
 (0)