Skrivning af et Jenkins-plugin

1. Oversigt

Jenkins er en kontinuerlig integrationsserver med open source, som gør det muligt at oprette en brugerdefineret plugin-oprettelse til en bestemt opgave / miljø.

I denne artikel gennemgår vi hele processen med at oprette en udvidelse, der tilføjer statistik til buildoutput, nemlig antallet af klasser og kodelinjer.

2. Opsætning

Den første ting at gøre er at oprette projektet. Heldigvis leverer Jenkins praktiske Maven-arketyper for det.

Kør bare kommandoen nedenfor fra en skal:

mvn arketype: generer -Dfilter = io.jenkins.archetypes: plugin

Vi får følgende output:

[INFO] Genererer projekt i interaktiv tilstand [INFO] Ingen arketype defineret. Brug af maven-archetype-quickstart (org.apache.maven.archetypes: maven-archetype-quickstart: 1.0) Vælg archetype: 1: remote -> io.jenkins.archetypes: empty-plugin (Skeleton of a Jenkins plugin with a POM and et tomt kildetræ.) 2: fjernbetjening -> io.jenkins.archetypes: global-configuration-plugin (Skelet af et Jenkins-plugin med en POM og et eksempel på en global konfiguration.) 3: remote -> io.jenkins.archetypes : hello-world-plugin (Skelet af et Jenkins-plugin med en POM og et eksempel på byggetrin.)

Vælg nu den første mulighed og definer gruppe / artefakt / pakke i den interaktive tilstand. Derefter er det nødvendigt at foretage forbedringer af pom.xml - da den indeholder poster som f.eks TODO-plugin.

3. Jenkins-plugin-design

3.1. Udvidelsespunkter

Jenkins leverer et antal udvidelsespunkter. Dette er grænseflader eller abstrakte klasser, der definerer kontrakter for bestemte brugssager og tillader andre plugins at implementere dem.

For eksempel består hver build af et antal trin, f.eks. “Checkout fra VCS”, "Udarbejde", "Prøve","Samle", osv. Jenkins definerer hudson.tasks.BuildStep udvidelsespunkt, så vi kan implementere det for at give et tilpasset trin, der kan konfigureres.

Et andet eksempel er hudson.tasks.BuildWrapper - dette giver os mulighed for at definere præ / post-handlinger.

Vi har også et ikke-core e-mail-udvidelses-plugin, der definerer hudson.plugins.emailext.plugins.RecipientProvider udvidelsespunkt, som gør det muligt at give e-mail-modtagere. Et eksempel på implementering er tilgængelig her: hudson.plugins.emailext.plugins.recipients.UpstreamComitterRecipientProvider.

Bemærk: der er en ældre tilgang, hvor plugin-klassen skal udvides hudson. plugin. Imidlertid, det anbefales nu at bruge udvidelsespunkter i stedet.

3.2. Initialisering af plugin

Det er nødvendigt at fortælle Jenkins om vores udvidelse, og hvordan det skal instantieres.

Først definerer vi en statisk indre klasse i pluginet og markerer det ved hjælp af hudson. udvidelse kommentar:

klasse MyPlugin udvider BuildWrapper {@Extension offentlig statisk klasse DescriptorImpl udvider BuildWrapperDescriptor {@Override public boolean isApplicable (AbstractProject item) {return true; } @ Override public String getDisplayName () {returner "navn, der skal vises i brugergrænsefladen"; }}}

For det andet skal vi definere en konstruktør, der skal bruges til plugins objekt-instantiering og markere den ved org.kohsuke.stapler.DataBoundConstructor kommentar.

Det er muligt at bruge parametre til det. De vises i brugergrænsefladen og leveres automatisk af Jenkins.

F.eks. overvej Maven-pluginet:

@DataBoundConstructor public Maven (strengemål, strengnavn, strengpom, strengegenskaber, streng jvmOptions, boolsk brugPrivateRepository, SettingsProvider-indstillinger, GlobalSettingsProvider globalSettings, boolsk injectBuildVariables) {...}

Det er kortlagt til følgende brugergrænseflade:

Det er også muligt at bruge org.kohsuke.stapler.DataBoundSetter kommentar med settere.

4. Implementering af plugin

Vi har til hensigt at indsamle grundlæggende projektstatistikker under en build, så hudson.tasks.BuildWrapper er den rigtige vej at gå her.

Lad os implementere det:

klasse ProjectStatsBuildWrapper udvider BuildWrapper {@DataBoundConstructor offentlig ProjectStatsBuildWrapper () {} @Override public Environment setUp (AbstractBuild build, Launcher launcher, BuildListener listener) {} @Extension public static class DescriptorImpl udvider BuildWrapperDescriptorable {@Oploader = @Projector = rigtigt; } @Nonnull @ Override public String getDisplayName () {return "Konstruer projektstatistik under build"; }}}

Ok, nu skal vi implementere den faktiske funktionalitet.

Lad os definere en domæneklasse for projektstatistikkerne:

klasse ProjectStats {private int klasserNummer; private int linjerNummer; // standard konstruktører / getters}

Og skriv koden, der bygger dataene:

private ProjectStats buildStats (FilePath root) kaster IOException, InterruptedException {int classesNumber = 0; int linesNumber = 0; Stak toProcess = ny stak (); toProcess.push (rod); mens (! toProcess.isEmpty ()) {FilePath-sti = toProcess.pop (); hvis (sti.isDirectory ()) {toProcess.addAll (sti.liste ()); } ellers hvis (path.getName (). endsWith (". java")) {classesNumber ++; linesNumber + = countLines (sti); }} returner nye ProjectStats (classesNumber, linesNumber); }

Endelig er vi nødt til at vise statistikken til slutbrugere. Lad os oprette en HTML-skabelon til det:

    $ PROJECT_NAME $ Project $ PROJECT_NAME $: 
Klassens nummerLinjenummer
$ CLASSES_NUMBER $$ LINES_NUMBER $

Og udfyld det under bygningen:

offentlig klasse ProjectStatsBuildWrapper udvider BuildWrapper {@Override public Environment setUp (AbstractBuild build, Launcher launcher, BuildListener listener) {return new Environment () {@Override public boolean tearDown (AbstractBuild build, BuildListener listener) kaster IOException, InterruptedExceptionStat = ProjectStats (ProjectStats) build.getWorkspace ()); String report = createReport (build.getProject (). GetDisplayName (), stats); Fil artefakterDir = build.getArtifactsDir (); Strengsti = artefakterDir.getCanonicalPath () + REPORT_TEMPLATE_PATH; File reportFile = ny fil ("sti"); // skriv rapportens tekst til rapportens fil}}; }}

5. Anvendelse

Det er tid til at kombinere alt, hvad vi hidtil har oprettet - og se det i aktion.

Det antages, at Jenkins er i gang i det lokale miljø. Se installationsoplysningerne ellers.

5.1. Føj pluginet til Jenkins

Lad os nu bygge vores plugin:

mvn installere

Dette vil skabe en * .hpi fil i mål vejviser. Vi er nødt til at kopiere det til Jenkins-plugins-biblioteket (~ / .jenkins / plugin som standard):

cp ./target/jenkins-hello-world.hpi ~ / .jenkins / plugins /

Lad os endelig genstarte serveren og sikre, at pluginet anvendes:

  1. Åbn CI-dashboard kl // localhost: 8080
  2. Naviger til Administrer Jenkins | Administrer plugins | Installeret
  3. Find vores plugin

5.2. Konfigurer Jenkins Job

Lad os oprette et nyt job til et open source Apache commons-lang-projekt og konfigurere stien til dets Git-repo der:

Vi skal også aktivere vores plugin til det:

5.3. Kontroller resultaterne

Vi er klar nu, lad os kontrollere, hvordan det fungerer.

Vi kan bygge projektet og navigere til resultaterne. Vi kan se, at en stats.html filen er tilgængelig her:

Lad os åbne det:

Det var det, vi forventede - en enkelt klasse, der har tre linjer kode.

6. Konklusion

I denne vejledning oprettede vi en Jenkins plugin fra bunden og sørgede for, at det fungerer.

Naturligvis dækkede vi ikke alle aspekter af udviklingen af ​​CI-udvidelser, vi leverede blot en grundlæggende oversigt, designideer og en indledende opsætning.

Og som altid kan kildekoden findes på GitHub.