Schnelle und einfache CI/CD-Pipelines mit semantischer Versionierung für jede Sprache oder jedes Tool. Die Veröffentlichung einer neuen Version eines Tools sollte langweilig sein. Keine Zeremonie, keine Planung von Besprechungen, nicht einmal eine Diskussion. Es sollte transparent, mühelos, zuverlässig und sogar informativ sein - mehr darüber später. Als Software-Berater, der Teams hilft, DevOps-Lösungen zu implementieren, finde ich jedoch oft, dass dies nicht der Fall ist.Was ich finde, variiert in der Qualität wild, also statt Ihnen zu sagen, was mir nicht gefällt, konzentrieren wir uns darauf, wie ich meine Pipelines strukturieren möchte, um neue Repositorys schnell und einfach an Bord zu bringen. Um meine Perspektive zu verstehen, möchte ich mit Ihnen teilen, wie sich meine Ansichten zu diesem Thema im Laufe der Jahre entwickelt haben.Jetzt verwende ich einen Prozess, der das Anordnen von „LEGO Blöcken“ von modularen Workflows mit geringfügigen Anpassungen, wie Parameteränderungen, beinhaltet.Idealerweise ziele ich auf Standardeinstellungen, die es mir ermöglichen, die gleichen Bausteine von einem Projekt in ein anderes zu kopieren und einzufügen, wenn sie denselben Typ teilen. Zum Beispiel ist der Build-Prozess für Rust-Bibliothek X wahrscheinlich ungefähr das gleiche wie Rust-Bibliothek Y, und Node-Server foo ist wahrscheinlich ungefähr das gleiche wie Node-Serverleiste. Im Laufe der Jahre habe ich versucht, Open-Source-Komponenten zusammenzustellen, um dies zu erreichen, aber ich habe nie die richtige Kombination gefunden. Aber zuerst... Ich bin mir bewusst, dass Versionierung und Veröffentlichung nicht die aufregendsten Themen sind; es ist jedoch ein Problem, mit dem jedes Projekt konfrontiert ist, selbst wenn es vibe-codiert ist (wahrscheinlich besonders!). Wenn Sie es richtig machen, wird Ihr Projekt viel professioneller aussehen und Änderungen an seine Benutzer kommunizieren. Dies schafft mehr Vertrauen in Ihre Projekte, indem es den Entwicklern hilft, neue Änderungen auf klare und konsistente Weise zu verstehen und anzunehmen. Zu Beginn... Sie waren das Nebenprodukt von Meilensteinen, erreicht durch eine Reihe von Sprints, geplant, um das Beste von jedermanns Fähigkeiten, in einer Reihe von Planungssitzungen, in denen der Rückstand durchgeworfen wurde, und Aufgaben, die würdig waren, wurden ausgewählt. Wir würden unser Bestes tun, um eine Spezifikation eines Plans zu schreiben und eine Fibonacci-Nummer oder T-Shirt-Größe zu schätzen, oder im schlimmsten Fall eine Anzahl von Tagen. Die Auslieferung war der Höhepunkt dieses Prozesses. Die Auslieferung von Auslieferungen, die an die echten Benutzer geliefert wurden. Als Höhepunkt dieses Prozesses und hohe Einsätze, um es richtig zu machen, war die Auslieferung ein emotionaler Moment. Und aufregend? Die Angst? Vielleicht haben einige, die Sie ausgelöst haben, Ihr Herz im Rennen, da sie die Maschinen in Bewegung setzen. Es gibt auch das Detail und das Drama, eine Versionszahl zu bestimmen. Ist das eine große Veröffentlichung? Eine völlig neue Version?? Manchmal diktierte Marketing die Version ... 2.0! Zu diesem Zeitpunkt in meiner Karriere war es weitgehend nicht meine Meinung, die sich auf dieses Thema der Versionsnummern bezog, und wenn man zurückblickt, sollte es wahrscheinlich niemandem gehören (Sie werden sehen, was ich später meine). Ich war nicht verantwortlich für die Veröffentlichungen am Anfang ... aber ... das würde nicht ewig dauern. In der Open Source An einem bestimmten Punkt in meiner Karriere wurde ich daran interessiert, zum Open Source beizutragen.Im Allgemeinen in Form von npm-Modulen, da ich damals sehr in Node war. Es war meine Reihe, für die Freigabe zuständig zu sein. Ich kann mich nicht erinnern, wie, vielleicht durch einen Newsletter oder vielleicht einen Teil des NYC NodeJS-Meetups, das Matt Walters und ich zusammen laufen ließen - ich traf die Bibliothek. Semantic Release implementierte ein Prinzip, mit dem ich als Webentwickler vibrierte, einer Separation von Bedenken, die auf Semantik basiert. semantic-release Bevor Sie losfahren und mit der Verwendung von Semantic-Release beginnen, gibt es einige Einschränkungen, mit denen ich konfrontiert bin ... Und ich komme in einem Moment zu denen. Erstens, auf einer hohen Ebene, war die grundlegende Idee, die semantic-release predigte, dass Sie einem bestimmten Format für Ihre Kommissionsnachrichten folgen würden, und basierend auf den Nachrichten könnte die Version berechnet werden. Es sprach von der Entfernung der Emotionen aus den Veröffentlichungen, indem sie sie robotisch machten, basierend auf dem, was sich tatsächlich verändert hat. Wenn es zum Beispiel eine neue Hauptversion – v2 zu v3 – gab, bedeutete das eine bahnbrechende Änderung. Um dies in Ihrer Commit-Nachricht zu bedeuten, sollten Sie im Körper des Komitees. BREAKING CHANGE: feat: revamp user auth flow BREAKING CHANGE: Per Chad's "game-changer" vision in the 3am Slack rant, we've ditched the old auth system for a blockchain-based solution because "passwords are so 2024." Update your clients or enjoy the 500 errors! Kleine Versionsstörungen, wie z. B. v2.0.0 bis v2.1.0, bedeuten, dass eine neue Funktion hinzugefügt wurde. feat: add dark mode toggle Per the 47-comment thread in the "urgent" ticket, users can now save their retinas. Dark mode added, but brace for the inevitable "make it darker" feedback. Patch-Versionen signalisierten Reparaturen oder Refaktoren oder im Grunde alles andere, was eine neue Veröffentlichung auslösen sollte. fix: revert "fix" by AI that skipped the breaking tests to avoid the failure Und schließlich sollten einige Verpflichtungen überhaupt keine Veröffentlichung auslösen. „Chores“, wie sie mir vorgestellt wurden. chore: update release pipeline version from v3.1.0 to v3.1.1 Dieses spezifische Format von Commit-Nachrichten war bekannt als , obwohl es andere gibt. Sie können ihre Seite für die vollständige Spezifikation überprüfen, aber ich wollte den Kern davon teilen. Konventionelle Komitees Darüber hinaus könnten diese Informationen, die in den Commits enthalten sind, auch als Änderungsprotokoll angezeigt werden – z. B. die Markierung einer brechenden Änderung. What's new in v2.0.0 * feat: remove deprecated API BREAKING CHANGE: the FooBar API that was deprecated. To upgrade, you can use the new BazBar API. Also, für eine Weile, semantische Release war großartig für mich. Für Node-Projekte, es ist immer noch... Auf DevOps Ich war immer an der Idee interessiert, wie man skalierbare verteilte Systeme baut, und so war es etwas, was ich seit einiger Zeit in meiner Karriere verfolgte. Dies waren keine npm-Module; es waren Anwendungen, Dienste, Datenbanken und Reihen! Ich mochte die Einfachheit der semantischen Veröffentlichung, aber es funktionierte nur gut für Node.js-Projekte. Datei zu nicht-Node-Projekten, aber das war am besten unordentlich und hacky. package.json Zu dieser Zeit wurde ich tief in DevOps involviert, während der Jenkins-Ära, als Docker anfing, Anziehungskraft zu gewinnen. Ich habe gelernt, Pipelines mit Jenkins zu schreiben und alles mit Docker Swarm zu implementieren! Meine frühe DevOps-Reise und die Entdeckung von Docker für die Bereitstellung. Mein jüngerer und immer noch relevanter und genauer Guide to Git with Trunk Based Development Artikel erklärt, warum und wie, wenn Sie interessiert sind. Mein jüngerer und immer noch relevanter und genauer Guide to Git with Trunk Based Development Artikel erklärt, warum und wie, wenn Sie interessiert sind. Ich wollte immer, dass diese Projekte, mit denen ich arbeitete, wie Semantic-Release-Projekte versioniert und veröffentlicht werden, aber ich fand nie eine Lösung, die auch funktionierte. Es war nicht das Wichtigste auf meiner Liste, also nannte ich es im Allgemeinen gut genug und lebte mit den Mängeln. Im Laufe der Zeit, als DevOps-Berater, habe ich verschiedene Projekte in mehreren Sprachen und Frameworks getroffen und veröffentlicht, und jede einzelne hat Versionierung, Veröffentlichungen und ChangeLogs benötigt. Ein weiterer Kopfschmerz, den ich oft traf, waren große, monolithische Rohrleitungen. Von der Jenkins-Ära aus bekomme ich es, so schrieb ich auch Rohrleitungen. Ich würde versuchen, den gesamten Freigabefluss in einer großen Reihe von Schritten zu haben, beginnend mit einem Schub zum Haupt. Wenn Sie zum Haupt drücken, würden verschiedene Qualitätskontrollen laufen und eine neue Version würde gebaut, veröffentlicht, gekennzeichnet und veröffentlicht. Dies ist an sich nicht schrecklich und auch wahrscheinlich "gut genug" in den meisten Fällen; als DevOps-Berater muss ich es jedoch immer wieder tun. Das Brechen der Dinge in kleinere, modulare Stücke ermöglicht es diesen Stücken, mehr Projekte zu dienen. , eine Idee, die aus der Annahme von UNIX-Philosophien stammt. Die Abdeckung von Ideen Zum Beispiel kann eine Node Quality Pipeline in jedem Node-Projekt gleich sein, vorausgesetzt, Sie befolgen die Standard-NPM-Skriptkonventionen, und so kann eine allgemeine Pipeline für das Ausführen von Linting, Building und Unit-Tests über die meisten, wenn nicht alle, Node.js-Projekte geteilt werden. und so weiter, und die Buchstabenabschnitte der Die Datei bestimmt, was passiert, wenn Der Befehl läuft. npm run lint --if-present package.json lint High-Level-Pipelines für Versionierung und Release Auf einer hohen Ebene wird jedes Projekt, das veröffentlicht werden muss, zunächst mit einer neuen Versionsnummer gekennzeichnet. Ich benutze GitHub-Aktionen am häufigsten, da ich denke, dass Pipelines Rohstoffe sind, und es ist einfach zu beginnen.Ich habe viele verwendet, aber sie sind alle im Wesentlichen dasselbe - führen Sie eine Reihe von Schritten mit einem freigegebenen Volumen durch. Die Versionierung selbst, wenn wir dem Standard der konventionellen Commits folgen, die an eine semantische Versionszunahme gebunden sind, ist keine sprachspezifische Sache. Lange Zeit habe ich Veröffentlichungen mit Versionen verknüpft, dachte ich, sie wären Teil derselben Sache, wenn sie in Wirklichkeit zwei verschiedene Einheiten sind, die miteinander verbunden sind. Wenn sie getrennt wurden, machte der versionierende Teil der Pipeline sein eigenes modulares Stück, das dann einen Aufbau dieser Version und eine anschließende Veröffentlichung auslöste. Lassen Sie mich es zusammenbrechen... Für jedes Projekt habe ich in GitHub Actions zwei Pipelines: On commit to the trunk branch, version, and tag When a commit occurs in the trunk branch (usually or ), trigger a pipeline that runs quality checks, and, if they pass, calculates a new version number. It then creates and pushes a tag with that new version number. We can also use this opportunity to update that version number in the code base if necessary, and generate a change log from the commit data that was used to calculate the new version number. main master When a tag is created, build new versions and release them. This step is simplified by the previous step of doing the version bump. Everything’s already been bumped to the new version. We can just run build and release using the tag as the base. Wie ich bereits erwähnt habe, habe ich nach vielen Versuchen, Open-Source-Komponenten vom GitHub Actions Marketplace zusammenzustellen, schließlich aufgegeben und mein eigenes Tool geschrieben, das Schritt eins bewältigt. Einführung vnext Nächster vnext ist ein schnelles Rust CLI-Tool, das herkömmliche Kommissionsnachrichten verwendet, um Ihre nächste semantische Version zu berechnen, um Major-, Minor- oder Patch-Bumps für vereinfachte Releases zu automatisieren. Hier ist, wie man es benutzt. NEXT_VERSION=v`vnext` vnext --changelog > CHANGELOG.md Ich denke, es ist ziemlich einfach! lassen Sie mich wissen, was Sie denken. Es basiert vollständig auf der Git-Geschichte des Projekts. Es spielt keine Rolle, welche Sprache oder Werkzeug Sie veröffentlichen; der Versionierungsprozess ist im Grunde derselbe.Holen Sie sich eine neue Version, aktualisieren Sie sie in einigen Dateien, erstellen Sie ein ChangeLog, Tag und Push.Der einzige Unterschied ist, welche Dateien aktualisiert werden müssen - dies wird in dem Workflow berücksichtigt, den ich in einem Moment teilen werde. ist schnell und einfach zu installieren über - der Nach der Konfiguration können Sie laufen: vnext ubi Der „Universal Binary Installer“ ubi --project unbounded-tech/vnext Ich habe auch einen geteilten GitHub-Aktionen-Workflow erstellt, den Sie anrufen können, der alle diese Details bearbeitet. Hier ist, wie Sie den gemeinsamen Workflow verwenden: name: On Push Main, Version and Tag on: push: branches: - main - master permissions: packages: write contents: write jobs: version-and-tag: uses: unbounded-tech/workflow-vnext-tag/.github/workflows/workflow.yaml@v1 with: useDeployKey: true changelog: true Die meisten Projekte müssen auch konfigurieren, wie und welche Dateien mit der neuen Versionsnummer aktualisiert werden sollen. zur Zeit, Unterstützt zwei generische Methoden ( und ) und einige sprachspezifische Optionen. vnext yqPatches regexPatches Die sprachspezifischen Optionen sind am einfachsten zu verwenden. Zwei benutzt Aktualisierung der Paketdateien des Projekts. with.node true npm Verwenden Sie das Tool um spezifische Felder in einer YAML-Datei zu patchen. Ich verwende dies häufig zum Aktualisieren von Versionsnummern in Helm-Charts: yqPatches yq version-and-tag: uses: unbounded-tech/workflow-vnext-tag/.github/workflows/workflow.yaml@v1.13.0 secrets: GH_PAT: ${{ secrets.YOUR_ORG_SECRET_PAT }} with: usePAT: true changelog: true yqPatches: | patches: - filePath: helm/values.yaml selector: .image.tag valuePrefix: "v" - filePath: helm/Chart.yaml selector: .version valuePrefix: "v" Ich habe auch diese Gelegenheit genutzt, um zu teilen, wie man einen Personal Access Token anstelle eines Deploy-Schlüssels verwendet. Ich habe auch diese Gelegenheit genutzt, um zu teilen, wie man einen Personal Access Token anstelle eines Deploy-Schlüssels verwendet. benutzt um eine Zeichenfolge mit der neuen Versionszahl zu finden und zu ersetzen. z. B.: regexPatches sed regexPatches: | patches: - filePath: package/composition.yaml regex: /ghcr.io/org-name/package-name:(.*)/g valuePrefix: ghcr.io/org-name/package-name:v - filePath: README.md regex: /Current version: v[0-9]+\.[0-9]+\.[0-9]+/g valuePrefix: Current version: v Sie können auch eine Kombination von Optionen verwenden. Eine Nuance über GitHub-Aktionen Wenn Sie eine Aktion auf GitHub Actions ausführen, erzeugt der Mitarbeiter standardmäßig einen temporären GitHub-Authentifizierungstoken. Dieser Token hat die Berechtigung, einige grundlegende Aufgaben auszuführen; es ist jedoch nie erlaubt, andere Pipelines auszulösen. Aber unser nächster Schritt nach der Kennzeichnung einer neuen Version war es, eine andere Pipeline mit diesem Tag auszulösen! Machen Sie sich keine Sorgen, das ist Design – einfach eine Maßnahme von GitHub, um zu verhindern, dass Sie unbeabsichtigt eine Reihe von Läufern drehen. Es gibt ein paar Möglichkeiten, bewusst darüber zu sein - ich habe bereits ein Beispiel von zwei gezeigt: Mit einem Deploy Key und dem entsprechenden GitHub Actions Secret Verwenden eines persönlichen Zugriffstokens als GitHub-Aktionsgeheimnis Erstellen einer GitHub-Anwendung (theoretisch – ich hatte keine Notwendigkeit für diese Option) Die Verwendung eines Personal Access Tokens ist bequem, wenn Sie ein bezahlter Kunde im GitHub-Ökosystem sind, da Organisationsgeheimnisse verfügbar sind. Auf der kostenlosen Ebene ist das keine Option, also zeige ich Ihnen, wie Sie stattdessen einen Bereitstellungsschlüssel einrichten können. Tatsächlich habe ich es sehr einfach gemacht, indem ich es in die CLI. Es ist eine großartige Option, da beim Konfigurieren auf diese Weise kein Mensch es kennen muss, und es kann leicht durch Wiederherstellen des gleichen Befehls gedreht werden. vnext Für jedes Repository, das Sie einrichten möchten um mit einem Bereitstellungsschlüssel zu veröffentlichen, im Verzeichnis des Projekts ... vnext Zuerst erhalten Sie ein auth-Token mit Mit Erlaubnis zum Verwalten von Schlüsseln: gh gh auth refresh -h github.com -s admin:public_key -s admin:ssh_signing_key export GITHUB_TOKEN=$(gh auth token) Und dann laufen: vnext generate-deploy-key Sie fragen sich vielleicht, kann dies nicht in eine Pipeline selbst gehen? Leider kann ich keinen Weg finden, diesen Schritt in Github-Aktionen zu automatisieren, ohne einen persönlichen Zugriffstoken zu erstellen, da der Standard-Token Geheimnisse nicht ändern kann. Dies besiegt die Pupose, einen Deploy-Schlüssel statt in der freien Ebene zu verwenden, da Sie ihn in jedem Repo erstellen müssen. Sie fragen sich vielleicht, kann dies nicht in eine Pipeline selbst gehen? Leider kann ich keinen Weg finden, diesen Schritt in Github-Aktionen zu automatisieren, ohne einen persönlichen Zugriffstoken zu erstellen, da der Standard-Token Geheimnisse nicht ändern kann. Dies besiegt die Pupose, einen Deploy-Schlüssel statt in der freien Ebene zu verwenden, da Sie ihn in jedem Repo erstellen müssen. Mit Ihrem Deploy Key oder Ihrem Personal Access Token (PAT) an Ort und Stelle und dem auf Ihrem Stammzweig laufenden Version- und Tag-Workflow ist der nächste Schritt die Freigabe! Dies wird je nach Projekt variieren, aber sie werden alle durch die Version ausgelöst, die aus dem vorherigen Schritt gekennzeichnet ist. name: On Version Tag, Trigger GitHub Release on: push: tags: - 'v*.*.*' permissions: contents: write jobs: release: uses: unbounded-tech/workflow-simple-release/.github/workflows/workflow.yaml@v1 with: tag: ${{ github.ref_name }} name: ${{ github.ref_name }} Oder, wenn es ein Rust-Projekt wäre, vielleicht etwas wie dieses: name: On Version Tagged, Build and Publish Rust Binaries on: push: tags: - "v*.*.*" permissions: contents: write jobs: build-and-release: uses: unbounded-tech/workflows-rust/.github/workflows/release.yaml@v1 with: binary_name: ${{ github.event.repository.name }} build_args: "--release --features vendored" Oder wenn es sich um eine Anwendung mit einem Dockerfile und k8s-Ressourcendefinitionen für Gitops-Deployments handelt, vielleicht so etwas: name: promote on: push: tags: - v*.*.* permissions: contents: write packages: write issues: write pull-requests: write jobs: publish: uses: unbounded-tech/workflows-containers/.github/workflows/publish.yaml@v1.1.1 release: needs: publish uses: unbounded-tech/workflow-simple-release/.github/workflows/workflow.yaml@v1 with: tag: ${{ github.ref_name }} name: ${{ github.ref_name }} promote: needs: release uses: unbounded-tech/workflows-gitops/.github/workflows/helm-promote.yaml@v1 secrets: GH_PAT: ${{ secrets.GH_PAT }} with: environment_repository: your-org/staging-env path: .gitops/deploy project: staging Hinweis: Ein Implementierungsschlüssel kann nicht auf andere Repos verschieben, z. B. im gitops Promote-Schritt, so dass Sie möglicherweise überlegen, überall für dieses Repository ein PAT zu verwenden. Hinweis: Ein Implementierungsschlüssel kann nicht auf andere Repos verschieben, z. B. im gitops Promote-Schritt, so dass Sie möglicherweise überlegen, überall für dieses Repository ein PAT zu verwenden. Im Allgemeinen ist jede Veröffentlichung eine Kombination einiger Teile dieser ähnlichen Module, die fast die gleichen Dinge tun, aber für ihre spezifischen Tools oder Sprachen. Normalerweise versuchen Organisationen zumindest, viele der gleichen Muster in den Anwendungen und Diensten zu folgen, die sie erstellen, und so können Entwickler die Workflows in geteilte modulare Teile aufteilen, um ihren Geschmack dieser geteilten Workflowanrufe in jedes Projekt dieser Art zu kopieren und einzufügen. Konsistente Releases mit Changelogs Sie haben vielleicht bemerkt, dass ich eine Art Blick über die Ich wollte darauf zurückdrehen, da es ein wichtiger Teil eines reifen Release-Prozesses ist.Das Changelog ist, wie Sie den anderen Entwicklern die Art und Weise mitteilen können, wie sich Ihr Projekt geändert hat. with.changelog Neben den Bumping-Versionen Außerdem verwendet er die Commit-Nachrichten, um dieses ChangeLog zu erstellen und speichert es in eine Datei namens CHANGELOG.md, die zusammen mit dem Versions-Tag und den Versions-Bumps verbunden ist. vnext Versteckt in den Workflows, die ich oben geteilt habe, wird diese Datei als Körper der GitHub Release verwendet. Das Projekt selbst: vnext Diese Veröffentlichung war eine Patch-Version, da sie eine Fix enthielt, in Form einer Abhängigkeitsversion und einer Reihe anderer Aufgaben. Diese Release-Notizen werden dann in anderen Tools wie , ein Tool, das PRs macht, um Ihre Abhängigkeiten auf dem neuesten Stand zu halten. Renovieren Bei der Fusion von Pull-Anfragen möchte ich die Funktion Squash und Fusion von GitHub verwenden, um die Möglichkeit zu haben, einen schönen endgültigen Commit-Nachrichtentitel und -Körper zu schreiben, der im Changelog verwendet wird. Zum Beispiel: Wie im Beispiel gezeigt, können Sie vollständige Markdown als Kommissionskörper setzen. Es wird entsprechend in den Release Notes abgebildet! Schlussfolgerung Ich weiß, dass Versionen und Veröffentlichungen nicht das sexyeste Thema sind; es ist ziemlich langweilig - oder besser gesagt, es sollte sein! Dies ist jedoch nicht immer der Fall.Deshalb habe ich Und ein Haufen von Jetzt kann ich die meisten Projekte sehr schnell leicht an Bord bringen! vnext Gemeinsame Workflows Hoffentlich hilft es auch Ihnen! Bitte lassen Sie mich wissen, wenn Sie geben Ich würde einige Sterne auf GitHub schätzen und teilen, wenn Sie sie nützlich finden! vnext