­čŚÖ Gitea Actions - Jekyll Workflow

6 Minute(n) Lesezeit

Nachdem ich in diesem Projekt meinen eigenen, kleinen Server aufgesetzt und mit den entsprechenden Programmen zum Hosten meines Blogs ausgestattet habe, m├Âchte ich ihn nun in die Lage versetzen, die Website automatisch zu bauen.

Gew├╝nschter Ablauf

Ich m├Âchte folgendes erreichen: Sobald Gitea eine push-Aktion auf dem Blog-Repository verzeichnet, soll ein Action Runner in einem eigenen Docker-Container loslaufen und Ruby, Bundler, Jekyll sowie s├Ąmtliche Abh├Ąngigkeiten nachladen. Dann soll der Runner meine Quelldateien f├╝r den Blog kopieren und dem bundle exec jekyll build Prozess zur Verf├╝gung stellen, welcher dann die Website baut und schlie├člich im _site-Ordner ablegt. Anschlie├čend soll der Runner sich selbst beenden und alle in Anspruch genommenen Ressourcen wieder freigeben.

An dieser Stelle m├Âchte ich nachkontrollieren k├Ânnen, ob die Website fehlerfrei gebaut wurde und in Zukunft eventuell noch ein paar weitere Pr├╝fungen dar├╝berlaufen lassen - z.B. kaputte Links erkennen, nicht angezeigte Bilder markieren, Rechtschreibpr├╝fung durchf├╝hren.

Die Freigabe sowie die Ver├Âffentlichung soll dann ein anderer Prozess ├╝bernehmen, um den ich mich sp├Ąter k├╝mmere.

Ausgangspunkt: Github Actions

Wie ├╝blich wildere ich erst einmal bei anderen Menschen, die ein ├Ąhnliches Problem f├╝r sich bereits gel├Âst haben. Ich wurde im Github Actions starter-workflows Repository von Github selbst f├╝ndig und habe die Workflowdatei f├╝r Jekyll mit leichten Modifikationen direkt mal mit meiner Gitea-Instanz ausprobiert:

# jekyll-build-pages.yml
# Sample workflow for building and deploying a Jekyll site
name: Deploy Jekyll site
run-name: $ builds Jekyll site
on: [push]

jobs:
  # Build job
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Setup Ruby
        uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
        with:
          ruby-version: '3.1' # Not needed with a .ruby-version file
          bundler-cache: true # runs 'bundle install' and caches installed gems automatically
          cache-version: 0 # Increment this number if you need to re-download cached gems
#[...]

Nachdem ich diesen Workflow in mein Blogverzeichnis unter workflows/jekyll.yml hochgeladen hatte, lief der Runner tats├Ąchlich direkt los:

Image: Gitea action runner returns error on ruby install

Probleme mit der Ruby-Installation

Schon mal prima. Allerdings wenig erbaulich, dass bereits bei der Installation von Ruby etwas nicht passt. Werfen wir einen Blick in die Logs:

::error::The current runner (debian-11-x64) was detected as self-hosted because the platform does not match a GitHub-hosted runner image 
(or that image is deprecated and no longer supported).
In such a case, you should install Ruby in the $RUNNER_TOOL_CACHE yourself, for example using https://github.com/rbenv/ruby-build
You can take inspiration from this workflow for more details: 
https://github.com/ruby/ruby-builder/blob/master/.github/workflows/build.yml

Na, das ist doch mal eine hilfreiche Fehlermeldung!

Der Runner l├Ąuft um Ressourcen zu sparen standardm├Ą├čig im Docker mit einem abgespeckten Image basierend auf Debian namens node:16-bullseye (Referenz). Scheinbar ist dieser nicht kompatibel mit dem unter Ubuntu22 betriebenen Github Actions Runner. Ich habe also ein paar L├Âsungsm├Âglichkeiten zur Verf├╝gung:

M├Âglichkeiten zur Fehlerbehebung

  • Den Runner ├╝ber seine ÔÇťLabelsÔÇŁ auf Ubuntu22.04 umsatteln.
  • Ren Runner nicht im Docker, sondern nativ auf dem Server laufen lassen.
  • Wie in der Fehlermeldung vorgeschlagen, Ruby im Cache des Runners vorinstallieren.
  • Ein Jekyll-Dockerimage verwenden, welches Jekyll bereits im Gep├Ąck hat und nicht erst die Installation ben├Âtigt.

Den Runner mit Ubuntu22 statt Node16 betreiben

Das entsprechende Dockerimage existiert zwar. Aber es kostet aber einen Haufen Speicherplatz auf meinem Server, ben├Âtigt durch seinen gr├Â├čeren Funktionsumfang mehr RAM und braucht vor allem l├Ąnger, bis es hochgefahren ist.

Und Zeit ist bei Runnern wertvoll, schlie├člich will ich ja m├Âglichst schnell wissen, ob das Bauen geklappt hat.

Den Runner direkt auf der Hostmaschine (Ubuntu22) laufen lassen

Ist sicherheitstechnisch nicht so sehr zu empfehlen (Bei einem ungesch├╝tzten Branch w├╝rde der Runner von Dritten per git push --force hochgeschobenen Schadcode unbesehen auf meiner Hostmaschine ausf├╝hren) und zudem ginge die Portabilit├Ąt fl├Âten, weil ich das Zielsystem des Runners dann fest verdrahte.

Gitea act_runner direkt auf dem Host laufen lassen

F├╝r den zweiten Ansatz habe ich mir per Anleitung eine Konfiguration f├╝r den runner angelegt und darin das bestehende label-mapping so ge├Ąndert, dass nicht mehr in Richtung Docker, sondern auf dem Ubuntu des Servers selbst gebaut wird. Daf├╝r gen├╝gt es in meinem Fall, das Label ubuntu-latest:host statt ubuntu-latest in die Konfiguration zu schreiben. Leider erhielt ich hier Fehlermeldungen bei den Zugriffsrechten des Runners, welcher aus Docker heraus auf dem Hostsystem laufen m├╝sste.

Nicht so schlimm, ich wollte diese L├Âsung wegen der oben beschriebenen m├Âglichen Probleme sowieso nicht dauerhaft verwenden. Also investiere ich hier keine weitere Zeit.

Ruby im Cache vorinstallieren

Wie von der Fehlermeldung empfohlen habe ich dieser Anleitung folgend in der docker-compose.yml von Gitea ein Volume angelegt f├╝r den Tool Cache des runners und das Zielverzeichnis in der Umgebungsvariable RUNNER_TOOL_CACHE abgelegt.

# gitea/docker-compose.yml
# [...]
runner:
    image: gitea/act_runner:nightly
    environment:
      - GITEA_INSTANCE_URL=<redacted>
      - GITEA_RUNNER_NAME=<redacted>
      - RUNNER_TOOL_CACHE=/opt/hostedtoolcache
      - GITEA_RUNNER_REGISTRATION_TOKEN= <redacted>
    volumes:
      - ./runner/data:/data
      - /opt/hostedtoolcache:/opt/hostedtoolcache
      - /var/run/docker.sock:/var/run/docker.sock

Hiermit wird dem in Docker laufenden Runner der Ordner /opt/hostedtoolcache im Dateisystem des Hosts unter dem Namen /opt/hostedtoolcache zur Verf├╝gung gestellt. Nun probiere ich mal, Ruby direkt dort hinein zu installieren.

Also lade ich das ruby-build repository herunter (git clone) und lasse das Installerscript mit ./ruby-build/install.sh durchlaufen. Danach f├╝hre ich den Build mit dem in der Fehlermeldung angegebenen Pfad aus: ruby-build 3.1.4 /opt/hostedtoolcache/Ruby/3.1.4/x64

==> Downloading openssl-3.1.4.tar.gz...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 14.8M  100 14.8M    0     0  81.3M      0 --:--:-- --:--:-- --:--:-- 81.1M
==> Installing openssl-3.1.4...

BUILD FAILED (Ubuntu 22.04 on x86_64 using ruby-build 20231114)

Probleme mit prebuilt-Ruby

Das Log zeigt das Problem:

[...] No C compiler found, please specify one with the environment variable CC [...]

Also tippe ich apt install build-essential und stelle dann mit which gcc fest, dass er nun unter /usr/bin/gcc installiert ist. Auf ein Neues!

crypto/comp/c_zlib.c:36:11: fatal error: zlib.h: No such file or directory

Dann schnell apt install libz-dev eingeben und erneut probieren. Dieses mal l├Ąuft er recht lange, dann:

*** Following extensions are not compiled:
openssl:
        Could not be configured. It will not be installed.
        /tmp/ruby-build.20231205114312.9174.0gmhNf/ruby-3.1.4/ext/openssl/extconf.rb:100: OpenSSL library could not be found. You might Check ext/openssl/mkmf.log for more details.
readline:
        Could not be configured. It will not be installed.
        /tmp/ruby-build.20231205114312.9174.0gmhNf/ruby-3.1.4/ext/readline/extconf.rb:62: Neither readline nor libedit was found
        Check ext/readline/mkmf.log for more details.
*** Fix the problems, then remove these directories and try again if you want.
[...]

OK, nun ist es openssl. Fix nachinstallieren mit apt install libssl-dev sowie apt install libreadline-dev und endlich ­čÄë:

Installed ruby-3.1.4 to /opt/hostedtoolcache/Ruby/3.1.4/x64

Noch immer Fehler beim Bauen mit dem Github-Acitons script

Merkw├╝rdig, das Log spuckt mir immer noch denselben Fehler aus:

­čĺČ  ::debug::isExplicit: 3.1.4

gitea-runner-1  | [Deploy Jekyll site/build]   ­čĺČ  ::debug::checking cache: /opt/hostedtoolcache/Ruby/3.1.4/x64
gitea-runner-1  | [Deploy Jekyll site/build]   | ::debug::checking cache: /opt/hostedtoolcache/Ruby/3.1.4/x64
gitea-runner-1  | [Deploy Jekyll site/build]   ­čĺČ  ::debug::not found
gitea-runner-1  | [Deploy Jekyll site/build]   | ::debug::not found
gitea-runner-1  | [Deploy Jekyll site/build]   ÔŁŚ  ::error::The current runner (debian-11-x64) was detected as self-hosted

Das geht auf folgende Abfage in der ausf├╝hrenden Action zur├╝ck:

//  setup-ruby/ruby-builder.js
if (common.shouldUseToolCache(engine, version)) {
    inToolCache = common.toolCacheFind(engine, version)
    if (inToolCache) {
      rubyPrefix = inToolCache
    } else {
      const toolCacheRubyPrefix = common.getToolCacheRubyPrefix(platform, engine, version)
      if (common.isSelfHostedRunner()) {
        const rubyBuildDefinition = engine === 'ruby' ? version : `${engine}-${version}`
        core.error( [...] )

Update Jan-2024

Es es gibt zwei weitere M├Âglichkeiten daf├╝r, dass der toolcache nicht gefunden wird:

  1. Ich habe das Volume nicht der Action, sondern dem Runner zur Verf├╝gung gestellt. Ich bin mir nicht sicher, dass die Daten auch in der Action verf├╝gbar sind.
  2. Der toolcache-Pfad ist nicht in der Konfigurationsdatei des runners unter dem Eintrag valid_volumes enthalten. Eine pull request Kommunikation l├Ąsst mich jedoch vermuten, dass dies automatisch passiert. Dennoch bin ich mir nicht 100% sicher, ob die Information noch dem Stand der Dinge entspricht.

Docker volume ├╝berpr├╝fen

Mist. Pr├╝fen wir schnell mal, ob Ruby in dem Volume auch wirklich verf├╝gbar ist. Daf├╝r suchen wir mit docker ps die Container ID des runners heraus und geben sie bei folgendem Kommando ein:

docker exec -it <containerID> bash

Dann navigiere ich in den gesuchten Ordner cd /opt/hostedtoolcache, liste dort den Inhalt mit ls und siehe da: Ruby. Es liegt also alles vor, nur wird es nicht gefunden.

Misserfolg anerkennen

So komme ich hier also nicht weiter ­čśľ. Daher ├Âffne ich mein Problem f├╝r die Community unter dem Titel act_runner cannot find hostedtoolcache und probiere

einen anderen Ansatz.

Problemursache

Der Support der Action setup-ruby f├╝r selbsgehostete CI-Pipelines wie meinen act_runner wurde wohl eingestellt. Die Dokumentation mit den Hinweisen zur Fehlerbehebung bei Verwendung selbstgehosteter Runner allerdings zum Zeitpunkt der Verwendung durch meine Wenigkeit war aber noch nicht auf Stand gebracht worden.