Skip to content

Release-Kette: Packaging-Skript und Workflow - #4

Merged
GodModeAI2025 merged 8 commits into
mainfrom
release/welle-4
Sep 4, 2026
Merged

GodModeAI2025 merged 8 commits into
mainfrom
release/welle-4

Conversation

@GodModeAI2025

Copy link
Copy Markdown
Owner

Release-Kette fuer das erste Release

Dieser Zweig macht aus dem Repo etwas, das man taggen kann. Fuenf Commits, aufeinander aufbauend.

Packaging-Skript. scripts/build_skill_package.py baut linkedin-optimizer.skill aus einer Positivliste: SKILL.md, references/, die beiden Laufzeit-Skripte, LICENSE, requirements.txt. Nicht drin: .git, .github, index.html, die Caches und die beiden Repo-Werkzeuge check_versions.py und build_skill_package.py, die ausserhalb des Repos ins Leere zeigen wuerden. Das Skript nimmt den Ausgabepfad als Argument und laeuft ohne Netz und ohne GitHub. Feste Zeitstempel, feste Rechte, sortierte Reihenfolge und ZIP_STORED statt Deflate machen das Ergebnis reproduzierbar. --print-name gibt den dokumentierten Dateinamen aus, damit Workflows und Anleitung ihn nicht getrennt pflegen.

Release-Workflow. .github/workflows/release.yml reagiert auf push eines Tags v*, prueft den Tagnamen gegen die Versionsangabe im Repo, ruft das Skript auf und haengt das Ergebnis mit softprops/action-gh-release@v2 an das Release. permissions: contents: write, fail_on_unmatched_files: true. Packaging-Logik steht keine darin, sonst liesse sie sich vor dem Tag nicht pruefen.

Versionsquelle. Die Nummer stand an sechs Stellen gleichberechtigt nebeneinander. Jetzt steht sie in VERSION, und check_versions.py prueft die sechs Kopien dagegen statt nur untereinander. Neu ist --expect, damit der Release-Workflow einen Tag ablehnen kann, der nicht zum Repo passt.

v2.3.0, nicht v2.2.2. Der Eintrag v2.2.2 vom 09.03. beschreibt nicht mehr den Stand: create_banner.py hat seitdem ein optionales --background, wendet die Schriftgroesse auf den Ersatz-Font an und meldet Safe-Zone-Verletzungen ueber den Exitcode. Dazu kommen requirements.txt, das Packaging und die CI. Ein erstes Release unter der alten Nummer wuerde ueber seinen eigenen Inhalt falsch Auskunft geben. Neue Funktion ohne Bruch der Aufrufe, also die zweite Stelle.

Installationsweg. Die Landingpage empfahl zip -r ../linkedin-optimizer.skill . im Klon. Das packt das gesamte Arbeitsverzeichnis, .git mit der kompletten Historie eingeschlossen, dazu index.html und die Workflows. Die zweite Karte, cp -r . in den Skills-Ordner, hatte denselben Fehler. Beide zeigen jetzt auf das Release-Artefakt. Der Dateiname bleibt derselbe, nur der Inhalt darunter stimmt. Die README bekommt denselben Abschnitt, dazu den Weg ueber das Skript.

Abhaengigkeit dokumentiert. requirements.txt haelt Pillow>=10.1 fest, mit der Begruendung: erst ab 10.1 nimmt ImageFont.load_default() einen size-Parameter, sonst ist die Safe-Zone-Messung nicht belastbar und --strict bricht auch bei sauberem Text ab. Die CI installiert jetzt diese Datei statt einer Zeile im Workflow.

Pruefschritt in der CI. Bei jedem Lauf: Paket zweimal bauen und die Bytes vergleichen, vorhanden, nicht leer, lesbares ZIP, Eintragsliste per diff gegen die erwartete, dazu ein ausdrueckliches Verbot von .git, .github, index.html, course.html, Caches und Schluesseldateien. Und: README und Landingpage muessen genau die URL nennen, die zum Dateinamen aus dem Skript passt. Damit faellt eine Anleitung ins Leere schon im PR auf, nicht erst nach dem Tag.

Was lokal gelaufen ist

Alle CI-Schritte woertlich nachgefahren, Gesamt-Exitcode 0. Das Paket enthaelt acht Dateien, 121155 Bytes, SHA256 b94b50c680785bd00ec99dcc2f0ca7302090b19c7c9281ea769db012c9f5bac9. Zwei Gegenproben in einer Repo-Kopie: index.html in die Positivliste eingetragen, der Schritt faellt mit > index.html; Artefaktnamen geaendert, der Schritt faellt mit der Meldung, dass README.md die URL nicht nennt. Im entpackten Archiv findet die Personendaten-Suche nur die Urheberrechtszeile der MIT-Lizenz und den Platzhalter linkedin.com/in/beispiel.

Was der PR-Lauf noch zeigen muss

Die Reproduzierbarkeit ist bisher nur auf macOS mit Python 3.9.6 beobachtet. Der SHA256 im CI-Log dieses PR (ubuntu, Python 3.11) muss der oben genannte sein. Weicht er ab, stimmt die Aussage in README und Landingpage nicht und gehoert vor dem Tag korrigiert.

Danach, in dieser Reihenfolge

  1. Mergen, CI auf main abwarten.
  2. git tag v2.3.0 <merge-commit> und git push origin v2.3.0.
  3. release.yml legt das Release an und haengt die Datei daran. Der Release-Text bleibt leer, weil der Workflow keinen body setzt: die vorbereiteten Release Notes dort einfuegen.
  4. Einmal curl -LO auf die dokumentierte URL, um zu sehen, dass sie liefert. Bis zum Tag antwortet sie mit 404, auch wenn die Landingpage nach dem Merge schon darauf zeigt.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BL7UoPomBp2Luhg89R6fYk


Gestapelt. Dieser PR sitzt auf ci/welle-3. GitHub haengt ihn automatisch auf main um, sobald der darunterliegende PR gemergt ist. Vorher zeigt der Diff nur die Welle-3-Aenderungen, das ist so gewollt.

Teil von Welle 4 des Haerteplans: Release und Packaging. Jede Aenderung wurde von einem zweiten Durchgang abgenommen, der das Artefakt selbst gebaut, entpackt und den Installationsweg durchgegangen ist.

GodModeAI2025 and others added 8 commits September 4, 2026 16:44
scripts/build_skill_package.py baut linkedin-optimizer.skill aus einer
Positivliste: SKILL.md, references/, die beiden Laufzeit-Skripte, LICENSE
und requirements.txt. Alles andere im Repo bleibt draussen, also .git,
.github, index.html, die Caches und die Werkzeuge check_versions.py und
build_skill_package.py selbst, die ausserhalb des Repos keinen Sinn haben.

Das Skript laeuft ohne Netz und ohne GitHub und nimmt den Ausgabepfad als
Argument. Feste Zeitstempel, feste Rechte, feste Reihenfolge und ZIP_STORED
statt Deflate machen das Ergebnis reproduzierbar, unabhaengig von zlib und
Betriebssystem. --print-name gibt den dokumentierten Dateinamen aus, damit
Workflows und Anleitung ihn nicht doppelt pflegen muessen.

requirements.txt haelt die Untergrenze Pillow>=10.1 fest, die in den
vorangegangenen Reparaturen an create_banner.py festgestellt wurde, samt
Begruendung.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BL7UoPomBp2Luhg89R6fYk
Der Workflow reagiert auf push eines Tags v*, prueft den Tagnamen gegen die
Versionsangabe im Repo, ruft scripts/build_skill_package.py auf und haengt
das Ergebnis mit softprops/action-gh-release@v2 an das Release.
fail_on_unmatched_files sorgt dafuer, dass ein leerer Upload auffaellt statt
ein Release ohne Artefakt zu erzeugen.

Die Packaging-Logik steht bewusst nicht hier, sondern im Skript. Nur so
laesst sich vor dem Tag pruefen, was beim Tag passiert.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BL7UoPomBp2Luhg89R6fYk
Die Nummer stand bisher an sechs Stellen gleichberechtigt nebeneinander.
Jetzt steht sie in VERSION, und check_versions.py prueft die sechs Kopien
gegen diese Datei statt nur untereinander. Mit --expect vergleicht das
Skript zusaetzlich VERSION gegen einen erwarteten Wert; der Release-Workflow
uebergibt dort den Tagnamen.

2.3.0 statt 2.2.2, weil der Stand nicht mehr der ist, den der Eintrag
v2.2.2 vom 09.03. beschreibt: create_banner.py hat seitdem ein optionales
--background, wendet die Schriftgroesse auf den Ersatz-Font an und meldet
Safe-Zone-Verletzungen ueber den Exitcode. Dazu kommen requirements.txt,
das Packaging und die CI. Neue Funktion ohne Bruch der Aufrufe, also die
zweite Stelle.

Eine eigene CHANGELOG.md kommt nicht dazu. Der Changelog steht in SKILL.md,
wird dort von der CI geprueft und liegt im ausgelieferten Paket. Eine zweite
Datei waere eine zweite Pflegestelle.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BL7UoPomBp2Luhg89R6fYk
Die Landingpage empfahl bisher "zip -r ../linkedin-optimizer.skill ." im
Klon. Das packt das ganze Arbeitsverzeichnis, also .git mit der kompletten
Historie, index.html und die Workflows. Der zweite Weg, "cp -r ." in den
Skills-Ordner, hat denselben Fehler. Beide zeigen jetzt auf das Artefakt aus
dem letzten Release: curl auf releases/latest/download/linkedin-optimizer.skill,
danach in Claude ziehen oder mit unzip in den Skills-Ordner auspacken. Der
Dateiname ist derselbe wie bisher, die alten Anleitungen erzeugten nur einen
anderen Inhalt darunter.

Die README bekommt denselben Abschnitt, dazu den Weg ueber das Skript fuer
alle, die lieber selbst bauen. Ordnerstruktur, Grenzen und Roadmap ziehen
nach: requirements.txt existiert jetzt, nennt fuer Pillow aber weiterhin nur
eine Untergrenze, und fuer das npm-Paket docx fehlt die package.json nach wie
vor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BL7UoPomBp2Luhg89R6fYk
Die CI ruft jetzt bei jedem Lauf dasselbe Packaging-Skript auf wie der
Release-Workflow und prueft danach das Ergebnis: zwei Laeufe liefern
identische Bytes, das Archiv ist vorhanden, nicht leer und lesbar, und seine
Eintragsliste stimmt genau mit der erwarteten ueberein. Der Vergleich faellt
in beide Richtungen auf, fehlende Datei wie ungewollte Zugabe. Ein zweiter
Schritt verbietet .git, .github, index.html, course.html, Caches und
Schluesseldateien noch einmal ausdruecklich.

Ausserdem muessen README und Landingpage genau die Download-URL nennen, die
zum Dateinamen aus dem Skript passt. Damit faellt eine Anleitung, die nach
dem Tag ins Leere zeigt, schon im Pull Request auf.

Die Pillow-Untergrenze steht nicht mehr im Workflow, sondern in
requirements.txt. Die CI installiert dieselbe Datei, die auch im Paket
liegt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BL7UoPomBp2Luhg89R6fYk
Phase 5 rief create_banner.py auf, ohne zu sagen, woher Pillow kommt. Im
Paket liegt requirements.txt zwar bei, aber der Weg dorthin stand nur in
der README, und die ist nicht im Paket. Wer nur das Artefakt hatte, lief
in ModuleNotFoundError: No module named 'PIL'.

Phase 5 und der Abschnitt "Banner-Erstellung scheitert" nennen jetzt
pip install -r requirements.txt und sagen dazu, wo die Datei im
installierten Skill liegt, naemlich neben SKILL.md.

Das Artefakt aendert sich dadurch: SHA256 jetzt
c217b34d26a5f2f3178da0ef8919d7ac90374092fed06251fcfc9e0df9a0cc62
statt b94b50c680785bd00ec99dcc2f0ca7302090b19c7c9281ea769db012c9f5bac9.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BL7UoPomBp2Luhg89R6fYk
Der Hinweis auf pip install -r requirements.txt nuetzt nur, solange er im
Artefakt steht. Der Schritt "Skill-Paket bauen und pruefen" liest die
Zeile jetzt mit unzip -p aus dem gebauten Paket und bricht ab, wenn sie
fehlt.

Geht ueber die Empfehlung des Pruefers hinaus und steht deshalb allein,
damit er sich ohne die Dokumentationsaenderung entfernen laesst.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BL7UoPomBp2Luhg89R6fYk
@GodModeAI2025
GodModeAI2025 changed the base branch from ci/welle-3 to main September 4, 2026 19:08
@GodModeAI2025 GodModeAI2025 reopened this Sep 4, 2026
@GodModeAI2025
GodModeAI2025 merged commit 4dd9103 into main Sep 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant