[JAVA] Ich habe eine Jenkins-Datei mit deklarativer Pipeline geschrieben (Checkstyle, Findbugs, PMD, CPD usw.)

Ich habe eine Jenkins-Datei an CI, eine Gradle Java-App mit Jenkins, geschrieben. Wenn ich es an Github weitergebe, wird der Jenkins-Pipeline-Job in AWS ausgeführt. Wenn der Test erfolgreich ist, verwende ich ihn wie die Bereitstellung in Tomcat unter AWS.

Declarative Pipeline Wie es ist, Jenkinsfile

node {
  ....
}

Es wurde geschrieben als, aber wenn Sie sich [Jenkins offizielle Website] ansehen (https://jenkins.io/doc/book/pipeline/syntax/) Dies ist die Scripted Pipelines-Notation. Ab Version 2.5 Migration des Pipeline Plugins

pipeline {
  ....  
}

Eine Notation namens Declarative Pipeline wurde eingeführt, um wie zu schreiben Es war einfacher und leichter zu schreiben, also habe ich es umgeschrieben. Es ist auf jeden Fall ordentlich (vor allem die letzte E-Mail, Bereitstellung), Es ist schön, im Notfall traditionelle Scripted Pipelines mischen zu können.

Plug-In hinzugefügt

Jenkins Zum Zeitpunkt der Ersteinrichtung nicht im empfohlenen Plugin enthalten

Jenkinsfile Führen Sie einen Jenkins-Pipeline-Job mit einem Webhook von Github aus. Verwenden Sie für Pipeline-Jobs Jenkinsfile von Github. Der Auftragsablauf ist wie folgt. Bereitstellung nur, wenn die Analyse und das Testen des statischen Codes erfolgreich sind. image

Jenkinsfile


pipeline {
    agent any
    //Definieren Sie Konstanten und Variablen
    environment {
        reportDir = 'build/reports'
        javaDir = 'src/main/java'
        resourcesDir = 'src/main/resources'
        testReportDir = 'build/test-results/test'
        jacocoReportDir = 'build/jacoco' 
        javadocDir = 'build/docs/javadoc'
        libsDir = 'build/libs'
        appName = 'SampleApp'
        appVersion = '1.0.0'
    }
    
    //Definieren Sie eine oder mehrere Stufen im Stufenblock
    stages {
        stage('Vorbereitungen') {
            //Die eigentliche Verarbeitung wird im Schrittblock definiert
            steps {
                deleteDir()

                //Schauen Sie sich das Github-Projekt an, das diesen Job ausgelöst hat
                checkout scm

                //Jenkinsfile und Build zur Untersuchung der Ursache von Jobfehlern.Gradle zuerst speichern
                archiveArtifacts "Jenkinsfile"
                archiveArtifacts "build.gradle"

                //Sie können auch die traditionelle Skript-Pipelines-Notation mit dem Skriptblock verwenden
                script {
                    //Erteilen Sie die Ausführungsberechtigung, damit Sie sich nicht über die verweigerte Berechtigung ärgern
                    if(isUnix()) {
                        sh 'chmod +x gradlew'
                    }
                }
                gradlew 'clean'
            }
        }
        
        stage('kompilieren') {
            steps {
                gradlew 'classes testClasses'
            }
            
            //Der Nachblock kann den Prozess definieren, der nach dem Schrittblock ausgeführt werden soll
            post {
                //Der Always-Block wird immer ausgeführt, unabhängig davon, ob die Blockverarbeitung der Schritte fehlschlägt oder erfolgreich ist.
                always {

                    //Wenn Sie es ausführen, wenn JavaDoc generiert wird, wird auch eine JavaDoc-Warnung eingefügt.
                    //Java-Kompilierungswarnungen werden unmittelbar nach dem Kompilieren gesammelt
                    step([

                        //Die Klassenspezifikation beim Ausführen des Plug-Ins muss kein vollständig qualifizierter Name sein
                        $class: 'WarningsPublisher',

                        //ConsoleParsers, wenn Sie beim Ausführen von Job Warnungen von der Konsole erfassen möchten
                        // pmd.Geben Sie Parser-Konfigurationen an, wenn Sie aus einer Datei wie XML sammeln.
                        //Bei Parser-Konfigurationen zusätzlich zum Parser-Namen Muster(Pfad der zu aggregierenden Datei)Muss auch angegeben werden
                        //Verwenden Sie den in der folgenden Eigenschaftendatei definierten Parsernamen.
                        // https://github.com/jenkinsci/warnings-plugin/blob/master/src/main/resources/hudson/plugins/warnings/parser/Messages.properties
                        consoleParsers: [
                            [parserName: 'Java Compiler (javac)'],
                        ],
                        canComputeNew: false,
                        canResolveRelativesPaths: false,
                        usePreviousBuildAsReference: true
                    ])
                }
            }
        }
        
        stage('Statische Code-Analyse') {
            steps {
                //Verwenden Sie die Parallelmethode für die Parallelverarbeitung
                parallel(
                    'Statische Code-Analyse' : {
                        gradlew 'check -x test'

                        //Sie können das aktuelle Verzeichnis mit der dir-Methode angeben
                        dir(reportDir) {
                            step([
                                $class: 'CheckStylePublisher',
                                pattern: "checkstyle/*.xml"
                            ])
                            step([
                                $class: 'FindBugsPublisher',
                                pattern: "findbugs/*.xml"
                            ])
                            step([
                                $class: 'PmdPublisher',
                                pattern: "pmd/*.xml"
                            ])
                            step([
                                $class: 'DryPublisher',
                                pattern: "cpd/*.xml"
                            ])
                
                            archiveArtifacts "checkstyle/*.xml"
                            archiveArtifacts "findbugs/*.xml"
                            archiveArtifacts "pmd/*.xml"
                            archiveArtifacts "cpd/*.xml"
                        }
                    },
                    'Schrittzahl': {
                        //Berichterstellung
                        //Wenn Sie outputFile und outputFormat angeben, wird auch eine Excel-Datei erstellt.
                        stepcounter outputFile: 'stepcount.xls', outputFormat: 'excel', settings: [
                            [key:'Java', filePattern: "${javaDir}/**/*.java"],
                            [key:'SQL', filePattern: "${resourcesDir}/**/*.sql"],
                            [key:'HTML', filePattern: "${resourcesDir}/**/*.html"],
                            [key:'JS', filePattern: "${resourcesDir}/**/*.js"],
                            [key:'CSS', filePattern: "${resourcesDir}/**/*.css"]
                        ]
                        //Speichern Sie die Excel-Datei vorerst als Liefergegenstand
                        archiveArtifacts "stepcount.xls"
                    },
                    'Task-Scan': {
                        step([
                            $class: 'TasksPublisher',
                            pattern: './**',
                            //Wird bei der Suche nach Aggregationszielen zwischen Groß- und Kleinschreibung unterschieden?
                            ignoreCase: true,
                            //Zu aggregierende Zeichenfolgen können für jede Priorität angegeben werden
                            //Wenn Sie mehr als eine angeben, geben Sie eine durch Kommas getrennte Zeichenfolge an.
                            high: 'System.out.System.err',
                            normal: 'TODO,FIXME,XXX',
                        ])
                    },
                    'JavaDoc': {
                        gradlew 'javadoc -x classes'
                        step([
                            $class: 'JavadocArchiver',
                            //Javadoc-Index.Geben Sie den Pfad des Ordners an, in dem sich HTML befindet
                            javadocDir: "${javadocDir}",
                            keepAll: true
                        ])
                    }
                )
            }
            
            post {
                always {
                   //Sammeln Sie JavaDoc-Warnungen
                    step([
                        $class: 'WarningsPublisher',
                        consoleParsers: [
                            [parserName: 'JavaDoc Tool']
                        ],
                        canComputeNew: false,
                        canResolveRelativesPaths: false,
                        usePreviousBuildAsReference: true
                    ])
                }
            }
        }
        

        stage('Prüfung') {
            steps {
                gradlew 'test jacocoTestReport -x classes -x testClasses'
                
                junit "${testReportDir}/*.xml"
                archiveArtifacts "${testReportDir}/*.xml"

                //Abdeckungsbericht erstellen (ohne Testklasse)
                step([
                    $class: 'JacocoPublisher',
                    execPattern: "${jacocoReportDir}/*.exec",
                    exclusionPattern: '**/*Test.class'
                ])
            }
        }
        
        stage('Bereitstellen') {
            //Sie können die Bedingungen für die Ausführung der Phase im when-Block angeben
            when {
                //Nicht bei statischer Code-Analyse und Testfehlern bereitstellen
                expression {currentBuild.currentResult == 'SUCCESS'}
            }
            
            steps {
                gradlew 'jar'
                archiveArtifacts "${libsDir}/${appName}-${appVersion}.jar"
                gradlew 'war'
                archiveArtifacts "${libsDir}/${appName}-${appVersion}.war"
                deploy warDir: libsDir, appName: appName, appVersion: appVersion
            }
        }
    }
    
    //Wenn Sie einen Postblock auf derselben Ebene wie den Stufenblock definieren
    //Es ist möglich, die Verarbeitung zu definieren, nachdem die gesamte Stufenverarbeitung abgeschlossen ist.
    post {
        always {
            //Löschen Sie abschließend den Inhalt des Arbeitsbereichs
            deleteDir()
        }
        //Senden Sie eine E-Mail an sich selbst, es sei denn, Sie sind hintereinander erfolgreich

        //Wenn sich das Ergebnis gegenüber dem letzten Mal ändert
        changed {
            sendMail("${currentBuild.previousBuild.result} => ${currentBuild.currentResult}")
        }
        //Wenn es fehlschlägt
        failure {
            sendMail(currentBuild.currentResult)
        }
        //Wenn es instabil ist (hauptsächlich wenn der Test fehlschlägt)
        unstable {
            sendMail(currentBuild.currentResult)
        }
    }
}


//Führen Sie den Befehl Gradlew aus
def gradlew(command) {
    if(isUnix()) {
        sh "./gradlew ${command} --stacktrace"
    } else {
        bat "./gradlew.bat ${command} --stacktrace"
    }
}

//Bereitstellen
// args.warDir war Speicherverzeichnis
// args.appName App-Name
// args.appVersion App-Version
def deploy(Map args) {
    //Pfad des privaten Schlüssels * Da die Datei auf den Tomcat-Server übertragen wird, muss der private Schlüssel vorab irgendwo auf dem Jenkins-Server gespeichert werden.
    def keyDir = '/var/lib/jenkins/.ssh/xxx'
    //Tomcat-Serveradresse und Benutzername
    def webServerAddress = 'ecX-XX-XXX-X-X.xx-xxxx-x.xxxxxxxx'
    def webServerUser = 'hoge-user'
    def webServer = "${webServerUser}@${webServerAddress}"
    
    def srcWar = "${args.appName}-${args.appVersion}.war"
    def destWar = "${args.appName}.war"
    
    //Übertragen Sie Dateien und platzieren Sie Krieg in Tomcats Webanwendungen
    sh "sudo -S scp -i ${keyDir} ./${args.warDir}/${srcWar} ${webServer}:/home/ec2-user"
    sh "sudo -S ssh -i ${keyDir} ${webServer} \"sudo cp /home/ec2-user/${srcWar} /usr/share/tomcat8/webapps/${destWar}\""
}

//Mail an Google Mail senden
def sendMail(result) {
    mail to: "[email protected]",
        subject: "${env.JOB_NAME} #${env.BUILD_NUMBER} [${result}]",
        body: "Build URL: ${env.BUILD_URL}.\n\n"
}

Stolpern

image

image

image

image

build.gradle Jenkins selbst führt nur Gradle-Befehle aus und generiert einen Bericht basierend auf der Ausgabe Die Java-App build.gradle von Gradle muss in der Lage sein, die folgenden Prozesse auszuführen. Erstellen Sie außerdem einen Gradle-Wrapper, damit Sie Gradle nicht mit Jenkins installieren müssen.

Zum Beispiel,

build.gradle


apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'
apply plugin: 'jacoco'

ext {
    appVersion = '1.0.0'
    appName = 'SampleApp'
    javaVersion = 1.8
    defaultEncoding = 'UTF-8'
}

sourceCompatibility = javaVersion
targetCompatibility  = javaVersion
tasks.withType(AbstractCompile)*.options*.encoding = defaultEncoding
tasks.withType(GroovyCompile)*.groovyOptions*.encoding = defaultEncoding
mainClassName = 'jp.takumon.sapmleapp.App'

repositories {
    mavenCentral()
}

dependencies {
    //Listen Sie abhängige Bibliotheken auf

    compile group: 'junit', name: 'junit', version: '4.12'
}

jar {
    baseName = appName
    version =  appVersion
}

war {
    baseName = appName
    version =  appVersion
}

checkstyle {
    //Setzen Sie die nachfolgende Verarbeitung fort, auch wenn sie fehlschlägt
    ignoreFailures = true
    sourceSets = [sourceSets.main]
    toolVersion = '7.6.1'
}

findbugs {
    //Setzen Sie die nachfolgende Verarbeitung fort, auch wenn sie fehlschlägt
    ignoreFailures = true
    sourceSets = [sourceSets.main]
    toolVersion = "3.0.1"
}

pmd {
    //Setzen Sie die nachfolgende Verarbeitung fort, auch wenn sie fehlschlägt
    ignoreFailures = true
    sourceSets = [sourceSets.main]
}

tasks.withType(Pmd) {
    reports {
      xml.enabled = true
    }
}

//CPD (Duplicate Code Check Processing) zur Prüfaufgabe hinzugefügt
check.doLast {
    File outputDir = new File("$reportsDir/cpd/")
    outputDir.mkdirs()
  
    ant.taskdef(
        name: 'cpd', 
        classname: 'net.sourceforge.pmd.cpd.CPDTask',
        classpath: configurations.pmd.asPath)
  
    ant.cpd(
        minimumTokenCount: '100',
        format: 'xml',
        encoding: defaultEncoding,
        outputFile: new File(outputDir, 'cpd.xml')
    ) {
        fileset(dir: "src/main/java") {
            include(name: '**/*.java')
        }
    }
}

javadoc {
    failOnError = false
    //Auf deinem Lieblingslevel
    options.memberLevel = JavadocMemberLevel.PRIVATE
}

test {
    //Setzen Sie die nachfolgende Verarbeitung fort, auch wenn sie fehlschlägt
    ignoreFailures = true
    reports {
        junitXml.enabled = true
    }
}

jacoco {
    toolVersion = '0.7.5.201505241946'
}

jacocoTestReport {
    reports {
      xml.enabled = true
    }
    
    //Testklasse vom Abdeckungsbericht ausschließen
    afterEvaluate { 
        classDirectories = files(classDirectories.files.collect {
            fileTree(dir: it, exclude: ['**/*Test.class']) 
        })
    }
}

task wrapper (type: Wrapper) {
    gradleVersion = '3.4.1'
}

das ist alles.

Recommended Posts

Ich habe eine Jenkins-Datei mit deklarativer Pipeline geschrieben (Checkstyle, Findbugs, PMD, CPD usw.)
Ich habe Code Pipeline mit AWS CDK erstellt.
Ich möchte eine bestimmte Datei mit WatchService überwachen
Ich habe versucht, mit OCR eine PDF-Datei mit Java zu verarbeiten
Ich habe jetzt einen Test mit Spring Boot + JUnit 5 geschrieben
Ich habe einen CRUD-Test mit SpringBoot + MyBatis + DBUnit geschrieben (Teil 1)
Ich habe versucht, eine PDF-Datei mit Java part2 zu verarbeiten