Blog

perlbrew

14.07.2021 // Gregor Goldbach

Das System-Perl zu verwenden hat viele Nachteile. Diese können behoben werden, wenn man ein eigenes Perl in seinem Benutzerverzeichnis installiert. Mit dem Werkzeug perlbrew kannst du mehrere Perl-Installationen nebeneinander auf einem System konfliktfrei betreiben.

Die Probleme mit dem System-Perl

Die Anwendungsentwicklung mit dem System-Perl zu koppeln bringt viele Nachteile mit sich. Hier einige Beispiele:

  • Perl kann nicht unabhängig vom System aktualisiert werden, wenn du Probleme beheben möchtest, neue Sprach-Features nutzen willst – oder vielleicht sogar ganz bewusst ein Perl nutzen möchtest, das älter als das System-Perl ist.
  • In Organisationen sind Entwickler häufig von den Systemadministratoren abhängig, die die Stabilität des gesamten Systems und nicht nur einer Anwendung beachten müssen, und deswegen nicht »einfach so« Perl aktualisieren können.
  • Die Installation von CPAN-Modulen ist wegen fehlender Berechtigungen nicht möglich.
  • Der Test von Anwendung unter neueren Perl-Versionen auf einem System ist nicht einfach möglich.

Eine Lösung ist perlbrew, das die Installation mehrerer Perl-Versionen im Benutzerverzeichnis ermöglicht, so dass keine Administratorrechte benötigt werden. Das Werkezeug isoliert diese Installationen voneinander und ermöglicht einen einfachen Wechsel zwischen ihnen.

Admin-freie Installation von Perl-Versionen

Die Installation von perlbrew ist auf zwei Wegen möglich. Die einfachste geht über cpanm:

$ cpanm App::perlbrew
$ perlbrew init

Solltest du keine Module von CPAN installieren können (siehe meine Anmerkung oben zu fehlenden Adminstratorrechten), kannst du dir ein Installationsskript herunterladen und es von der Shell ausführen lassen. Aus Sicherheitsgründen verweise ich dich dafür auf die Homepage.

perlbrew kann alle offiziell verfügbaren Perl-Versionen bauen und installieren. Welche das sind, kannst du dir auflisten lassen:

$ perlbrew available
   perl-5.33.7   
   perl-5.32.1   
   perl-5.30.3   
   perl-5.28.3   
  perl-5.26.3.tar.bz2
  ...
    perl-5.8.9.tar.bz2   
    perl-5.6.2   
  perl5.005_03   
  perl5.004_05   
  cperl-5.29.2   
  cperl-5.30.0   
  cperl-5.30.0-RC1 

Aus diesen Versionen wählst du dir eine aus. Diese wird dann in das Verzeichnis perl5/perlbrew im Benutzerverzeichnis installiert:

perlbrew install perl-5.33.7
$ perlbrew install perl-5.33.7
Fetching perl 5.33.7 as $HOME/perl5/perlbrew/dists/perl-5.33.7.tar.gz
Download http://www.cpan.org/src/5.0/perl-5.33.7.tar.gz to $HOME/perl5/perlbrew/dists/perl-5.33.7.tar.gz
Installing /Users/glauschwuffel/perl5/perlbrew/build/perl-5.33.7/perl-5.33.7 into ~/perl5/perlbrew/perls/perl-5.33.7

This could take a while. You can run the following command on another shell to track the status:

  tail -f ~/perl5/perlbrew/build.perl-5.33.7.log

Wenn du den in der letzten Zeile angegeben Befehl in einer zweiten Shell ausführt, kannst du dem Installationprozess »zusehen«.

Welches Perl die Shell ausführt, wird durch den Ausführungspfad bestimmt. Durch die Änderung dieses Ausführungspfads wird zwischen den installierten Perl-Versionen umgeschaltet. Dafür gibt es den perlbrew-Befehl use:

$ perlbrew use perl-5.33.7

Durch mehrfache Verwendung von perlbrew use kannst du in einer Arbeitssitzung in der Shell zwischen den Versionen wechseln. Beim Öffnen einer weiteren Shell wird aber weiterhin das System-Perl verwendet. Wenn du dauerhaft eine Perl-Version verwenden möchtest, kann du mit dem Befehl switch die gewünschte Version in der Shell-Konfiguration ablegen:

perlbrew switch perl-5.33.7

Gelegentlich kommt es bei der Arbeit mit perlbrew vor, dass kurzfristig das System-Perl benutzt werden soll:

perlbrew switch-off

Mit den hier gezeigten Befehlen hast du nun die grundlegenden Werkzeuge zusammen, um dir die Perl-Versionen zu installieren, die du benötigst. Da sich alles in deinem Benutzerverzeichnis abspielt, hast du die volle Kontrolle.

Zusammenfassung

In diesem Artikel habe ich einen kurzen Überblick über die Möglichkeiten gegeben, die perlbrew bietet. Dabei konnte ich vieles nur anreißen. Wenn du jetzt neugierig geworden bist und tiefer einsteigen möchtest, empfehle ich dir die Homepage des Projekts, um mehr über weitere Befehle zu erfahren.


Permalink:

Wie nutzen wir Gitlab?

01.09.2020 // Gregor Goldbach

Gitlab ist eine webbasierte Plattform für die kontinuierliche Auslieferung von Software. Diese Plattform bietet viele Funktionen, die über die reine Softwareentwicklung und das Deployment hinausgehen. Wir erstellen damit Perl-Distributionen, Docker-Images sowie Dokumentation.

Hauptteil

Gitlab ist eine webbasierte Plattform für die kontinuierliche Auslieferung von Software. Unter anderem integriert es Komponenten wie ein Wiki, ein Ticket-System und die Unterstützung des Versionskontrollsystems Git. Außerdem bietet es eine automatisierte Ausführung von beliebigem Code in Docker-Images an, die von Commits ausgelöst werden können.

Welche Befehle ausgeführt werden, kann man in einer YAML-Datei beschreiben. Dort wird auch beschrieben, welches Docker-Image dafür verwendet werden soll und unter welchen Bedingungen die Befehle ausgeführt werden sollen.

Wie wir bei Perl-Services diese Möglichkeiten nutzen, beschreibe ich in diesem Artikel.

Automatisiertes Erstellen von Perl-Distributionen

Als wir begonnen haben, Gitlab zu evaluieren, haben wir zunächst kleinere Perl-Distributionen als Projekt angelegt und die Git-Repositorys eingebunden. In den YAML-Dateien dieser Projekte haben wir dann konfiguriert, dass nach jedem Commit die Unit-Tests ausgeführt werden und zum Abschluss die Perl-Distribution paketiert werden sollen. Hier ein Auszug aus einem mittlerweile so nicht mehr existenten Projekt:

image: ubuntu:rolling

build:
  script:
    - apt-get update -qq
    - cpanm --installdeps .
    - dzil authordeps | cpanm
    - dzil listdeps | cpanm
    - dzil build

artifacts:
    when: always
    name: "${CI_BUILD_STAGE}_${CI_BUILD_REF_NAME}"
    paths:
      - *.tar.gz

Unser Ansatz war zunächst, Fehler durch Tests zu finden und bei erfolgreichem Testdurchlauf die Perl-Distribution zu erstellen. Die benötigten Abhängigkeiten haben wir mit cpanm installiert. Dabei haben wir festgestellt, dass wir gerne schneller Rückmeldung erhalten würden. Dies führte dann dazu, dass wir die Build-Pipeline optimiert haben.

Verkürzte Durchlaufzeiten erreichen wir einerseits durch eine Anpassung der Befehle, andererseits aber auch dadurch, dass wir ein Docker-Image verwenden, das für diese Distribution optimiert ist und bereits alle Abhängigkeiten enthält.

Was sind die nächsten Schritte? Wir prüfen, ob wir die erfolgreich gebauten Distributionen automatisiert in einen Pinto-Server laden oder auf CPAN veröffentlichen.

Erzeugen von Docker-Images

Im vorherigen Abschnitt habe ich erwähnt, dass wir Docker-Images für die Entwicklung von Perl-Distributionen optimieren. Wir wollen dafür alle Abhängigkeiten einer Perl-Distribution in einem Docker-Image zur Verfügung stellen, damit wir die Durchlaufzeit der Perl-Distribution klein halten und dann schnell Rückmeldung nach einem Commit bekommen.

Wie haben wir dies mit Gitlab erreicht? Wir setzen Dist::Zilla ein und beschreiben Abhängigkeiten über dessen Konfiguration dist.ini und das cpanfile. Im verwendeten Docker-Image werden diese darüber beschriebenen Abhängigkeiten mit cpanm installiert.

Dafür haben wir Gitlab so konfiguriert, dass bei einer Änderung dieser Dateien im Master-Branch der Perl-Distribution das verwendete Docker-Image neu erstellt wird. Hier ein beispielhafter Auszug aus einer Gitlab-Konfiguration:

trigger_image_build:
  stage: trigger
  script:
    - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=master https://gitlab.com/api/v4/projects/9398220/trigger/pipeline
  only:
    refs:
      - /^master$/
    changes:
      - cpanfile
      - dist.ini

Die Beschreibungen der Abhängigkeiten werden beim Erstellen des Docker-Images aus dem abhängigen Projekt gelesen. Hier ein beispielhafter Auszug aus einem Dockerfile:

RUN cd /home/mydocker/src && \
  git clone https://gitlab-ci-token:${CI_TOKEN}@gitlab.com/perlservices/project.git && \

[...]
  
RUN cd /home/mydocker/src/project && \
   cpanm --skip-satisfied --installdeps . && \
   dzil authordeps --missing | cpanm --skip-satisfied && \
   dzil listdeps | cpanm --skip-satisfied

Die Gitlab-Dokumentation hat uns hier teilweise eher verwirrt als geholfen, aber letzten Endes haben wir ein perfekt abgestimmtes Image erhalten, in dem alle Abhängigkeiten enthalten sind. Dadurch können in dem Projekt, das auf diesem Image basiert, nach einem Commit sofort die Unit-Tests ausgeführt werden können.

Die Durchlaufzeiten sind daher sehr gering und liegen bei einem gehosteten Gitlab-Repository bei etwa drei Minuten. Der Löwenanteil dieser drei Minuten liegt darin begründet, dass wir auf einen freien Gitlab-Runner warten müssen.

Um die Durchlaufzeiten weiter zu verringern, migrieren wir die Repositorys derzeit auf einen eigenen Gitlab-Server.

Hinweis: Das müssen wir wegen dem Fall des Privacy Shields ohnehin machen 🙂

Dokumentation erstellen

Die in Projekten zu erstellende Dokumentation reicht je nach Wunsch des Kunden von kurzen Beschreibungen über HTML-Dateien bis zu sauber mit LaTeX gesetzten Dokumenten. Das Ausgangsformat der Dokumente ist für uns stets Markdown, da dies einfach zu schreiben ist, wir uns auf das Wesentliche konzentrieren können und alle gewünschten Zielformate erzeugt werden können.

In Gitlab erzeugen wir mit pandoc aus den Quelldateien das Zielformat. Gegebenenfalls verarbeiten wir das Resultat automatisiert weiter. Wenn als Ergebnis beispielsweise ein PDF erzeugt werden soll, dann bedeutet dies, dass wir aus Markdown LaTeX-Dokumente erzeugen und diese im Anschluss mit lualatex in ein PDF wandeln. Damit dies möglich ist, haben wir uns ein Docker-Image erstellt, in dem TeX Live installiert ist.

Da wir lualatex aus TeX Live einsetzen, ist unser Docker-Image mehrere Gigabyte groß. Diese Kröte müssen wir wohl schlucken. Pandoc leistet sehr gute Dienste und die Entscheidung für Markdown als Ausgangsformat hat sich bewährt.

Wir werden diese Kombination beibehalten, jedoch gelegentlich prüfen, ob wir das Docker-Image etwas verkleinern können 🙂

Zusammenfassung

Wir erstellen mit Gitlab automatisiert Perl-Distributionen, Docker-Images und Dokumente in unterschiedlichen Formaten. Gitlab als Plattform hat sich hierfür bewährt. Durch den Einsatz einer selbst betriebenen Gitlab-Instanz erhoffen wir uns geringere Durchlaufzeiten.

Links


Permalink: