Repository navigation
Release-Kette: Packaging-Skript und Workflow - #4
Merged
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.pybautlinkedin-optimizer.skillaus einer Positivliste: SKILL.md,references/, die beiden Laufzeit-Skripte, LICENSE, requirements.txt. Nicht drin:.git,.github, index.html, die Caches und die beiden Repo-Werkzeugecheck_versions.pyundbuild_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-namegibt den dokumentierten Dateinamen aus, damit Workflows und Anleitung ihn nicht getrennt pflegen.Release-Workflow.
.github/workflows/release.ymlreagiert aufpusheines Tagsv*, prueft den Tagnamen gegen die Versionsangabe im Repo, ruft das Skript auf und haengt das Ergebnis mitsoftprops/action-gh-release@v2an 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, undcheck_versions.pyprueft 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.pyhat 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,.gitmit 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.txthaeltPillow>=10.1fest, mit der Begruendung: erst ab 10.1 nimmtImageFont.load_default()einensize-Parameter, sonst ist die Safe-Zone-Messung nicht belastbar und--strictbricht 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
diffgegen 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 Platzhalterlinkedin.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
mainabwarten.git tag v2.3.0 <merge-commit>undgit push origin v2.3.0.release.ymllegt das Release an und haengt die Datei daran. Der Release-Text bleibt leer, weil der Workflow keinenbodysetzt: die vorbereiteten Release Notes dort einfuegen.curl -LOauf 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 aufmainum, 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.