Skip to content

Commit

Permalink
1.25.0: add Remigrate task
Browse files Browse the repository at this point in the history
  • Loading branch information
sergej-koscejev committed May 17, 2024
1 parent d66a1fb commit 2d9315f
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 1 deletion.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 1.25.0

### Added

- `Remigrate` task type to run re-runnable migrations on a project or several projects.

### Changed

- Extensions now use `--plugin-root` command line argument of backends, requiring backend versions 1.15.0 or above.

## 1.24.0

### Changed
Expand Down
12 changes: 12 additions & 0 deletions api/mps-gradle-plugin.api
Original file line number Diff line number Diff line change
Expand Up @@ -378,3 +378,15 @@ public abstract class de/itemis/mps/gradle/tasks/MpsMigrate : org/gradle/api/Def
public final fun getProjectDirectories ()Lorg/gradle/api/file/ConfigurableFileCollection;
}

public class de/itemis/mps/gradle/tasks/Remigrate : org/gradle/api/tasks/JavaExec {
public fun <init> (Lorg/gradle/api/model/ObjectFactory;Lorg/gradle/api/provider/ProviderFactory;)V
public fun exec ()V
public final fun getAdditionalClasspath ()Lorg/gradle/api/file/ConfigurableFileCollection;
protected final fun getAllProjectFiles ()Lorg/gradle/api/provider/Provider;
public final fun getFolderMacros ()Lorg/gradle/api/provider/MapProperty;
public final fun getMpsHome ()Lorg/gradle/api/file/DirectoryProperty;
public final fun getMpsVersion ()Lorg/gradle/api/provider/Property;
public final fun getPluginRoots ()Lorg/gradle/api/file/ConfigurableFileCollection;
public final fun getProjectDirectories ()Lorg/gradle/api/file/ConfigurableFileCollection;
}

2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ plugins {
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.13.2"
}

val baseVersion = "1.24.0"
val baseVersion = "1.25.0"

group = "de.itemis.mps"

Expand Down
35 changes: 35 additions & 0 deletions docs/tasks/Remigrate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## `Remigrate` Task Type

Execute re-runnable migrations and project migrations on a project or several projects.

### Usage

```groovy
import de.itemis.mps.gradle.tasks.Remigrate
plugins {
// Required in order to use the task
id("de.itemis.mps.gradle.common")
}
tasks.register('remigrate', Remigrate) {
mpsHome = mpsHomeDir
// Remigrate task can run migrations on multiple projects
projectDirectories.from(projectDir1)
projectDirectories.from(projectDir2)
}
```

Parameters:

* `mpsHome` - the home directory of the MPS distribution (or RCP) to use for testing.
* `mpsVersion` - the MPS version, such as "2021.3". Autodetected by reading `$mpsHome/build.properties` by default.
* `projectDirectories` - project directories to migrate.
* `folderMacros` - path variables/macros that are necessary to open the project. Path macros are not considered part of
Gradle build cache key.
* `pluginRoots` - directories that will be searched (recursively) for additional plugins to load.

### Operation

The task will execute re-runnable migrations and project migrations on the specified projects.
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ internal object BackendConfigurations {
internal const val GENERATE_BACKEND_CONFIGURATION_NAME = "generateBackend"
internal const val MODELCHECK_BACKEND_CONFIGURATION_NAME = "modelcheckBackend"
internal const val EXECUTE_BACKEND_CONFIGURATION_NAME = "executeBackend"
internal const val REMIGRATE_BACKEND_CONFIGURATION_NAME = "remigrateBackend"
}
7 changes: 7 additions & 0 deletions src/main/kotlin/de/itemis/mps/gradle/common.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ generateBackend.defaultDependencies {
executeBackend.defaultDependencies {
add(dependencies.create("de.itemis.mps.build-backends:execute:${MPS_BUILD_BACKENDS_VERSION}"))
}

configurations.create(BackendConfigurations.REMIGRATE_BACKEND_CONFIGURATION_NAME) {
isCanBeConsumed = false
defaultDependencies {
add(project.dependencies.create("de.itemis.mps.build-backends:remigrate:[0,2)"))
}
}
98 changes: 98 additions & 0 deletions src/main/kotlin/de/itemis/mps/gradle/tasks/Remigrate.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package de.itemis.mps.gradle.tasks

import de.itemis.mps.gradle.BackendConfigurations
import de.itemis.mps.gradle.TaskGroups
import de.itemis.mps.gradle.launcher.MpsBackendBuilder
import de.itemis.mps.gradle.launcher.MpsVersionDetection
import org.gradle.api.Incubating
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.Directory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.ProviderFactory
import org.gradle.api.tasks.*
import org.gradle.kotlin.dsl.mapProperty
import org.gradle.kotlin.dsl.newInstance
import org.gradle.kotlin.dsl.property
import org.gradle.process.CommandLineArgumentProvider
import javax.inject.Inject

@Incubating
@UntrackedTask(because = "Operates 'in place'")
open class Remigrate @Inject constructor(
objectFactory: ObjectFactory,
providerFactory: ProviderFactory
) : JavaExec() {

@get:Internal
val mpsHome: DirectoryProperty = objectFactory.directoryProperty()

@get:Input
@get:Optional
val mpsVersion: Property<String> = objectFactory.property<String>()
.convention(MpsVersionDetection.fromMpsHome(project.layout, providerFactory, mpsHome.asFile))

@get:Internal("covered by allProjectFiles")
val projectDirectories: ConfigurableFileCollection = objectFactory.fileCollection()

@get:InputFiles
@get:SkipWhenEmpty
@get:IgnoreEmptyDirectories
protected val allProjectFiles = providerFactory.provider { projectDirectories.flatMap { objectFactory.fileTree().from(it) } }

@get:Internal("Folder macros are ignored for the purposes of up-to-date checks and caching")
val folderMacros: MapProperty<String, Directory> = objectFactory.mapProperty()

@get:Classpath
val pluginRoots: ConfigurableFileCollection = objectFactory.fileCollection()

@get:Internal
val additionalClasspath: ConfigurableFileCollection =
objectFactory.fileCollection().from(initialBackendClasspath())


init {
val backendBuilder: MpsBackendBuilder = project.objects.newInstance(MpsBackendBuilder::class)
backendBuilder.withMpsHomeDirectory(mpsHome).withMpsVersion(mpsVersion).configure(this)

val backendConfig = project.configurations.named(BackendConfigurations.REMIGRATE_BACKEND_CONFIGURATION_NAME)
dependsOn(backendConfig)

argumentProviders.add(CommandLineArgumentProvider {
val result = mutableListOf<String>()

for (dir in projectDirectories) {
result.add("--project=$dir")
}

addPluginRoots(result, pluginRoots)
addLogLevel(result)
addFolderMacros(result, folderMacros)
result.add("--plugin=de.itemis.mps.buildbackends.remigrate::" +
backendConfig.get().files(backendConfig.get().dependencies.first()).first())

result
})

group = TaskGroups.MIGRATION

classpath(backendConfig)
classpath(additionalClasspath)

mainClass.set("de.itemis.mps.gradle.remigrate.MainKt")
}

@TaskAction
override fun exec() {
for (dir in projectDirectories) {
checkProjectLocation(dir)
}
super.exec()
}

private fun initialBackendClasspath() = mpsHome.asFileTree.matching {
include("lib/**/*.jar")
}
}
37 changes: 37 additions & 0 deletions src/test/kotlin/test/migration/RunMigrationsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,43 @@ class RunMigrationsTest {
assertEquals(TaskOutcome.SUCCESS, result.task(":migrate")?.outcome)
}

@Test
fun `Remigrate task works`() {
buildFile.writeText(
"""
import de.itemis.mps.gradle.tasks.Remigrate
plugins {
id("de.itemis.mps.gradle.common")
}
repositories {
mavenCentral()
maven("https://artifacts.itemis.cloud/repository/maven-mps")
}
val mps = configurations.create("mps")
dependencies {
mps("com.jetbrains:mps:2021.3.2")
}
val resolveMps by tasks.registering(Sync::class) {
from(Callable { zipTree(mps.singleFile) })
into(layout.buildDirectory.dir("mps"))
}
val remigrate by tasks.registering(Remigrate::class) {
projectDirectories.from("$mpsTestPrjLocation")
mpsHome.set(layout.dir(resolveMps.map { it.destinationDir }))
}
""".trimIndent()
)

val result = gradleRunner().withArguments("remigrate").forwardOutput().build()

assertEquals(TaskOutcome.SUCCESS, result.task(":remigrate")?.outcome)
}

private fun gradleRunner(): GradleRunner = GradleRunner.create()
.withProjectDir(testProjectDir.root)
.withPluginClasspath()
Expand Down

0 comments on commit 2d9315f

Please sign in to comment.