Projekt: git gradle spring-boot
W każdym (nawet freelancer’skim) projekcie przychodzi moment na to aby zacząć pisać kod i tu już dostajemy wiatr w żagiel i stopy wody pod kilem. W zasadzie ogranicza nas tylko lenistwo z jednej strony i kreatywność z drugiej.
Dla potrzeb prezentacji wybiorę sobie coś na czasie, a będzie to:
- spring-boot
- gradle
- git
- javafx
A zatem bez zbędnych patosów, teorii i literatury zacznijmy od stworzenia kilku plików.
Tworzenie projektu
Zacznijmy od utworzenia repozytorium. Jeśli nie widziałeś mojego wpisu na ten temat to zobacz pierw: php7-git-gitlist.
A teraz do rzeczy. Struktura projektu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | └───javafx-git-sample<br> │ .gitignore<br> │ build.gradle<br> │ latest.properties<br> │ settings.gradle<br> │<br> ├───gradle<br> │ release.gradle<br> │<br> └───src<br> └───main<br> ├───java<br> │ └───pl<br> │ └───estrix<br> │ └───javafx<br> │ FilterProp.java<br> │ JavaApplication.java<br> │ MainController.java<br> │<br> └───resources<br> │ logo.png<br> │ main.fxml<br> │<br> └───META-INF<br> spring.factories |
Plik .gitignore
1 2 3 4 | .gradle/<br> .idea/<br> build/<br> *.iml |
Plik build.gradle
1 2 3 4 5 6 7 8 9 | buildscript {<br> repositories {<br> mavenCentral()<br> jcenter()<br> }<br> dependencies {<br> classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.1.RELEASE")<br> }<br> } |
apply from: 'gradle/release.gradle’
apply plugin: 'java’
apply plugin: 'org.springframework.boot’
apply plugin: 'io.spring.dependency-management’
bootJar {
mainClassName = 'pl.estrix.javafx.JavaApplication’
manifest {
attributes 'Start-Class’: 'pl.estrix.javafx.JavaApplication’
}
}
springBoot {
mainClassName = 'pl.estrix.javafx.JavaApplication’
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile(„org.springframework.boot:spring-boot-starter”)
testCompile(„junit:junit”)
}
def buildTime() {
new Date().format(’yyyy.MM.dd HH:mm’)
}
def generatedResources = „$buildDir/resources/main/”
sourceSets {
main {
output.dir(generatedResources, builtBy: 'generateMyResources’)
}
}
task generateMyResources {
doLast {
def generatedTmp = new File(generatedResources)
if( !generatedTmp.exists() ) {
generatedTmp.mkdirs()
}
def generated = new File(generatedResources, „filter.properties”)
1 2 3 4 5 | generated.text = "estrix.application.biuld-time=${buildTime()}\n" +<br> "estrix.application.name=${project.name}\n" +<br> "estrix.application.version=${project.version}\n"<br> }<br> } |
Plik latest.properties
1 2 3 4 | #Tue Apr 10 16:59:22 CEST 2018<br> bugfix=0<br> major=1<br> minor=0 |
Plik settings.gradle
1 | rootProject.name = 'JavaFxGitSample' |
Plik gradle/release.gradle
Notatka: Pomysł na zarządzanie wersjami pochodzi z https://www.youtube.com/watch?v=Y6SVoXFsw7I
1 2 3 4 5 | class Version {<br> int major<br> int minor<br> int bugfix<br> boolean snapshot = true |
static Version load(File versionFile){
def props = new Properties()
versionFile.withInputStream {
stream -> props.load(stream)
}
def major = Integer.parseInt(props[’major’])
def minor = Integer.parseInt(props[’minor’])
def bugfix = Integer.parseInt(props[’bugfix’])
return new Version(major:major, minor:minor, bugfix:bugfix)
}
String toString(){
„${major}.${minor}.${bugfix}${snapshot ? ’-SNAPSHOT’:”}”
}
void store(File versionFile){
def props = new Properties()
props[’bugfix’] = bugfix.toString()
props[’major’] = major.toString()
props[’minor’] = minor.toString()
props.store(versionFile.newWriter(), null)
}
Version next(String releaseType = „bugfix”){
if(releaseType == „major”){
return new Version(major:major+1, minor:0, bugfix:0)
}else if(releaseType == „minor”){
return new Version(major:major, minor:minor+1, bugfix:0)
}else{
return new Version(major:major, minor:minor, bugfix:bugfix+1)
}
}
}
def latest = Version.load(rootProject.file(„latest.properties”))
allprojects{
version = latest.next()
}
gradle.taskGraph.whenReady { graph ->
if(graph.hasTask(„:release”)){
allprojects{
version = latest.next(release.type)
version.snapshot = false
}
}
}
task persistVersionInfo(type:Exec){
commandLine „git” , „commit”,”-i”, „latest.properties”, „-m”, „’ update version to ${-> version }'”
doFirst{
version.store(file(„latest.properties”))
}
}
task tagWorkspace(type:Exec){
commandLine 'git’, 'tag’, „${-> version }”
commandLine 'git’, 'push’, 'origin’, 'HEAD:master’
}
task release(type:Release){
type = System.getProperty(„type”)
dependsOn „build”, „persistVersionInfo”, „tagWorkspace”
}
import org.gradle.api.internal.tasks.options.Option
class Release extends DefaultTask{
@Option(option=”type”, description=”the type of a release.”)
String type = „bugfix”
1 2 3 4 | @TaskAction void release(){<br> println "doing a $type release of ${project.version}"<br> }<br> } |
Plik src/main/java/pl/estrix/javafx/FilterProp.java
1 | package pl.estrix.javafx; |
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(„filter.properties”)
public class FilterProp {
@Value(„${estrix.application.name}”)
private String name;
@Value(„${estrix.application.version}”)
private String version;
@Value(„${estrix.application.biuld-time}”)
private String biuldTime;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getBiuldTime() {
return biuldTime;
}
1 2 3 4 | public void setBiuldTime(String biuldTime) {<br> this.biuldTime = biuldTime;<br> }<br> }<br> |
Plik src/main/java/pl/estrix/javafx/JavaApplication.java
1 | package pl.estrix.javafx; |
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication
@ComponentScan(„pl.estrix.javafx”)
@PropertySource(„classpath:filter.properties”)
@Configuration
public class JavaApplication extends Application {
private ConfigurableApplicationContext context;
private Parent rootNode;
public static void main(final String[] args) {
Application.launch(args);
}
@Override
public void init() throws Exception {
SpringApplicationBuilder builder = new SpringApplicationBuilder(JavaApplication.class);
context = builder.run(getParameters().getRaw().toArray(new String[0]));
FXMLLoader loader = new FXMLLoader(getClass().getResource(„/main.fxml”));
loader.setControllerFactory(context::getBean);
rootNode = loader.load();
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(rootNode, 480, 320));
primaryStage.centerOnScreen();
primaryStage.show();
}
@Override
public void stop() throws Exception {
context.close();
}
1 | } |
Plik src/main/java/pl/estrix/javafx/MainController.java
1 | package pl.estrix.javafx; |
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MainController {
@Autowired
private FilterProp filterProp;
@FXML
private Label propName;
@FXML
private Label propVersion;
@FXML
private Label propBuildTime;
1 2 3 4 5 6 7 | @FXML<br> public void initialize() {<br> propName.setText(filterProp.getName());<br> propVersion.setText(filterProp.getVersion());<br> propBuildTime.setText(filterProp.getBiuldTime());<br> }<br> } |
Plik src/main/resources/main.fxml
Plik src/main/resources/META-INF/spring.factories
1 2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\<br> pl.estrix.javafx.JavaApplication |
Plik src/main/resources/logo.png
1 | wget http://e-strix.com/wp-content/uploads/2018/04/logo.png -P src/main/resources/ |
Budowa lokalna
Uruchamianie
1 | gradle clean generateMyResources bootRun |
Budowanie jar
1 | gradle clean generateMyResources bootJar |
Uruchamianie
1 | java -jar build\libs\JavaFxGitSample-1.0.1-SNAPSHOT.jar |
No dobra, teraz wiemy jak zbudować aplikację. Ale docelowo ma to robić Ci, zatem zabieramy się za konfigurację job’ów.
Konfiguracja Jenkins
Budowa zdalna
W polu: Repository URL
git@git.e-strix.com:repositories/javafx-git-sample.git
W polu: Repository browser
gitlist
W polu: Repository browser -> URL
git.e-strix.com
W polu: Budowanie -> Invoke Gradle -> Version
Gradle_4_6
W polu: Budowanie -> Tasks
clean generateMyResources bootJar
Podnoszenie wersji
Kroki takie jak w przypadku „Budowa zdalna” z tą różnicą że w:
W polu: Budowanie -> Tasks
clean release --type minor
Gdzie wartość –type przyjmuje wartości:
- major
- minor
- bugfix – domyślny
Publikacja na Landing Page
W polu: Budowanie -> Execute Shell -> Command
mkdir -p release_lib rm -f ./release_lib/* cp ${WORKSPACE}/../javafx-git-sample-release/build/libs/*.jar ./release_lib/ rm -f /home/appuser/public_html/download/*.jar cp ./release_lib/*.jar /home/appuser/public_html/download/
Zakończenie
Jak widzisz storzenie projektu jest dość proste. Mimo że musiałem kilka godzin spędzić na odnalezieniu odpowiedniej dla mojego projektu ścieżki rozwoju. Przetestowałem kilka rozwiązań, pluginów i stwierdziłem że jednak najlepsze rozwiązanie to będzie ręczne napisanie skryptu (mimo że zapożyczyłem rozwiązanie od mądrych ludzi z internetu).