Rund um Lua und sein NuGet-Paket ist eine Menge passiert.

Lua 5.4.5 wurde veröffentlicht. Es war also Zeit für ein Update meines Lua NuGet Pakets. Und für eine Überraschung. Und für Schmerzen.

Am Ende wurde alles gelöst, und die neue Version des Lua NuGet-Pakets ist online.

Allerdings wurde der Lua-5.4.5-Release wieder entfernt, und hoffentlich kommt schnell Lua 5.4.6.

Update 20230514: Lua 5.4.6 is here!

Die Überraschung: Das Lua NuGet-Paket war nicht gelisted!?

Vor einigen Monaten haben meine Benachrichtigungen von Github aufgehört zu funktionieren. Keine Ahnung, warum. Aber da ich dort nicht viel Updates habe, war es für mich nie eine hohe Priorität, das zu fixen. Aus diesem Grund hätte ich dieses von Smurf-IV aufgeworfene Problem fast übersehen: „[Question] Why does nuget state that the packages have been witdrawn ?

Woot? Ich habe absolut keine Ahnung, was dort passiert ist. Aber ich habe eine Vermutung. Das NuGet-Paket wurde ursprünglich von der CoApp-Organisation erstellt. Irgendwann haben sie es jedoch nicht mehr aktualisiert. Als ich eine neuere Version von Lua benötigte, beschloss ich, selbst ein NuGet-Paket zu erstellen. Ich hatte bereits gute Erfahrungen mit der Erstellung nativer C++-NuGet-Pakete gemacht, also habe ich es ausprobiert, und es hat gut funktioniert. Zu diesem Zeitpunkt wandte ich mich an die CoApp-Organisation und fragte sie, ob ich das NuGet-Paket für Lua mitverfassen dürfte. Meine Idee war, dass ich dieses Paket unter Verwendung der schönen und präzisen NuGet-Paket-ID veröffentlichen könnte. Sie stimmten zu, gaben mir die Co-Autorenschaft, und seither veröffentliche ich NuGet-Pakete für jede Version von Lua.

Und nun wurde das Paket vom „Autor“ nicht mehr gelistet und als veraltet und mit kritischen Fehlern versehen gekennzeichnet. Was? Das kann ich Ihnen sagen, ich war es nicht!

Die Sache mit den „kritischen Fehlern“ hat mich ein wenig beunruhigt. In meinem früheren Job war ich auch damit beauftragt, unsere Codebasis regelmäßig auf CVEs zu überprüfen. Ich kenne also ein paar Dinge, auf die man achten muss. Ich habe einen schnellen Check für Lua gemacht, und ja, es gibt CVEs, aber nichts Ungewöhnliches. Nichts so Schwerwiegendes, dass das Paket so stark eingeschränkt werden müsste.

Und noch etwas wurde deutlich: Die CoApp-Org scheint überhaupt keine NuGet-Pakete mehr zu besitzen. Keines. Das ist ziemlich überraschend.

Also, meine Vermutung ist, dass die CoApp-Organisation auf NuGet vielleicht aufgelöst wurde, aber mit Sicherheit ihr Engagement für die Wartung der NuGet-Pakete eingestellt hat. Als Vorsichtsmaßnahme wurden alle NuGets abgeschaltet und vielleicht automatisch als veraltet und veraltet markiert. Bei der Sache mit den „kritischen Fehlern“ bin ich mir nicht sicher. Deshalb gehe ich von einer automatischen „Abschaltung“ aus, bei der wahllos alle Pakete markiert und aus der Liste entfernt wurden.

Nun, mein Commitment, das Lua-Nuget-Paket zu pflegen, bleibt bestehen!

Ich werde weiterhin Versions-Updates und ähnliches veröffentlichen. Deshalb habe ich die 5.4.x Versionen des Lua-Pakets (wieder) aufgelistet und die Warnhinweise, dass sie veraltet sind, veraltet sind oder kritische Fehler haben, entfernt. Über die Beweggründe der CoApp-Gruppe kann ich nur spekulieren. Aber das werde ich nicht tun.

Der Schmerz: Umzug von AppVeyor zu Github Actions

All dies geschah im Zuge der Veröffentlichung der Version 5.4.5 von Lua. Eine Aufgabe, die seit langem auf meiner ToDo-Liste steht, war die Migration und Konsolidierung der verschiedenen Code- und CI-Plattformen. Bis jetzt habe ich die verschiedenen Varianten von Lua für das NuGet-Paket auf AppVeyor gebaut. Und ich plante schon lange, diese Aufgabe auf Github Actions zu verlagern. Also habe ich beschlossen, dass jetzt endlich die Zeit ist, das zu tun. Ein Grund dafür ist ein bevorstehender Feiertag in Deutschland, der mir die zusätzliche Zeit verschafft hat, mich um diese Aufgabe zu kümmern.

Während Github-Aktionen für einfache Projekte ganz nett sind, und obwohl sie ziemlich leistungsfähig sind, stoße ich sofort auf ein Problem: Mein NuGet-Paket enthält auch Build-Flavors von älteren Visual C++-Tools, derzeit bis hinunter zu v120. Und auf der Runner-VM der GitHub-Aktionen sind nur das neueste Visual C++ und die neuesten Toolsets installiert.

Und so begann für mich eine lange Reihe von Versuchen und Fehlern. Eine Menge Schmerzen, Kopfschmerzen und „warum, warum, warum…“-Momente. Am Ende habe ich die folgenden Lösungen gefunden:

HowTo: Anpassen der Visual Studio 2022-Installation auf Github Actions Runner

Fangen wir einfach an. Der Github-Runner wird mit Visual Studio Enterprise 2022 installiert. Daher sollte die neueste Toolchain sofort funktionieren, nämlich Visual C++ v143, v142 und v141, und das hat sie auch. Nun zu der Toolchain v140, die über den Visual Studio Installer installiert werden kann. Das sollte also einfach sein. Nun, theoretisch ja. Der Visual Studio Installer bietet Befehlszeilenargumente zum Ändern einer Installation und zum Hinzufügen von Komponenten, und das ist es, was ich tun muss. Das einzige Problem ist, dass der Installer keine Konsolenanwendung ist. Wenn er gestartet wird, kehrt die aufrufende Konsole sofort zurück, so dass ein Job im Workflow Yaml nicht warten kann, zumindest nicht automatisch. Ich muss den Installer mit `Start-Process` aufrufen und dem Befehl explizit sagen, dass er auf das Ende des erzeugten Prozesses warten soll.

Wenn Sie den Installer lokal in einer Eingabeaufforderung, z. B. einer Powershell, ausführen, werden Sie Ausgabemeldungen sehen. Wenn Sie ihn auf Github CI ausführen, ist das nicht der Fall. Wie ich schon sagte, ist der Installer keine Konsolenanwendung. Als solche führt er wahrscheinlich eine manuelle Konsolen-Host-Verbindung durch, um seine Ausgabemeldungen einzuschieben. Und auf Github CI existiert der Konsolen-Host wahrscheinlich nicht, da die Prozessausgabe vom CI-Agentenprozess in eine temporäre Datei geleitet wird. Infolgedessen findet der Installer keinen Konsolenhost und gibt daher auch keine Ausgabemeldungen aus. Ich befinde mich im Blindflug. Um zu wissen, ob der Befehl erfolgreich war oder nicht, verwende ich „vs_installer.exe export“, um die Liste der installierten Komponenten auszugeben. Das ist nicht schön, aber gut genug für die manuelle Fehlersuche.

So, das hat funktioniert:

- name: Modify Visual Studio 2022
  if: matrix.toolConfig.vs2022addMod != ''
  shell: pwsh
  run: |
    $component = "${{matrix.toolConfig.vs2022addMod}}"
    Write-Host "Adding:" $component

    Start-Process -FilePath "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" -ArgumentList "modify","--add",$component,"--installPath","`"C:\Program Files\Microsoft Visual Studio\2022\Enterprise`"","--passive","--includeRecommended","--norestart","--noUpdateInstaller" -Wait

    Start-Process -FilePath "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" -ArgumentList "export","--config","info-post.txt","--installPath","`"C:\Program Files\Microsoft Visual Studio\2022\Enterprise`"","--passive","--noUpdateInstaller" -Wait
    Write-Host "VS2022 Components after modification:"
    Write-Host (gc info-post.txt)

    Write-Host "Added:"
    Write-Host (gc info-post.txt | Select-String $component)

HowTo: Visual Studio 2013 auf Github Actions Runner

Dies lässt mit dem Build mit der ältesten noch unterstützten Toolkette: v120 aka Visual Studio 2013, und das ist ein echter Schmerz! Ich kann es den meisten Leuten nicht verübeln, da dies eine über 10 Jahre alte Software ist. Ich würde für so etwas keinen Support geben wollen. Aber mit diesem NuGet-Paket tue ich es irgendwie doch.

Das aktuelle Visual Studio unterstützt diese Toolkette nicht. Ich brauche also eigentlich Visual Studio 2013. Fragen Sie das Internet, was zu tun ist, und es wird Ihnen sagen, Visual Studio 2013 zu installieren, z. B. die kostenlose „Expression“ Edition, über Chocolatey. Ich habe es versucht, und es schlug mit der kryptischsten Fehlermeldung aller Zeiten fehl:

„Exit code indicates the following: Generischer MSI-Fehler. Dies ist ein lokaler Umgebungsfehler, kein Problem mit einem Paket oder dem MSI selbst […]“ bla bla bla.

Es gibt eine Menge falscher Hinweise, was zu tun ist. Der eigentliche Grund ist ein ganz anderer: Das Paket lädt eigentlich nur den Bootstrap-Installer von Visual Studio herunter, etwa 1,2 MB. Der Rest des Pakets wird bei der Installation auf Anforderung heruntergeladen. Und genau da liegt das Problem. Microsoft hat diese alten Download-Quellen entfernt, da sie anfällig waren, weil sie mit SHA-1-Hashes signiert waren. Und damit sind jetzt alle Chocolatey-Pakete kaputt. … Ich könnte mich irren, aber die Auswirkungen und die spärlichen Informationen, die ich aus den Logdateien herausgeschnitten habe, sehen wirklich so aus.

Das heißt, ich brauche ein vollständiges Visual Studio 2013. Zu diesem Zeitpunkt ist es offiziell über Microsofts Download-Website my.visualstudio.com verfügbar. Nachdem ich mich angemeldet und durch eine dynamische Website geklickt habe, versteht sich. Für meine Automatisierungszwecke nicht akzeptabel. Also habe ich die DVD-ISO auf meinem OneDrive neu gehostet. Ich würde sagen, das ist ok, aber nicht ideal. Und jetzt muss ich auch noch das komplette Visual Studio 2013 installieren. Klingt teuer. Klingt mühsam. Klingt langsam. Klingt wie ein Job für Docker. … Nun, ja, aber leider würde ich ein Windows-Docker-Image benötigen, das einen Windows-Docker-Host benötigt, und das scheint auf Github noch nicht unterstützt zu werden. Also, ja, ich muss Visual Studio 2013 auf dem Runner installieren.

- name: Install VS 2013 tools
  if: matrix.toolConfig.toolset == 'v120'
  shell: pwsh
  working-directory: ${{env.GITHUB_WORKSPACE}}
  run: |
    Write-Host "Downloading VS 2013 Express for Windows Desktop (w Update 5) DVD ISO..."
    Invoke-WebRequest -Uri "${{ secrets.VS2013ISO_URL }}" -OutFile dvd.iso
    gci dvd.iso
    $dvdiso = (Resolve-Path .\dvd.iso).Path

    Write-Host "Mounting Disk..."
    $DiskImage = Mount-DiskImage -ImagePath $dvdiso -StorageType ISO -PassThru

    $volumeInfo = (Get-Volume -DiskImage $DiskImage)
    $volumeInfo

    cd ($volumeInfo.DriveLetter + ":\")
    gci

    Write-Host "Installing Visual Studio 2013 Express..."
    Start-Process -FilePath ($volumeInfo.DriveLetter + ":\wdexpress_full.exe") -ArgumentList "/Q","/NoRestart","/NoRefresh","/NoWeb","/Full" -Wait

    Write-Host "Unmounting Disk..."
    Dismount-DiskImage -DevicePath $DiskImage.DevicePath

Und das funktioniert. Und ist, wie erwartet, schmerzhaft langsam. Um den Overhead dieses Installationsschritts zu begrenzen, ist es sinnvoll, die Breite der Job-Matrix im Workflow zu verringern: nur einen Job für die Installation und danach alle Build-Schritte nacheinander ausführen. Im Endeffekt ist dies fast um den Faktor 4 schneller, als man aufgrund des massiven Installations-Overheads erwarten würde. Zum Glück für mich ist dieser Workflow kein Pull-Request-Blocker während der aktiven Entwicklung, sondern nur eine Release-Automatisierung.

Gedanken zum Abschluss

Letztendlich funktioniert die Migration zu Github-Aktionen. War es das wert? Ich meine, Lua wird etwa alle zwei Jahre veröffentlicht. Brauche ich dafür überhaupt CI? Und überhaupt, ist das native NuGet nicht tot, ersetzt durch andere Mittel, wie vcpkg, oder so?

Nun, all dies ist wahr. Ich habe dieses Unterfangen nicht weiterverfolgt, weil ich ein CI für mein Lua-NuGet-Paket haben wollte. Mein Hauptgrund ist „weil ich es kann“, oder eigentlich „weil ich es noch nicht kann“. Es war eine gute Gelegenheit, mein Github-Aktions-Fu zu verbessern. Meine Empfehlung an Sie: Wenn Sie eine solche Gelegenheit sehen, um zu lernen und Ihre Fähigkeiten zu verbessern, mit dem Vorteil, etwas Brauchbares daraus zu machen, tun Sie es.

Und, jetzt warte ich auf Lua 5.4.6 und vielleicht neue Überraschungen…

Dieser Artikel is nur auf Englisch verfügbar.

Git has this cursed function to fuck up your files by doing unspeakable things to your line endings.

For example, from Githubs Documentation on Line Endings:

On Windows, you simply pass true to the configuration. For example:

$ git config –global core.autocrlf true

Please, never never never never never never never never never never never never do this!

THERE IS NO REASON TO DO IT!

Git is here to keep track of our files, NOT TO CHANGE OUR FILES IN ANY WAY.

So, please, just, never never never never never never never never never never never never do this! Leave my file endings alone!

Vielleicht habt Ihr bemerkt, dass die Shields.io-Badges für die Nuget-Pakete, die ich betreue, seit einigen Tagen verschwunden sind und jetzt durch eine einfache Tabelle ersetzt wurden. Was ist passiert?

Nun eine Entscheidung eines deutschen Gerichts is passiert, dass die Verwendung von Google Fonts von deren CDN-Server, der in den USA gehostet wird, eine Verletzung der Privatsphäre darstellen kann, wenn sie ohne die Zustimmung der Nutzer verwendet wird. Scheinbar sind auch schon einige räuberische Anwälte bereits auf der Jagd. Daher habe ich alle meine Websites so umgestellt, dass die von mir verwendeten Schriftarten auf denselben Servern gehostet werden. Auch wenn ich mich über den zusätzlichen Aufwand geärgert habe, verstehe ich die Wichtigkeit des Datenschutzes und kann die Entscheidung in diesem Sinne nachvollziehen. Soviel zu den Google Fonts. Was ist mit dem Rest?

Ich wollte meine Website so zu ändern, dass entweder alles selbst gehostet wird oder dass ich für alle eingebetteten Inhalte explizit Inhalte anfordere. Aus diesem Grund wird Shields.io nicht mehr direkt auf meiner Website verwendet. Das mag übertrieben wirken, aber ich denke es hilft auch für die „Stabilität“ des Inhalts. Jetzt holt sich mein Backend alle Daten, die ich brauche, speichert sie auf meinem eigenen Server und liefert sie als lokalen Teil meiner Website aus. In diesem Fall habe ich das Abrufen der Daten sogar auf einen Cron-Job umgestellt, der einmal pro Tag läuft. Ich bin sowieso nicht so schnell mit Nuget-Paketen.

Damit werden nun alle Inhalte, die auf sgrottel.de angezeigt werden, von den Servern ausgeliefert, auf denen sgrottel.de gehostet wird.

Der Nachteil ist natürlich, dass dies einen zusätzlichen Wartungsaufwand für mich bedeutet. Das Backend ruft halbdokumentierte APIs auf, die sich jederzeit ändern können, und es führt einige fragile Parsing-Vorgänge durch, z.B. im Falle der nicht so gut strukturierten Lua-Projekt-Website. Die derzeitige Lösung kann keine endgültige Lösung sein, und wird in Zukunft verbessert werden müssen. Wir werden sehen.

Okey, eine Warnung vorweg: Dies ist ein Beitrag geschrieben mit dickem Hals, denn ich bin wirklich verärgert und enttäuscht über meine jüngste Erfahrung mit dem Kundendienst von Lenovo. Und, ich hatte wirklich keinen hohen Erwartungen. Wirklich nicht.

Vor über einem Jahr habe ich einen ThinkPad-Laptop mit passender Dockingstation gekauft. Und beides hat nie perfekt funktioniert. Manchmal verlor die Dockingstation das Signal zum angeschlossenen Monitor. Manchmal schaltete sie sich beim Hochfahren nicht ein usw. All diese Probleme konnten entweder durch Abziehen und erneutes Einstecken oder, in schlimmeren Fällen, durch Aus- und wieder Einschalten behoben werden.

Kürzlich lernte die Dockingstation einen neuen Trick: Ihr Ethernet-Anschluss begann auszufallen. Erst manchmal, dann immer. Das vermutlich Gute daran ist, dass der Ausfall im Windows-Gerätemanager dadurch angezeigt wird, dass ein USB-Gerät einen Startfehler meldet, und dass es immer, zu 100%, auftritt. Das sollte doch ein Kundendienst nachvollziehen und beheben können, oder? Im schlimmsten Fall, selbst wenn sie das Problem nicht reproduzieren können, könnten sie die Fehlerbeschreibung lesen und einfach die Ethernet-Komponente austauschen, richtig? Versuch macht kluch.

Der erste Kontakt vor einigen Wochen verlief wie erwartet: Ich wurde gebeten, Kabel auszutauschen, Software sauber neu zu installieren usw. Alles verständlich. Ein von Lenovo geliefertes Kabel könnte inkompatibel sein, es ist besser, auf etwas von Amazon zu wechseln. Und nachdem eine saubere Neuinstallation von Windows 10 auf einer formatierten Festplatte genau denselben USB-Gerätefehler im Gerätemanager meldet wie zuvor, könnte man anfangen zu glauben, dass es sich vielleicht wirklich um ein Hardwareproblem handeln könnte.

Zu diesem Zeitpunkt stimmte der Kundendienst also zu, dass ich das Gerät an ein Servicecenter einschicken kann. Zu meiner großen Überraschung sollte ich den Laptop einzuschicken. Nur den Laptop. Nicht die Dockingstation. Seltsam, aber ok. Ich war ohnehin auf eine „lange Reise“ vorbereitet. Also schicke ich den Laptop ein, zusammen mit einer detaillierten Beschreibung, was los ist und wie man den Fehler reproduzieren kann. Das ist die Fehlerbeschreibung Nummer eins. Das ist wichtig für das Ende der Geschichte.

Nach etwa einer Woche kommt der Laptop zu mir zurück, mit einem Reparaturbericht im Paket. Ich verstehe wirklich nicht, warum Lenovo eine Kundendienst-Website hat, auf der sie ihre Service Tickets anzeigen. Auf dieser Website finden sich außer den Sendungsverfolgungsnummern der Postdienste null Informationen. Nutzlos. Wie auch immer. Im Reparaturbericht stand, dass sie die Hauptplatine und den Ethernet-Anschluss des Laptops ersetzt haben. Komisch. Ich habe eindeutig angegeben, dass der Ethernet-Anschluss meiner Dockingstation nicht funktioniert. Nun, was soll’s. Interessanterweise ist das gelegentliche Problem, dass der Monitor nicht erkannt wird, seither verschwunden. Ich denke also, dass wirklich irgendetwas mit dem Mainboard nicht in Ordnung war. Nun gut.

Aber das Problem mit dem Ethernet-Anschluss meiner Dockingstation ist immer noch nicht gelöst. Er bleibt defekt in 100% aller Fälle. Also erstelle ich eine Lenovo-Kundendienst-Eskalation für das ungelöste Problem. Runde zwei begann damit, dass ich eine detaillierte Fehlerbeschreibung des Problems und der Schritte zur Reproduktion lieferte (im Grunde: Laptop anschließen, hochfahren, Fehler sehen! Minimales Setup mit Laptop + Dock + 3 Kabel: Laptop-Dock-Verbindung, Stromversorgung, Ethernet). Nach einigen weiteren „Experimenten“ mit der Software durfte ich schließlich mein Gerät endlich wieder zum Service-Center schicken. Zu meiner (immer noch recht großen) Überraschung sollte ich sowohl den Laptop als auch die Dockingstation einzuschicken, da es sich um ein Problem mit der Kombination beider Geräte handeln könnte. Seltsam, aber egal, ok. Also schicke ich beides ein.

Dann, nach einer halben Woche, wechselt die nutzlose Status-Website auf „On Hold“. Zu diesem Zeitpunkt war ich mir ziemlich sicher, dass das nicht gut ausgehen würde. Dann, fast eine Woche nachdem ich die Geräte eingeschickt habe, erhalte ich eine E-Mail vom Kundendienst, in der dieser mir mitteilt, dass er mein Problem nicht reproduzieren kann. Ach! Ich kann mir nur vorstellen, dass sie den Laptop nie eingeschaltet haben, sondern nur auf der Suche nach Kratzern am Gehäuse waren. Viel wichtiger ist jedoch, dass sie mich bitten, eine detaillierte Fehlerbeschreibung abzugeben! Ansonsten würden sie mein Gerät zurückschicken. Ich meine, ganz ehrlich, ich habe bereits detaillierte Fehlerbeschreibungen und Schritt-für-Schritt-Beschreibungen zur Reproduktion des Fehlers geliefert. Zwei Mal. Aber ok!

Noch am selben Tag schreibe ich eine Antwort auf diese E-Mail, wieder mit einer detaillierten Fehlerbeschreibung und einer Schritt-für-Schritt-Beschreibung des minimalen Setups, um den Fehler zu reproduzieren, zur Erinnerung: die zwei Geräte und drei Kabel und eine neue, saubere Windows 10-Installation mit nur allen installierten Updates. Einfach genug. Es ist erwähnenswert, dass ich diese drei verschiedenen Fehlerbeschreibungen alle jeweils neu geschrieben habe. Es war nicht ein Text, dreimal kopiert. Es waren drei Texte, alle immer im Kontext der Fragen des Kundendienstes, alle ausführlich, alle klar, alle höflich. … Drei Mal!

Da mir der Kundendienst eine Frist von zwei Tagen für die Informationen gesetzt hatte, nahm ich direkt am Tag danach über den Web-Live-Chat Kontakt mit dem Service auf. Dort bestätigte eine freundliche Kundendienstmitarbeiterin oder ein wirklich gut geschriebener Bot, dass meine E-Mail eingegangen sei und an den Kundendienstmitarbeiter weitergeleitet worden war. Nun gut.

Dann, fast eine zweite Woche später, wurden meine Geräte an mich zurückgeschickt, Laptop und Dockingstation. Mit erneut überraschendem Reparaturbericht im Paket:

Darin stand ausdrücklich, dass sie nichts „repariert“ haben, weil sie nie die erforderlichen Informationen von mir erhalten haben.

Drei Mal!

Übrigens ist der Ethernet-Anschluss meiner Dockingstation immer noch defekt. 100% der Zeit. 100% reproduzierbar. Immer. Mit der Meldung eines defekten USB-Geräts im Windows-Geräte-Manager. In 100% der Fälle. Immer.

Drei Mal!