GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Häufig erstelle ich Pipelines für Java-Projekte, sei es für Open-Source oder proprietäre Projekte. Kürzlich habe ich beschlossen, einige meiner Repositories von Travis-CI und TeamCity nach GitHub Actions zu migrieren und das ist dabei herausgekommen.

Was werden wir automatisieren

Zunächst benötigen wir ein Projekt zur Automatisierung. Lassen Sie uns eine kleine Anwendung mit Spring Boot / Java 11 / Maven erstellen. In diesem Artikel interessiert uns die Logik der Anwendung nicht besonders; wichtig ist die Infrastruktur rund um die Anwendung. Ein einfacher REST-API-Controller reicht dafür aus.

Die Quelldateien finden Sie hier: github.com/antkorwin/github-actions Alle Schritte zum Aufbau der Pipeline sind in den Pull-Requests dieses Projekts dokumentiert.

JIRA und Planung

Es sei erwähnt, dass wir normalerweise JIRA als Aufgaben-Tracker nutzen. Lassen Sie uns also ein separates Board für dieses Projekt erstellen und dort die ersten Aufgaben festhalten:

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Später werden wir noch darauf zurückkommen, welche interessanten Möglichkeiten sich aus der Kombination von JIRA und GitHub ergeben.

Automatisierung des Projektaufbaus

Unser Testprojekt wird über Maven erstellt, daher ist der Build-Prozess recht einfach. Alles, was wir benötigen, ist mvn clean package.

Um dies mit GitHub Actions zu erreichen, müssen wir eine Datei im Repository erstellen, die unseren Workflow beschreibt. Dies kann durch eine einfache yml-Datei geschehen. Ich kann nicht sagen, dass ich das 'Programmieren in yml' mag, aber was soll’s — wir erstellen die Datei build.yml im Verzeichnis .github/workflow/, in der wir die Aktionen für den Build der Master-Branch beschreiben:

name: Build

on:
  pull_request:
    branches:
      - '*'
  push:
    branches:
      - 'master'

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@v1
      - name: JDK 11 einrichten
        uses: actions/setup-java@v1
        with:
          java-version: 1.11
      - name: Maven-Paket
        run: mvn -B clean package -DskipTests

on — dies ist die Beschreibung des Ereignisses, das unseren Skript auslösen wird.

on: pull_request / push — zeigt an, dass dieser Workflow bei jedem Push zum Master und bei der Erstellung von Pull-Requests ausgeführt werden soll.

Als Nächstes folgt die Beschreibung der Aufgaben (jobs) und der Ausführungsschritte (steps) für jede Aufgabe.

runs-on — hier können wir das Zielbetriebssystem auswählen. Überraschenderweise kann man sogar Mac OS wählen, aber bei privaten Repositories ist das im Vergleich zu Linux ziemlich teuer.

uses ermöglicht die Wiederverwendung anderer Aktionen, zum Beispiel installieren wir mit der Aktion actions/setup-java die Umgebung für Java 11.

Mit Hilfe von mit können wir die Parameter angeben, mit denen die Aktion ausgeführt wird; das sind im Grunde die Argumente, die an die Aktion übergeben werden.

Jetzt bleibt nur noch, das Projekt mit Maven zu bauen: run: mvn -B clean package Das Flag -B besagt, dass wir den non-interactive mode benötigen, damit Maven uns nicht plötzlich etwas fragt.

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Prima! Jetzt wird bei jedem Commit in den Master die Projektbuild gestartet.

Automatisierung der Testausführung

Der Build ist gut, aber in der Realität kann ein Projekt zwar erfolgreich gebaut werden, aber nicht funktionieren. Daher müssen wir als nächsten Schritt die Automatisierung der Testausführung angehen. Es ist auch sehr praktisch, die Testergebnisse zu sehen, wenn man einen PR überprüft — man weiß genau, dass die Tests bestanden sind und niemand etwas vergessen hat, bevor man seinen Branch merged.

Wir führen die Tests bei der Erstellung eines Pull-Requests und beim Mergen in den Master aus und erstellen außerdem einen Bericht über die Codeabdeckung.

name: Build

on:
  pull_request:
    branches:
      - '*'
  push:
    branches:
      - 'master'

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@v1
      - name: JDK 11 einrichten
        uses: actions/setup-java@v1
        with:
          java-version: 1.11
      - name: Maven Überprüfung
        run: mvn -B clean verify
      - name: Testabdeckung
        uses: codecov/codecov-action@v1
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

Für die Testabdeckung verwende ich Codecov in Kombination mit dem Jacoco-Plugin. Codecov hat eine eigene Action, benötigt jedoch für die Arbeit mit unserem Pull-Request einen Token:

${{ secrets.CODECOV_TOKEN }} — eine solche Konstruktion werden wir noch öfter sehen, secrets ist der Mechanismus zur Speicherung von Geheimnissen in GitHub. Dort können wir Passwörter, Token, Hosts, URLs und andere Daten eingeben, die nicht im Code-Repository sichtbar sein sollten.

Eine Variable zu den Geheimnissen hinzufügen, ist in den Repository-Einstellungen auf GitHub möglich:

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Den Token kann man unter codecov.io nach der Authentifizierung über GitHub erhalten. Für die Hinzufügung eines öffentlichen Projekts muss man einfach einen Link wie folgt aufrufen: GitHub-Benutzername/[repo name]. Приватный репозиторий тоже можно добавить, для этого надо дать права codecov приложению в гитхабе.

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Fügen Sie das Jacoco-Plugin in die POM-Datei ein:

org.jacoco
	jacoco-maven-plugin
	0.8.4
	
		
			
				prepare-agent
			
		
		
		
			report
			test
			
				report
			
		
	


	org.apache.maven.plugins
	maven-surefire-plugin
	2.22.2
	
		plain
		
			**/*Test*.java
			**/*IT*.java

Jetzt wird jeder unserer Pull-Requests vom Codecov-Bot besucht, der ein Diagramm zur Änderung der Testabdeckung hinzufügt:

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Wir fügen einen statischen Codeanalysator hinzu

In den meisten meiner Open-Source-Projekte nutze ich SonarCloud für die statische Codeanalyse, es lässt sich ziemlich einfach zu Travis-CI hinzufügen. Daher ist es ein logischer Schritt, bei der Migration zu GitHub Actions dasselbe zu tun. Die Actions-Marketing ist eine tolle Sache, aber diesmal hat sie mich ein wenig im Stich gelassen, da ich aus Gewohnheit die benötigte Action gefunden und in den Workflow eingetragen habe. Dabei stellte sich heraus, dass Sonar die Analyse von Maven- oder Gradle-Projekten über eine Action nicht unterstützt. Das steht natürlich in der Dokumentation, aber wer liest das schon?!

Das geht über die Action nicht, also werden wir es über das Maven-Plugin machen:

name: SonarCloud

on:
  push:
    branches:
      - master
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  sonarcloud:
    runs-on: ubuntu-16.04
    steps:
      - uses: actions/checkout@v1
      - name: JDK einrichten
        uses: actions/setup-java@v1
        with:
          java-version: 1.11
      - name: Mit SonarCloud analysieren
#       Umgebungsvariablen setzen:
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
#       Sonar Maven Plugin ausführen:
        run: mvn -B verify sonar:sonar -Dsonar.projectKey=antkorwin_github-actions -Dsonar.organization=antkorwin-github -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=$SONAR_TOKEN -Dsonar.coverage.jacoco.xmlReportPaths=./target/site/jacoco/jacoco.xml

SONAR_TOKEN — kann auf sonarcloud.io erhalten werden und muss in den Secrets hinterlegt werden. GITHUB_TOKEN — ist ein integrierter Token, den GitHub generiert. Damit kann sonarcloud[bot] in Git einloggen, um uns Kommentare in Pull-Anfragen zu hinterlassen.

Dsonar.projectKey — der Name des Projekts in Sonar, den man in den Projekteinstellungen einsehen kann.

Dsonar.organization — der Name der Organisation in GitHub.

Wir erstellen eine Pull-Anfrage und warten, bis sonarcloud[bot] in den Kommentaren erscheint:

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Release-Management

Der Build ist konfiguriert, die Tests sind durchlaufen, jetzt können wir ein Release erstellen. Lassen Sie uns anschauen, wie GitHub Actions das Release-Management erheblich vereinfacht.

Bei meiner Arbeit habe ich Projekte, deren Codebasis in Bitbucket liegt (alles wie in der Geschichte „Tagsüber schreibe ich in Bitbucket, nachts committe ich in GitHub“). Leider gibt es in Bitbucket keine integrierten Tools zum Management von Releases. Das ist problematisch, denn für jedes Release muss man manuell eine Seite in Confluence anlegen und alle Features, die in das Release eingeflossen sind, dort hinterlegen, sich durch die Gedanken zu wühlen, Aufgaben in Jira durchzugehen, Commits im Repository zu prüfen. Dabei gibt es viele Fehlerquellen; man kann etwas vergessen oder etwas aufschreiben, das bereits im letzten Release war, und manchmal ist es einfach nicht klar, wie man eine bestimmte Pull-Anfrage einordnen soll – ist es ein Feature, ein Bugfix, eine Testanpassung oder etwas Infrastrukturtechnisches?

Wie kann uns GitHub Actions unterstützen? Es gibt eine großartige Action – den Release Drafter. Damit können Sie eine Vorlage für die Release-Notizen festlegen, um die Kategorien der Pull-Requests zu definieren und sie automatisch in der Datei der Release-Notizen zu gruppieren.

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Beispiel einer Vorlage zur Konfiguration des Berichts (.github/release-drafter.yml):

name-template: 'v$NEXT_PATCH_VERSION'
tag-template: 'v$NEXT_PATCH_VERSION'
categories:
  - title: 'Neue Funktionen'
    labels:
      - 'type:features'
# In diese Kategorie sammeln wir alle PRs mit dem Label type:features

  - title: 'Fehlerbehebungen'
    labels:
      - 'type:fix'
# Analog für das Label type:fix usw.

  - title: 'Dokumentation'
    labels:
      - 'type:documentation'

  - title: 'Konfiguration'
    labels:
      - 'type:config'

change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
template: |
  ## Änderungen
  $CHANGES

Fügen Sie das Skript zur Erstellung des Entwurfs für die Veröffentlichung hinzu (.github/workflows/release-draft.yml):

name: "Entwurf für Release erstellen"

on:
  push:
    branches:
      - master

jobs:
  update_draft_release:
    runs-on: ubuntu-18.04
    steps:
      - uses: release-drafter/release-drafter@v5
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Ab diesem Moment werden alle Pull-Requests automatisch in den Release-Notizen gesammelt – Magie!

Es könnte die Frage aufkommen: Was geschieht, wenn die Entwickler vergessen, die Labels im PR zu setzen? Dann ist unklar, in welche Kategorie er gehört, und wir müssen wieder manuell bei jedem PR nacharbeiten. Um dieses Problem zu beheben, können wir eine weitere Aktion nutzen – den Label Verifier – der die Vorhandensein von Tags im Pull-Request überprüft. Wenn kein obligatorisches Tag vorhanden ist, schlägt die Überprüfung fehl, und wir sehen eine entsprechende Nachricht in unserem Pull-Request.

name: "Typ-Labels überprüfen"

on:
  pull_request:
    types: [opened, labeled, unlabeled, synchronize]

jobs:
  triage:
    runs-on: ubuntu-18.04
    steps:
      - uses: zwaldowski/match-label-action@v2
        with:
          allowed: 'type:fix, type:features, type:documentation, type:tests, type:config'

Jetzt muss jeder Pull-Request mit einem der folgenden Tags versehen werden: type:fix, type:features, type:documentation, type:tests, type:config.

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Automatische Annotation von Pull-Requests

Da wir das Thema effektive Arbeit mit Pull-Requests angesprochen haben, sollten wir auch die Aktion Labeler erwähnen, die die Labels im PR basierend auf den geänderten Dateien setzt. Zum Beispiel können wir jeden Pull-Request, der Änderungen im Verzeichnis enthält, als [build] kennzeichnen. .github/workflow.

Die Einbindung ist ziemlich einfach:

name: "Automatische Zuordnung von Themen zu PR"

on:
  - pull_request

jobs:
  triage:
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/labeler@v2
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

Wir benötigen zudem eine Datei, die die Übereinstimmung der Projektverzeichnisse mit den Themen der Pull-Requests beschreibt:

theme:build:
  - ".github/**"
  - "pom.xml"
  - ".travis.yml"
  - ".gitignore"
  - "Dockerfile"

theme:code:
  - "src/main/*"

theme:tests:
  - "src/test/*"

theme:documentation:
  - "docs/**"

theme:TRASH:
  - ".idea/**"
  - "target/**"

Es ist mir nicht gelungen, die Aktion, die automatisch Labels zu Pull-Requests hinzufügt, mit der Aktion, die das Vorhandensein erforderlicher Labels überprüft, zu verbinden. match-label will die vom Bot gesetzten Labels auf keinen Fall erkennen. Es scheint einfacher zu sein, eine eigene Aktion zu schreiben, die beide Schritte kombiniert. Aber selbst in dieser Form ist die Nutzung recht bequem; man muss beim Erstellen eines Pull-Requests ein Label aus der Liste auswählen.

Es ist Zeit, zu deployen

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Ich habe einige Optionen für das Deployment über GitHub Actions (über SSH, über SCP und mit docker-hub) ausprobiert und ich kann sagen, dass Sie wahrscheinlich einen Weg finden werden, das Binary auf den Server zu bringen, egal wie ausgefallen Ihr Pipeline ist.

Ich finde die Idee, die gesamte Infrastruktur an einem Ort zu halten, gut. Lassen Sie uns also anschauen, wie wir ein Deployment in GitHub Packages durchführen können (dies ist ein Repository für binäre Inhalte, npm, jar, docker).

Docker-Image-Bau- und Veröffentlichungsskript für GitHub Packages:

name: Deploy docker image

on:
  push:
    branches:
      - 'master'

jobs:

  build_docker_image:
    runs-on: ubuntu-18.04
    steps:

#     JAR bauen:
      - uses: actions/checkout@v1
      - name: JDK 11 einrichten
        uses: actions/setup-java@v1
        with:
          java-version: 1.11
      - name: Maven-Paket
        run: mvn -B clean compile package -DskipTests

#     Globale Umgebungsvariablen setzen:
      - name: Globale Umgebungsvariablen setzen
        id: global_env
        run: |
          echo "::set-output name=IMAGE_NAME::${GITHUB_REPOSITORY#*/}"
          echo "::set-output name=DOCKERHUB_IMAGE_NAME::docker.pkg.github.com/${GITHUB_REPOSITORY}/${GITHUB_REPOSITORY#*/}"

#     Docker-Image bauen:
      - name: Image bauen und taggen
        run: |
          docker build -t "${{ steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}:latest" -t "${{ steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}:${GITHUB_SHA::8}" .

      - name: Docker-Login
        run: docker login docker.pkg.github.com -u $GITHUB_ACTOR -p ${{secrets.GITHUB_TOKEN}}

#     Bild im GitHub-Paketrepository veröffentlichen:
      - name: Bild veröffentlichen
        env:
          IMAGE_NAME: $GITHUB_REPOSITORY
        run: docker push "docker.pkg.github.com/$GITHUB_REPOSITORY/${{ steps.global_env.outputs.IMAGE_NAME }}"

Zunächst müssen wir die JAR-Datei unserer Anwendung erstellen, danach berechnen wir den Pfad zum GitHub Docker-Registry und den Namen unseres Images. Hier gibt es einige Tricks, mit denen wir bisher nicht konfrontiert waren:

  • Die Konstruktion: echo «::set-output name=NAME::VALUE» ermöglicht es, den Wert einer Variablen im aktuellen Schritt festzulegen, sodass er später in allen anderen Schritten gelesen werden kann.
  • Um den Wert einer im vorherigen Schritt festgelegten Variablen zu erhalten, verwenden wir die ID dieses Schrittes: ${{ steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}
  • In der Standardvariablen GITHUB_REPOSITORY wird der Name des Repositories und seines Besitzers gespeichert („owner/repo-name“). Um aus dieser Zeichenfolge alles außer dem Namen des Repositories zu extrahieren, verwenden wir die Bash-Syntax: ${GITHUB_REPOSITORY#*/}

Als nächstes müssen wir das Docker-Image erstellen:

docker build -t "docker.pkg.github.com/antkorwin/github-actions/github-actions:latest"

Im Registry anmelden:

docker login docker.pkg.github.com -u $GITHUB_ACTOR -p ${{secrets.GITHUB_TOKEN}}

Und das Image im GitHub Packages Repository veröffentlichen:

docker push "docker.pkg.github.com/antkorwin/github-actions/github-actions"

Um die Version des Abbilds anzugeben, verwenden wir die ersten Ziffern des SHA-Hashes des Commits – GITHUB_SHA. Hier gibt es einige Besonderheiten: Wenn Sie solche Builds nicht nur beim Merge in den Master, sondern auch beim Erstellen von Pull-Requests durchführen, kann der SHA von dem Hash abweichen, den wir in der Git-Historie sehen, da die Aktion actions/checkout ihren eigenen einzigartigen Hash erzeugt, um gegenseitige Blockaden in PR zu vermeiden.

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Wenn alles gut gelaufen ist, sehen Sie im Abschnitt Packages (https://github.com/antkorwin/github-actions/packages) im Repository ein neues Docker-Abbild.

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Dort können Sie auch die Liste der Versionen des Docker-Abbilds einsehen.

Jetzt bleibt nur noch, unseren Server für die Arbeit mit diesem Registry einzurichten und den Dienst neu zu starten. Wie das über systemd geht, werde ich wohl ein anderes Mal erzählen.

Überwachung

Lassen Sie uns eine einfache Möglichkeit ansehen, wie wir einen Health-Check unserer Anwendung mit GitHub Actions durchführen können. In unserer Boot-Anwendung gibt es einen Actuator, sodass die API zur Überprüfung des Status nicht einmal geschrieben werden muss – für Faule wurde bereits alles erledigt. Sie müssen nur den Host aufrufen: SERVER-URL:PORT/actuator/health

$ curl -v 127.0.0.1:8080/actuator/health

> GET /actuator/health HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.61.1
> Accept: */*

< HTTP/1.1 200
< Content-Type: application/vnd.spring-boot.actuator.v3+json
< Transfer-Encoding: chunked
< Date: Thu, 04 Jun 2020 12:33:37 GMT

{"status":"UP"}

Alles, was wir brauchen, ist ein Cron-Job, der den Server überprüft. Wenn er nicht antwortet, senden wir eine Benachrichtigung über Telegram.

Zuerst schauen wir uns an, wie man einen Workflow mit Cron ausführt:

on:
  schedule:
    - cron:  '*/5 * * * *'

Es ist ganz einfach, kaum zu glauben, dass man in GitHub solche Ereignisse erstellen kann, die nicht in Webhooks passen. Details findest du in der Dokumentation: help.github.com/en/actions/reference/events-that-trigger-workflows#scheduled-events-schedule

Wir überprüfen den Serverstatus manuell mit curl:

jobs:
  ping:
    runs-on: ubuntu-18.04
    steps:

      - name: curl actuator
        id: ping
        run: |
          echo "::set-output name=status::$(curl ${{secrets.SERVER_HOST}}/api/actuator/health)"

      - name: health check
        run: |
          if [[ ${{ steps.ping.outputs.status }} != *"UP"* ]]; then
            echo "Health-Check ist fehlgeschlagen"
            exit 1
          fi
          echo "Alles in Ordnung"

Zuerst speichern wir in einer Variablen, was der Server als Antwort auf die Anfrage gesendet hat. Im nächsten Schritt überprüfen wir den Status UP und, falls das nicht der Fall ist, brechen wir mit einem Fehler ab. Wenn wir die Aktion manuell "abbrechen" möchten, dann exit 1 ist das das passende Mittel.

  - name: Benachrichtigung in Telegram senden
    if: ${{ failure() }}
    uses: appleboy/telegram-action@master
    with:
      to: ${{ secrets.TELEGRAM_TO }}
      token: ${{ secrets.TELEGRAM_TOKEN }}
      message: |
        Gesundheitscheck für:
        ${{secrets.SERVER_HOST}}/api/actuator/health
        ist fehlgeschlagen mit folgendem Ergebnis:
        ${{ steps.ping.outputs.status }}

Wir senden die Nachricht nur, wenn der vorherige Schritt fehlgeschlagen ist. Für das Senden der Nachricht verwenden wir appleboy/telegram-action. Informationen zur Erlangung des Bot-Tokens und der Chat-ID finden Sie in der Dokumentation: github.com/appleboy/telegram-action

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Vergessen Sie nicht, in den GitHub-Secret zu hinterlegen: die URL für den Server und die Tokens für den Telegram-Bot.

Bonus-Track — JIRA für Faule

Ich hatte versprochen, dass wir zu JIRA zurückkehren, und hier sind wir. Hunderte Male habe ich bei Stand-ups die Situation beobachtet, dass Entwickler ein Feature erstellt, den Branch zusammengeführt haben, aber vergessen haben, die Aufgabe in JIRA zu verschieben. Natürlich wäre es einfacher, wenn alles an einem Ort erledigt würde, aber tatsächlich schreiben wir den Code in der IDE, führen Branches in Bitbucket oder GitHub zusammen und verwalten die Aufgaben später in JIRA. Dazu müssen wir neue Fenster öffnen, manchmal uns erneut einloggen usw. Wenn man genau weiß, was als Nächstes zu tun ist, macht es keinen Sinn, das Board erneut zu öffnen. Am Ende muss man morgens beim Stand-up Zeit für die Aktualisierung des Taskboards aufwenden.

GitHub wird uns auch bei dieser Routineaufgabe helfen. Zunächst können wir Aufgaben automatisch in die Spalte code_review verschieben, sobald wir einen Pull-Request erstellt haben. Alles, was wir tun müssen, ist, uns an die Namenskonvention für Branches zu halten:

[projektnamen]-[aufgabenummer]-titel

zum Beispiel, wenn der Schlüssel des Projekts "GitHub Actions" GA ist, dann GA-8-jira-bot kann der Branch für die Umsetzung der Aufgabe GA-8 sein.

Die Integration mit JIRA funktioniert über die Aktionen von Atlassian. Sie sind nicht perfekt, ich muss sagen, dass einige von ihnen bei mir überhaupt nicht funktioniert haben. Aber wir werden nur die besprechen, die tatsächlich funktionieren und aktiv genutzt werden.

Zunächst müssen Sie sich bei JIRA über die Aktion anmelden: atlassian/gajira-login

jobs:
  build:
    runs-on: ubuntu-latest
    name: Jira Workflow
    steps:
      - name: Login
        uses: atlassian/gajira-login@master
        env:
          JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
          JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
          JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}

Dafür müssen Sie ein Token in JIRA erhalten. Wie das geht, wird hier beschrieben: confluence.atlassian.com/cloud/api-tokens-938839638.html

Wir extrahieren die Aufgaben-ID aus dem Branch-Namen:

  - name: Problem finden
    id: find_issue
    shell: bash
    run: |
      echo "::set-output name=ISSUE_ID::$(echo ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}')"
      echo branch name: $GITHUB_HEAD_REF
      echo extrahierte Problemmat: ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}'

  - name: Problem überprüfen
    shell: bash
    run: |
      if [[ "${{steps.find_issue.outputs.ISSUE_ID}}" == "" ]]; then
        echo "Bitte benennen Sie Ihren Branch gemäß dem JIRA-Problem: [project_key]-[task_number]-branch_name"
        exit 1
      fi
      echo erfolgreich gefundenes JIRA-Problem: ${{steps.find_issue.outputs.ISSUE_ID}}

Wenn man im GitHub-Marktplatz sucht, findet man eine Aktion für diese Aufgabe, aber ich musste dasselbe mit grep nach dem Branch-Namen schreiben, da diese Aktion von Atlassian in meinem Projekt einfach nicht funktionieren wollte, herauszufinden, was dort nicht stimmte, dauerte länger, als es manuell zu tun.

Es bleibt nur noch, die Aufgabe beim Erstellen des Pull-Requests in die Spalte „Code-Review“ zu verschieben:

  - name: Problem übertragen
    if: ${{ success() }}
    uses: atlassian/gajira-transition@master
    with:
      issue: ${{ steps.find_issue.outputs.ISSUE_ID }}
      transition: "Code-Review"

Dafür gibt es eine spezielle Aktion auf GitHub, alles, was sie benötigt, ist die im vorherigen Schritt erhaltene Aufgaben-ID und die zuvor vorgenommene Authentifizierung in JIRA.

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Auf die gleiche Weise können Aufgaben beim Mergen in den Master und in anderen Szenarien des GitHub-Workflows verschoben werden. Letztendlich hängt alles von Ihrer Kreativität und dem Drang ab, Routineprozesse zu automatisieren.

Fazit

Wenn man sich das klassische DEVOPS-Diagramm ansieht, haben wir alle Phasen abgedeckt, bis auf die Betriebsphase. Ich denke, wenn man ein wenig sucht, findet man sicher eine Aktion im Marketplace für die Integration mit einem Helpdesk-System. Daher können wir davon ausgehen, dass unser Pipeline umfassend ist und auf deren Grundlage wertvolle Erkenntnisse gewonnen werden können.

GitHub Actions im Einsatz: CI/CD-Pipeline für ein Java-Projekt aufbauen

Vorteile:

  • Der Marketplace mit fertigen Aktionen für alle Lebenslagen ist großartig. In den meisten Fällen kann man auch den Quellcode einsehen, um zu verstehen, wie man ein ähnliches Problem lösen kann, oder direkt im GitHub-Repository eine Feature-Anfrage beim Autor posten.
  • Die Auswahl der Zielplattform für den Build: Linux, macOS, Windows ist eine sehr interessante Funktion.
  • GitHub Packages ist eine großartige Lösung. Es ist praktisch, die gesamte Infrastruktur an einem Ort zu haben, man muss nicht durch verschiedene Fenster suchen; alles ist innerhalb von ein oder zwei Klicks erreichbar und perfekt mit GitHub Actions integriert. Die Unterstützung von Docker-Registries in der kostenlosen Version ist ebenfalls ein gutes Plus.
  • GitHub versteckt Geheimnisse in den Build-Logs, daher ist es nicht so schlimm, ihn zur Speicherung von Passwörtern und Tokens zu verwenden. Während all meiner Experimente ist es mir nie gelungen, ein Geheimnis in reiner Form in der Konsole zu sehen.
  • Kostenlos für Open-Source-Projekte

Nachteile:

  • YML, ich mag es einfach nicht. Bei der Arbeit mit einem solchen Workflow ist meine häufigste Commit-Nachricht «fix yml format», weil man irgendwo vergisst, ein Tab zu setzen oder es nicht in der richtigen Zeile schreiben kann. Insgesamt ist es nicht besonders angenehm, mit einem Geodreieck und einem Lineal vor dem Bildschirm zu sitzen.
  • DEBUG, das Debugging des Workflows durch Commits, das Starten von Neuaufbauen und das Ausgeben in die Konsole ist nicht immer bequem, aber das ist mehr so eine Sache von «ihr seid verwöhnt», ihr habt euch daran gewöhnt, mit komfortablen IDEs zu arbeiten, wo man alles debuggen kann.
  • Sein eigenes Action kann man mit allem Möglichen schreiben, solange man es in Docker verpackt, aber nativ wird nur JavaScript unterstützt. Natürlich ist das Geschmackssache, aber ich würde etwas anderes statt js bevorzugen.

Zur Erinnerung, das Repository mit allen Skripten ist hier: github.com/antkorwin/github-actions

Nächste Woche werde ich mit einem Vortrag auftreten über Auf der Heisenbug 2020 Piter-Konferenz werde ich nicht nur darüber sprechen, wie man Fehler bei der Vorbereitung von Testdaten vermeiden kann, sondern auch meine Geheimnisse im Umgang mit Datensätzen in Java-Anwendungen teilen!

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster