Projekt: git gradle spring-boot

http://git.e-strix.com/sample_fx_app.git/

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
    │     .gitignore
    │     build.gradle
    │     latest.properties
    │     settings.gradle
    │
    ├───gradle
    │        release.gradle
    │
    └───src
        └───main
            ├───java
            │    └───pl
            │        └───estrix
            │            └───javafx
            │                    FilterProp.java
            │                    JavaApplication.java
            │                    MainController.java
            │
            └───resources
                │     logo.png
                │     main.fxml
                │
                └───META-INF
                        spring.factories

Plik .gitignore

1
2
3
4
.gradle/
.idea/
build/
*.iml

Plik build.gradle

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
buildscript {
    repositories {
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.1.RELEASE")
    }
}

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")

        generated.text = "estrix.application.biuld-time=${buildTime()}\n" +
                "estrix.application.name=${project.name}\n" +
                "estrix.application.version=${project.version}\n"
    }
}

Plik latest.properties

1
2
3
4
#Tue Apr 10 16:59:22 CEST 2018
bugfix=0
major=1
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
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class Version {
    int major
    int minor
    int bugfix
    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"

    @TaskAction void release(){
        println "doing a $type release of ${project.version}"
    }
}

Plik src/main/java/pl/estrix/javafx/FilterProp.java

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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;
    }

    public void setBiuldTime(String biuldTime) {
        this.biuldTime = biuldTime;
    }
}

Plik src/main/java/pl/estrix/javafx/JavaApplication.java

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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();
    }

}

Plik src/main/java/pl/estrix/javafx/MainController.java

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
26
27
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;

    @FXML
    public void initialize() {
        propName.setText(filterProp.getName());
        propVersion.setText(filterProp.getVersion());
        propBuildTime.setText(filterProp.getBiuldTime());
    }
}

Plik src/main/resources/main.fxml

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.Cursor?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="320.0" prefWidth="480.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="pl.estrix.javafx.MainController">
   <children>
      <HBox alignment="CENTER" style="-fx-background-color: #ffffff;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <AnchorPane prefHeight="320.0" prefWidth="255.0" HBox.hgrow="ALWAYS">
               <children>
                  <ImageView fitHeight="320.0" fitWidth="255.0" pickOnBounds="true" preserveRatio="true" AnchorPane.leftAnchor="0.0">
                     <image>
                        <Image url="@logo.png" />
                     </image>
                  </ImageView>
               </children>
            </AnchorPane>
            <VBox prefHeight="320.0" prefWidth="217.0" style="-fx-background-color: #ffffff;" HBox.hgrow="ALWAYS">
               <children>
                  <Label alignment="CENTER" contentDisplay="CENTER" maxWidth="1.7976931348623157E308" text="e-Strix.com" textAlignment="CENTER">
                     <VBox.margin>
                        <Insets bottom="10.0" top="10.0" />
                     </VBox.margin>
                  </Label>
                  <GridPane>
                    <columnConstraints>
                      <ColumnConstraints hgrow="SOMETIMES" maxWidth="106.0" minWidth="10.0" prefWidth="58.0" />
                      <ColumnConstraints hgrow="SOMETIMES" maxWidth="163.0" minWidth="10.0" prefWidth="163.0" />
                    </columnConstraints>
                    <rowConstraints>
                      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                    </rowConstraints>
                     <children>
                        <Label text="Name" />
                        <Label text="Version" GridPane.rowIndex="1" />
                        <Label text="Buil Time" GridPane.rowIndex="2" />
                        <Label fx:id="propName" text="Label" GridPane.columnIndex="1" />
                        <Label fx:id="propVersion" text="Label" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                        <Label fx:id="propBuildTime" text="Label" GridPane.columnIndex="1" GridPane.rowIndex="2" />
                     </children>
                  </GridPane>
               </children>
            </VBox>
         </children>
         <cursor>
            <Cursor fx:constant="SW_RESIZE" />
         </cursor>
      </HBox>
   </children>
</AnchorPane>

Plik src/main/resources/META-INF/spring.factories

1
2
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
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

Jenkins new project

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).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *