Создать собственный плагин, который определяет плагины и зависимости - PullRequest
0 голосов
/ 04 февраля 2020

Моя организация использует одни и те же плагины и зависимости Gradle для многих наших проектов. Мои знания о пользовательских плагинах довольно слабые, но я хотел бы объединить эти плагины и зависимости в один отдельный плагин. Я застрял в понимании того, как отделить плагины / зависимости, необходимые для плагина, от тех, которые я хочу использовать в потребляющем проекте. Вот простой пример, который я собрал на основе пользовательского документа плагина gradle и некоторой информации о хранении плагина в репозитории maven, чтобы он мог автоматически загружать зависимости :

// build.gradle from standalone plugin
plugins {
  id 'java-gradle-plugin'
  id 'maven-publish'

  // these ones I don't need in the plugin, just in the project where I apply the plugin
  id 'war'
  id 'org.springframework.boot' version '2.2.4.RELEASE'
  id 'io.spring.dependency-management' version '1.0.9.RELEASE'
  id 'org.asciidoctor.convert' version '1.5.8'
}

group = 'org.sample'
version = '1.0.0'

publishing {
  repositories {
    maven {
      url "../maven-repo"
    }
  }
}

gradlePlugin {
  plugins {
    greeting {
      id = "org.sample.greeter"
      implementationClass = "org.sample.GreetingPlugin"
    }
  }
}

dependencies {
  implementation gradleApi() // I think I need this for the imports in GreetingPlugin.java
  implementation localGroovy() // I think I would need this if GreetingPlugin was written in Groovy

  // these ones I don't need in the plugin, just in the project where I apply the plugin
  implementation 'org.springframework.boot:spring-boot-starter-web'
  testImplementation 'org.springframework.boot:spring-boot-starter-test' {
    exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
  }
  testImplementation 'org.junit.jupiter:junit-jupiter-engine'
}

// this is only needed in the project where I apply the plugin
// I believe this should be in the GreetingPlugin.java file though
test {
 useJUnitPlatform()
}

и класс поддержки ...

package org.sample;

import org.gradle.api.DefaultTask;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;

class Greeting Plugin implements Plugin<Project> {
  @Override
  public void apply(Project project) {
    project.getTasks().create("hello", MyTask.class);
  }

  public static class MyTask extends DefaultTask {
    @TaskAction
    public void myTask() {
      System.out.println("Hello, World!");
    }    
  }
}

В проекте я пытаюсь использовать плагин, у меня есть следующие файлы:

// settings.gradle
pluginManagement {
  repositories {
    maven {
      url "../maven-repo"
    }
    gradlePluginPortal()
  }
}
// build.gradle
plugins {
  id 'org.sample.greeter' version '1.0.0'
}

Я думаю, что при использовании плагина таким образом, проект наследует плагины и зависимости, перечисленные в коде плагина. Я думаю, что я близок, как когда я ./gradlew publish я вижу, что плагин применяется, но ему не нравится, что у зависимости spring-starter-web нет версии (я знаю, что когда я делаю мультипроект в gradle repo, мне нужно включить блок dependencyManagement в mavenBOM, так что, может быть, в этом ключ?) Я пытаюсь следовать плагину SpringBoot gradle для понимания, но это слишком сложно для меня.

Итак, это правильный способ создания отдельного плагина, который включает в себя плагины / зависимости, запеченные в? И почему менеджер зависимостей Spring не применяет управление версиями?


EDIT: я перешел по ссылке @Alan Hay, и вместо собственного плагина я попытался использовать «apply from». Тем не менее, это все еще не работает. Вот файлы, основанные на этом подходе:

// build.gradle from 'parent' build.gradle
plugins {
  id 'war'
  id 'org.springframework.boot' version '2.2.4.RELEASE'
  id 'io.spring.dependency-management' version '1.0.9.RELEASE'
  id 'org.asciidoctor.convert' version '1.5.8'
}

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-web'
  testImplementation 'org.springframework.boot:spring-boot-starter-test' {
    exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
  }
  testImplementation 'org.junit.jupiter:junit-jupiter-engine'
}

test {
 useJUnitPlatform()
}

и попытка ссылки из другого проекта, это единственная строка в файле:

apply from: '<path-to-above>/build.gradle'

Я получаю следующую ошибку:

  script '<path-to-above>/build.gradle': 15: Only Project build scripts can contain plugins {} blocks

  See https://docs.gradle.org/5.5.1/userguide/plugins.html#sec:plugins_block for information on the plugins {} block

   @ line 15, column 1.
     plugins {
     ^

  1 error

1 Ответ

0 голосов
/ 11 февраля 2020

Отдельный бинарный плагин является предпочтительным подходом, когда вам нужно совместно использовать одни и те же логику сборки c для нескольких независимых проектов. Кроме того, хороший дизайн плагинов отделяет возможности от условностей. В этом случае возможности предоставляются Gradle и некоторыми сторонними плагинами, но вы добавляете свои собственные соглашения сверху в этом плагине.

Когда вы реализуете это, вам, по сути, нужно 1015 * код на один уровень ниже. Все, что будет в build.gradle, должно быть в исходном коде вашего плагина. Все, что может повлиять на путь к классу сценария сборки (т. Е. buildscript { } или plugins { }), относится к зависимостям вашего плагина. Блок plugins { } в вашем плагине должен иметь только те плагины сборки, которые необходимы для сборки самого плагина.

// build.gradle from standalone plugin

// plugins {} should contain only plugins you need in the build of the plugin itself
plugins {
  id 'java-gradle-plugin'
  id 'maven-publish'
}

group = 'org.sample'
version = '1.0.0'

dependencies {
  implementation gradleApi()

  // Dependencies for plugins you will apply to the target build
  implementation 'io.spring.gradle:dependency-management-plugin:1.0.9.RELEASE'
  implementation 'org.asciidoctor:asciidoctor-gradle-jvm:2.4.0'
  implementation 'org.springframework.boot:spring-boot-gradle-plugin:2.2.4.RELEASE'
}

gradlePlugin {
  plugins {
    greeting {
      id = "org.sample.greeter"
      implementationClass = "org.sample.GreetingPlugin"
    }
  }
}

publishing {
  repositories {
    maven {
      url "../maven-repo"
    }
  }
}
package org.sample;

import org.gradle.api.DefaultTask;
import org.gradle.api.Plugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.testing.Test;

class Greeting Plugin implements Plugin<Project> {

  @Override
  public void apply(Project project) {

    // Apply plugins to the project (already on the classpath)
    project.getPluginManager().apply("war");
    project.getPluginManager().apply("org.springframework.boot");
    project.getPluginManager().apply("io.spring.dependency-management");
    project.getPluginManager().apply(" org.asciidoctor.convert");

    // Dependencies that you need for the code in the project that this plugin is applied
    DependencyHandler dependencies = project.getDependencies();
    dependencies.add(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME, "org.springframework.boot:spring-boot-starter-web");
    dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, "org.junit.jupiter:junit-jupiter-engine");
    dependencies.add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, springBootStarterTest(dependencies));

    projects.getTasks().withType(Test.class, test -> {
      test.useJUnitPlatform();
    });
  }

  private Dependency springBootStarterTest(DependencyHandler dependencies) {
    Map<String, String> exclude = new HashMap<>();
    exclude.put("group", "org.junit.vintage");
    exclude.put("module", "junit-vintage-engine");
    return ((ModuleDependency) dependencies.module("org.springframework.boot:spring-boot-starter-test")).exclude(exclude);
  }

}

Это более многословно из-за того, что написано в Java, но оно функционально эквивалентно помещению этого в build.gradle:

plugins {
  id 'war'
  id 'org.springframework.boot' version '2.2.4.RELEASE'
  id 'io.spring.dependency-management' version '1.0.9.RELEASE'
  id 'org.asciidoctor.convert' version '1.5.8'
}

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-web'
  testImplementation 'org.springframework.boot:spring-boot-starter-test' {
    exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
  }
  testImplementation 'org.junit.jupiter:junit-jupiter-engine'
}

test {
 useJUnitPlatform()
}
вашего проекта
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...