Spis treści

gradle init dla Spring Boot

Produkcyjny plugin Gradle inspirowany praktykami z DPE University.

Dlaczego kolejny plugin Gradle

Ostatnio chciałem poszerzyć swoją wiedzę o Build Scanach, Develocity i ich praktycznym zastosowaniu, dlatego zacząłem przerabiać kursy na naszej platformie DPE University. Na co dzień mam styczność z Develocity od strony operacyjnej i produkcyjnej – utrzymuję między innymi instancje open source, więc zależało mi na lepszym zrozumieniu produktu, a zwłaszcza użycia od strony użytkowników, w mojej codziennej pracy inżyniera.

Aby usystematyzować zdobytą wiedzę, postanowiłem zbudować projekt zgodny z best practices omawianymi na kursach. Równolegle pracowałem nad mikroserwisem w Spring Boot, generowanym ze Spring Initializr, i zauważyłem brak pluginu Gradle, który automatyzowałby ten proces w sposób przyjazny build cache i CI/CD. W efekcie każdy nowy projekt wymagał ręcznej konfiguracji. Chciałem to uprościć i zbliżyć doświadczenie do znanego gradle init – ale w wersji dla Spring Boot.

Tak powstał gradle-springinitializr-plugin – narzędzie gotowe do użycia na produkcji, które ułatwia tworzenie projektów Spring Boot z poziomu Gradle. Ten wpis jest o tym, jak powstał, jak działa i jak możesz go wykorzystać, aby przyspieszyć start nowych projektów w swoim zespole.

Szybki start

Plugin jest open source i dostępny w Gradle - Plugins. Możesz od razu go zainstalować i używać.

Stwórz plik build.gradle oraz dodaj poniższe:

1
2
3
plugins {
    id 'io.oczadly.springinitializr' version '1.0.0'
}

Następnie stwórz plik settings.gradle i dodaj konfigurację:

1
rootProject.name = 'examples-simple-groovy'

Lub dodaj konfigurację do build.gradle w swoim istniejącym projekcie.

Dzięki temu będziesz mógł generować kolejne projekty Spring Boot z Gradle od razu podczas czytania wpisu, przyspieszając swój onboarding i codzienną pracę.

👉 Gradle - Plugins

👉 GitHub

Ten plugin traktuję jako wzorzec: jak budować produkcyjny plugin w Groovy zgodny z Gradle best practices. Jeśli sam tworzysz pluginy, możesz go użyć jako punkt odniesienia.


Dla kogo

Dla Platform Engineerów

gradle-springinitializr-plugin może stać się elementem Waszej platformy, który przyspieszy tworzenie mikroserwisów w organizacji. Dzięki niemu możecie:

✅ Szybko generować mikroserwisy Spring Boot (Groovy/Java/Kotlin, Gradle/Maven) z CLI, pipeline’ów lub automatycznych procesów GitOps.

✅ Generować projekty zawsze z aktualną wersją Spring Boot, Javy i zależności, eliminując ręczne utrzymywanie szablonów.

✅ Standaryzować strukturę projektów, metadane (groupId, artifactId, packageName, description) i proces tworzenia mikroserwisów.

Jeśli budujecie platformę inżynierską dla zespołów developerskich w ekosystemie JVM, ten plugin może stać się Waszym lekko konfigurowalnym, automatyzowalnym elementem pipeline do bardzo prostego tworzenia projektów Spring Boot.

Dla Software Engineerów

gradle-springinitializr-plugin może stać się Waszym pierwszym wyborem do szybkiego startu projektów Spring Boot bez opuszczania ekosystemu Gradle. Zamiast klikania w webowe UI Spring Initializr czy pisania curli, generujecie w pełni konfigurowalny projekt jedną komendą Gradle. To oszczędność czasu, spójność konfiguracji i od razu wpięcie w Wasz workflow build cache, CI/CD oraz konwencje zespołowe.

Dla osób ciekawych i świadomych

gradle-springinitializr-plugin pozwoli Wam w jedną minutę zobaczyć, jak wygląda proces generowania projektu Spring Boot z poziomu Gradle, bez klikania po https://start.spring.io czy pisania curli. Zamiast ręcznego ściągania ZIP-ów, od razu startujecie projekt lokalnie i możecie eksplorować Spring Boot w sposób powtarzalny, czysty i przyjazny.


Jak działa

Po zainstalowaniu gradle-springinitializr-plugin możesz generować projekty Spring Boot bezpośrednio z Gradle, bez opuszczania terminala.

Plugin udostępnia pojedynczy task initSpringBootProject, który pobiera projekt z Spring Initializr i następnie rozpakowuje go. Zamiast klikać w interfejs webowy, wystarczy uruchomić:

1
gradle initSpringBootProject

Otrzymasz:

1
2
3
4
5
6
> Task :initSpringBootProject
Downloading Spring Boot starter project...
Project downloaded to: /opt/my-projects/build/generated-project/starter.zip
Project extracted to: /opt/my-projects/build/generated-project/demo

BUILD SUCCESSFUL in 1s

Domyślnie projekt zostanie pobrany i rozpakowany do build/generated-project/demo, gotowy do otwarcia i uruchomienia.

Plugin pozwala także ustawić dowolny parametr dostępny w Spring Initializr:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
gradle initSpringBootProject \
    -PprojectType="gradle-project-kotlin" \
    -Planguage="kotlin" \
    -PgroupId="com.mycompany" \
    -PartifactId="my-spring-app" \
    -PprojectName="My Spring App" \
    -PprojectDescription="My Spring Boot application generated via gradle-springinitializr-plugin" \
    -PpackageName="com.mycompany.myspringapp" \
    -Ppackaging="war" \
    -PjavaVersion="21" \
    -Pdependencies="web,actuator"
    -PoutputDir="/opt/my-projects/my-spring-boot-app"

Dzięki temu możesz generować czyste, spójne projekty, gotowe do pracy w Twoim workflow CI/CD i zgodne z zespołowymi konwencjami – bez manualnych kroków.

Plugin wspiera także eksperymentalny tryb interaktywny wzorowany na komendzie gradle init:

https://raw.githubusercontent.com/paweloczadly/gradle-springinitializr-plugin/refs/tags/v1.0.0/docs/images/demo.gif
gradle init dla Spring Boot

Dzięki temu możesz wprowadzić wszystkie parametry projektu bez konieczności zapamiętywania flag wiersza poleceń - plugin przeprowadza go krok po kroku przez proces wyboru wersji Spring Boot, języka, typu projektu i zależności. To szczególnie przydatne dla nowych członków zespołu lub w sytuacjach, gdy chcemy szybko przygotować projekt w standardzie naszej organizacji.

UWAGA
Tryb interaktywny jest wciąż eksperymentalny: świetny do nauki i szybkiego startu. W pipeline’ach CI/CD rekomenduję jawne flagi -P.

Aby skorzystać z trybu interaktywnego, należy podążać za instrukcjami z FAQ.


Jak został zbudowany

Jak wspomniałem wcześniej, poza wykorzystaniem wiedzy z kursów DPE University, chciałem, aby ten plugin był referencyjną implementacją pod budowę kolejnych pluginów. Moim celem było stworzenie czegoś solidnego, niemal bezobsługowego oraz tak bardzo ponadczasowego, jak to możliwe.

plugin.properties

Sercem pluginu jest plik plugin.properties, który zawiera domyślne wartości parametrów. To rozwiązanie wspiera zasadę separacji kodu oraz konfiguracji - zmiany wartości nie wymagają modyfikacji ani rekompilacji kodu, tylko podmiany pliku.

Plik properties jest ładowany raz przy starcie pluginu i wartości dostępne są poprzez statyczne stałe:

1
PluginConfig.getOrThrow(PluginConstants.PLUGIN_ID)

Takie podejście upraszcza zarówno konfigurację produkcyjną, jak i testową – dając pełną kontrolę nad środowiskiem bez zmian w logice pluginu.

Wnioski z testów funkcjonalnych

Aby plugin.properties był widoczny w testach funkcjonalnych jako zasób, należy dodać w build.gradle:

1
2
3
4
5
sourceSets {
    functionalTest {
        resources.srcDir file('src/main/resources')
    }
}

Dzięki temu testy funkcjonalne korzystają z dokładnie tej samej konfiguracji co produkcyjny plugin.

convention: czysta konfiguracja pluginu

Opcje takie jak initializrUrl, metadataEndpoint i extract są zaprojektowane jako konfiguracja globalna pluginu – dotyczą źródła danych (czyli skąd pobierać projekt), a nie samego projektu (co ma zawierać). Dzięki temu plugin zachowuje separację między konfiguracją infrastrukturalną a właściwą logiką generowania.

Domyślne wartości są ustawiane przez mechanizm convention(...) w Gradle - co oznacza:

  • użytkownik nie musi nic ustawiać, aby użyć pluginu w trybie domyślnym,
  • ale może nadpisać dowolną wartość w build.gradle, jeśli chce użyć np. własnej wersji Spring Initializr lub zablokować rozpakowanie ZIP-a, jak poniżej:
1
2
3
4
5
6
7
8
9
plugins {
    id 'io.oczadly.springinitializr' version '1.0.0'
}

tasks.named('initSpringBootProject') {
    initializrUrl = 'https://your-initializr.example.com'
    metadataEndpoint = '/yours'
    extract = 'false'
}

To podejście zapewnia:

  • czystość buildów - nie trzeba mieszać konfiguracji z parametrami wywołania.
  • przewidywalność - plugin zawsze działa na jawnie zdefiniowanych danych wejściowych.
  • elastyczność - użytkownik może użyć własnego endpointu, np. w CI albo mirrorze.

Zobacz oficjalną dokumentację Gradle dotyczącą convention(...), aby dowiedzieć się, jak ustawiać przejrzyste, nadpisywalne wartości domyślne we własnych pluginach i taskach.

Wyciąganie dostępnych opcji z Metadata API

Plugin pobiera wspierane wersje między innymi Spring Boot, typów projektu oraz języków, w których można programować aplikacje po pobraniu ze Spring Initializr. Jest to dostępne przy użyciu Metadata endpoint. Dzięki temu nie ma potrzeby ciągłego aktualizowania pluginu o wspierane parametry.

Podczas dodawania wspieranych typów projektów oraz języków natknąłem się na ciekawy problem z użyciem configuration cache w Gradle. O którym poniżej.

Wnioski z używania --configuration-cache

Na początku napotkałem kilka problemów podczas testowania pluginu z flagą --configuration-cache. Początkowo sądziłem, że problem wynika z odczytu plugin.properties, ale prawdziwą przyczyną było korzystanie z API project.* w klasie rozszerzającej DefaultTask:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package io.oczadly.tasks

abstract class InitSpringBootProjectTask extends DefaultTask {

  @Internal
  final ListProperty<String> supportedProjectTypes = project.objects.listProperty String

  @Internal
  final ListProperty<String> supportedLanguages = project.objects.listProperty String

  @TaskAction
  void download() {
    /* Pozostały kod pominięty dla przejrzystości */
  }
}

To łamie mechanizm configuration cache, ponieważ Gradle wymaga, aby wszystkie dane wejściowe były jawnie zadeklarowane przy użyciu Property<T>, Provider<T> lub DirectoryProperty. Następnie w fazie wykonania nie można odwoływać się do zmiennego stanu projektu.

Rozwiązałem to przez:

  • Przeniesienie całej logiki pobierania wspieranych typów projektu i języków do metody download().

  • Upewnienie się, że @TaskAction operuje wyłącznie na właściwościach deklarowanych jako Property<T> lub Provider<T>, czyli ocenianych dopiero w czasie wykonania.

Ta zmiana nie tylko umożliwiła zgodność pluginu z configuration cache, ale też doprowadziła do czystszej, bardziej idiomatycznej implementacji zgodnej z praktykami Gradle.

Zobacz oficjalną dokumentację Gradle dotyczącą configuration cache, aby poznać wszystkie szczegóły i ograniczenia.

Parametry -P i mechanizm walidacji

Plugin akceptuje wszystkie parametry dostępne na stronie https://start.spring.io - te same, które możesz ustawić w webowym UI Spring Initializr.

Po ustawieniu przez użytkowników parametrów albo przypisania domyślnych wartości, w tasku initSpringBootProject jest robiona walidacja. Task na początku pobiera listę wspieranych wersji Spring Boot, typów projektu oraz języków z endpointu Metadata. Jeśli użytkownik poda błędną wartość parametru, która nie jest wspierana task zakończy się błędem. Na przykład:

1
gradle initSpringBootProject -Planguage=clojure

Dostanie komunikat:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
> Task :initSpringBootProject FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':initSpringBootProject'.
> Unsupported language: 'clojure'. Supported: java, kotlin, groovy.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 5s

Incremental build i build cache

Na podstawie ścieżki Gradle Build Caching na DPE University oraz wiedzy tam nabytej w pluginie zostało dodane wsparcie do incremental build oraz Build Cache. Dzięki temu kolejne uruchomienia są natychmiastowe, a rezultaty mogą być ponownie użyte.

Task initSpringBootProject deklaruje zarówno dane wejściowe (@Input), jak i dane wyjściowe (@OutputDirectory - w tym przypadku outputDir, powiązany z DirectoryProperty). To zgodne z definicją poprawnie skonfigurowanego taska w Gradle, opisaną tutaj.

Dzięki temu Gradle ma pełną kontrolę nad śledzeniem stanu wejść i wyjść, co umożliwia:

  • Pomijanie taska (UP-TO-DATE), jeśli dane wyjściowe się nie zmieniły - incremental build.
  • Przywrócenie wyników (FROM-CACHE), jeśli dane wyjściowe są w lokalnym cache - build cache.

Poniżej znajduje się przykład, jak task zachowuje się w obu przypadkach.

Incremental build

Przy pierwszym uruchomieniu pobierany jest projekt ze Spring Initializr:

1
gradle initSpringBootProject -PoutputDir=/opt/my-projects/my-spring-boot-app --console=plain --info

Zostanie wyświetlone:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21

...

Task name matched 'initSpringBootProject'
Selected primary task 'initSpringBootProject' from project :
Tasks to be executed: [task ':initSpringBootProject']
Tasks that were excluded: []
Resolve mutations for :initSpringBootProject (Thread[included builds,5,main]) started.
:initSpringBootProject (Thread[included builds,5,main]) started.

> Task :initSpringBootProject
Build cache key for task ':initSpringBootProject' is 75b4d5a65d989aa6453584fe39baeab5
Task ':initSpringBootProject' is not up-to-date because:
  No history is available.
Downloading Spring Boot starter project...
Project downloaded to: /opt/my-projects/my-spring-boot-app/starter.zip
Project extracted to: /opt/my-projects/my-spring-boot-app/demo
Stored cache entry for task ':initSpringBootProject' with cache key 75b4d5a65d989aa6453584fe39baeab5

BUILD SUCCESSFUL in 12s
5 actionable tasks: 1 executed, 4 up-to-date

Natomiast, przy ponownym uruchomieniu z tym samym parametrem -PoutputDir:

1
gradle initSpringBootProject -PoutputDir=/opt/my-projects/my-spring-boot-app --console=plain --info

Ponieważ dane wyjściowe się nie zmieniły, będzie widoczne:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
...

Task name matched 'initSpringBootProject'
Selected primary task 'initSpringBootProject' from project :
Tasks to be executed: [task ':initSpringBootProject']
Tasks that were excluded: []
Resolve mutations for :initSpringBootProject (Thread[Execution worker Thread 4,5,main]) started.
:initSpringBootProject (Thread[Execution worker Thread 4,5,main]) started.

> Task :initSpringBootProject UP-TO-DATE
Build cache key for task ':initSpringBootProject' is 75b4d5a65d989aa6453584fe39baeab5
Skipping task ':initSpringBootProject' as it is up-to-date.

BUILD SUCCESSFUL in 383ms
5 actionable tasks: 5 up-to-date

Co potwierdza, że wykorzystany jest incremental build przez oznaczenie taska etykietą UP-TO-DATE.

Build Cache

Gdy plik /opt/my-projects/my-spring-boot-app/starter.zip zostanie skasowany, a task zostanie uruchomiony ponownie:

1
gradle initSpringBootProject -PoutputDir=/opt/my-projects/my-spring-boot-app --console=plain --info

Z racji tego, że dane wyjściowe wcześniej zostały dodane do lokalnego cache, w odpowiedzi będzie widoczne poniższe:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21

...

Task name matched 'initSpringBootProject'
Selected primary task 'initSpringBootProject' from project :
Tasks to be executed: [task ':initSpringBootProject']
Tasks that were excluded: []
Resolve mutations for :initSpringBootProject (Thread[included builds,5,main]) started.
:initSpringBootProject (Thread[included builds,5,main]) started.

> Task :initSpringBootProject FROM-CACHE
Build cache key for task ':initSpringBootProject' is 75b4d5a65d989aa6453584fe39baeab5
Task ':initSpringBootProject' is not up-to-date because:
  Output property 'outputDir' file /opt/my-projects/my-spring-boot-app has been removed.
  Output property 'outputDir' file /opt/my-projects/my-spring-boot-app/demo has been removed.
  Output property 'outputDir' file /opt/my-projects/my-spring-boot-app/demo/build.gradle has been removed.
  and more...
Loaded cache entry for task ':initSpringBootProject' with cache key 75b4d5a65d989aa6453584fe39baeab5

BUILD SUCCESSFUL in 416ms
5 actionable tasks: 1 from cache, 4 up-to-date

Co mówi o wykorzystaniu lokalnego build cache, potwierdzone przez oznaczenie FROM-CACHE.

Wnioski ze ścieżki Gradle Build Cache (DPE University)

Podczas przerabiania ścieżki Gradle Build Caching na DPE University zaciekawiło mnie, jak dokładnie działa lokalny build cache i co właściwie trafia do jego środka. Postanowiłem to rozłożyć na czynniki pierwsze.

Po wykonaniu taska initSpringBootProject uwagę zwraca klucz build cache: 75b4d5a65d989aa6453584fe39baeab5. To archiwum, które znajduje się w katalogu $GRADLE_USER_HOME/caches/build-cache-1. Po rozpakowaniu można zobaczyć m.in. plik METADATA, który zawiera następujące informacje:

1
2
3
4
5
6
7
8
9
#Generated origin information
#Sun Jul 13 13:47:46 CEST 2025
executionTime=787
creationTime=1752677283570
identity=\:initSpringBootProject
buildInvocationId=b6ynyhegwjcl5ojld4csg2g7ee
buildCacheKey=75b4d5a65d989aa6453584fe39baeab5
type=org.gradle.api.internal.tasks.execution.TaskExecution
gradleVersion=8.14

Natomiast, w folderze tree-outputDir/ znajduje się zarchiwizowany plik starter.zip oraz folder z projektem, czyli dokładnie to, co wcześniej zostało pobrane ze Spring Initializr i zapisane jako wynik działania taska.

Więcej o incremental build oraz Build Cache, możesz znaleźć w oficjalnej dokumentacji:

👉 Incremental build.

👉 Build Cache.

Tryb interaktywny

Aby zachować zgodność ze wsparciem incremental build oraz build cache zostało użyte odpowiednio upToDateWhen oraz cacheIf.


Gotowość do użytku

gradle-springinitializr-plugin nie jest tylko hobbystycznym projektem. Traktuję go bardzo poważnie, dlatego też oprócz dodania niezbędnych funkcjonalności zawiera on wszystkie kluczowe aspekty inżynierii oprogramowania, które opisane są w poniższych sekcjach.

Testy jednostkowe

Zostały napisane w Spocku. Pokrywają kluczowe funkcjonalności, takie jak walidację, budowanie zapytania do Spring Initializr oraz rozpakowywanie. Zgodnie z piramidą testów, jest ich najwięcej w projekcie.

Testy funkcjonalne

Również napisane w Spocku z użyciem Gradle TestKit. Do tego testuję odpowiedzi JSON ze Spring Initializr z użyciem WireMock zgodne z polecaną oficjalną dokumentacją ze Spring Initializr.

Wnioski z używania TestKit w Spocku

Na początku podczas pracy nad testami funkcjonalnymi natknąłem się na przypadek opisany w dokumentacji TestKit w paragrafie Controlling the build environment.

Mimo tego, że task initSpringBootProject wykonywał się i w logach widziałem:

1
2
3
4
5
6
> Task :initSpringBootProject
Project downloaded to: /private/var/folders/lj/q3_9z0ws4ygb_bvng5vy2vs00000gn/T/spock_initSpringBootProje_0_testProjectDir13964729921630795147/build/generated-project/starter.zip
Project extracted to: /private/var/folders/lj/q3_9z0ws4ygb_bvng5vy2vs00000gn/T/spock_initSpringBootProje_0_testProjectDir13964729921630795147/build/generated-project/demo

BUILD SUCCESSFUL in 3s
1 actionable task: 1 executed

To testy nie przechodziły, a ja dostawałem poniższą wiadomość w logach:

1
2
3
4
5
6
Condition not satisfied:

FilesTestUtils.projectFilesExist unzipDir, 'build.gradle', 'src/main/java/com/example/demo/DemoApplication.java'
|              |                 |
|              false             /var/folders/lj/q3_9z0ws4ygb_bvng5vy2vs00000gn/T/spock_initSpringBootProje_0_testProjectDir8148397175690448479/generated-project/demo
class io.oczadly.testsupport.FilesTestUtils

Problem z testem wynikał z tego, że Gradle TestKit zawsze uruchamia build w odizolowanym katalogu roboczym wewnątrz java.io.tmpdir (np. /private/var/folders/.../build/), a nie w katalogu, w którym oczekiwałem plików.

Natomiast w asercji (generatedProjectDir.absolutePath) szukałem plików w katalogu tymczasowym Spocka (@TempDir), który jest innym miejscem niż working directory TestKit.

Rozwiązałem to przez:

  • Ustawienie -PoutputDir=${generatedProjectDir.absolutePath}, które wymuszało, by plugin zapisał pliki tam, gdzie oczekiwał test.

Statyczna analiza kodu

Każde narzędzie przed wypuszczeniem do użytku powinno posiadać mechanizm statycznej analizy kodu. W tym przypadku został użyty CodeNarc plugin z koniecznym zestawem reguł przydatnych dla narzędzi typu Gradle plugin.

Pokrycie kodu testami

Tak, jak zostało wcześniej wspomniane gradle-springinitializr-plugin jest objęty zarówno testami jednostkowymi, jak i funkcjonalnymi. Pokrycie jest mierzone przy pomocy JaCoCo plugin. Obejmuje oba rodzaje testów i musi przekraczać 80%.

Ciągła integracja

Do ciągłej integracji zostało wykorzystane GitHub Actions. Przy każdym PR weryfikowane jest, czy commit jest zgodny z Conventional Commits. Następnie wykonywane jest gradle build. Dzięki temu sprawdzane jest poniższe:

  • Kompilacja kodu
  • Testy jednostkowe oraz funkcjonalne
  • Statyczna analiza kodu
  • Pokrycie kodu testami

Build Scan

Na końcu procesu ciągłej integracji, Build Scan z wykonaniem jest publikowany w https://scans.gradle.com. Przykładowy Build Scan z wykonania można znaleźć tutaj.

Testy kompatybilności

W procesie tworzenia pluginu ważne było, żeby był kompatybilny z różnymi wersjami Gradle oraz Kotlin DSL i Groovy DSL. Dlatego też przy każdym PR oprócz wcześniej wspomnianych kroków są uruchamiane właśnie testy kompatybilności, które uruchamiają task initSpringBootProject na różnych wersjach Gradle z katalogów:

  • examples/simple-groovy
  • examples/simple-kotlin

To wszystko jest możliwe dzięki wykorzystaniu strategii matrix w GitHub Actions. Więcej o tym można znaleźć tutaj.

Ciągłe dostarczanie

Po wcześniej opisanym procesie ciągłej integracji, gdy commit trafia do main’a uruchamiane jest GitHub Actions, które wykorzystuje semantic-release do zarządzania zmianami w CHANGELOG.md, tworzenia nowego taga wraz z releasem w repozytorium oraz publikowania pluginu do Gradle - Plugins.


Podsumowanie

Tworząc gradle-springinitializr-plugin miałem nie tylko radość z odwzorowania gradle init dla Spring Boot, przerabiania kursów DPE University poznania API Spring Initializr, najlepszych praktyk Gradle, Spock i Groovy, ale jestem w pełni zadowolony z efektu końcowego. To nie jest przykład kolejnego pluginu. To narzędzie gotowe do użycia lokalnie i jako element platformy przygotowane świadomie, solidnie i podążające za najlepszymi wzorcami.

Dla Platform Engineerów to gotowy asset do platformy, dla Software Engineerów – szybki start w codziennej pracy, a dla eksplorujących – praktyczny wzorzec budowy pluginu Gradle.

Co dalej?

Zainteresowany rozwojem pluginu?

👉 Zobacz, jak możesz uczestniczyć w jego rozwoju i przejrzyj plik CONTRIBUTING.

Masz pomysł na nową funkcję lub znalazłeś buga?

👉 Zgłoś swój pomysł albo zaraportuj błąd tutaj.

Do you like this blog and my work? Buy Me A Coffee