READMEs: Wie erstellt man Badges für (private) Repositories?

badges-title

Oft sieht man in den READMEs populärer Open-Source-Projekte eine Vielzahl bunter Badges, die einem eine schnelle Übersicht über den Projektstatus geben sollen. Für öffentliche Projekte gibt es bereits Services wie Shields.io, doch wie kann man Badges für private/unternehmensinterne Projekte erstellen? In diesem Artikel wollen wir uns anschauen, wie auch wir eigene Badges erstellen und diese dann in unseren Projekten einbinden können.

Der fertige Code kann hier gefunden werden.

Ausgangssituation

Wir entwickeln eine versionierte Webseite, deren Quellcode auf einem unternehmensinternen Server liegt (z.B. GitLab). Die Abhängigkeiten unserer Webseite managen wir mit npm.

Badges erstellen

Natürlich sind uns keine Grenzen gesetzt, welchen Inhalt unsere Badges haben werden. Doch für einen leichten Einstieg demonstriere ich, wie wir ein Badge erstellen können, welches die aktuelle Version unseres Projekts darstellt.

Die Version anhand der package.json herausfinden

Wenn wir die Version unserer Webseite in der package.json pflegen, ist es ein Leichtes, diese programmatisch zu extrahieren:

// scripts/badges.js

const version = require('../package.json').version;
console.log(version); 

Führen wir dieses Skript via node scripts/badges.js aus, wird das Attribut version aus der package.json geladen und schließlich in der Konsole ausgegeben.

Das Skript erweitern

Um ein Badge zu erstellen, wird das Paket badge-maker benötigt:

npm install --save-dev badge-maker 

Um dieses Paket im Code zu verwenden, muss es vorerst in unserem Skript importiert werden.

const { makeBadge } = require('badge-maker'); 

Außerdem benötigen wir das Modul fs, welches in Node.js integriert ist und deshalb nicht extra installiert werden muss:

const fs = require('fs'); 

Nun können wir aus der extrahierten Version ein Badge erstellen:

const version = require('../package.json').version;
const svgVersion = makeBadge({
  label: 'version',
  message: version,
  color: 'blue',
}); 

Die Funktion makeBadge() liefert einen String mit dem Badge im SVG-Format. Ihr muss ein Objekt übergeben werden, in dem das Format des Badges beschrieben wird (siehe https://www.npmjs.com/package/badge-maker#format).

In unserem Beispiel erhalten wir folgendes Badge:

 Gespeichert werden sollen unsere Badges im Verzeichnis badges/, welches zunächst erstellt werden muss:

fs.mkdir('badges', err => {
  if (err && err.errno !== -17) console.error(err);
}); 

fs.mkdir() erwartet eine Callback-Funktion, der bei einem Fehler eben dieser übergeben wird. Da diese Funktion jedoch bei jedem Aufruf ausgeführt wird, sollte man überprüfen, ob es überhaupt einen Fehler gibt. Außerdem wollen wir keinen Fehler ausgeben, wenn das Verzeichnis bereits existiert (der Fehlercode dafür ist -17).

Zu guter Letzt speichern wir das Badge in badges/version.svg:

fs.writeFile('badges/version.svg', svgVersion, err => {
  if (err) console.error(err);
}); 

Vereinen wir nun diese Codeschnipsel in einem Skript und führen dieses via node scripts/badges.js aus, finden wir anschließend ein neues Verzeichnis, badges/, welches die Datei version.svg beinhaltet.

Das Badge in der README einbinden

Schließlich müssen wir das jüngst erstellte Badge ./badges/version.svg nur noch in der README einbinden:

<!-- README.md -->
# Custom Badges ![version](badges/version.svg) 

Das Erstellen der Badges automatisieren

Damit wir die Badges nicht jedes Mal manuell aktualisieren müssen, können wir deren Erstellung automatisieren. Dazu erweitern wir die package.json um folgende Skripte:

{
  "scripts": {
    "postinstall": "npm run badges:make",
    "badges:make": "node scripts/badges.js"
  }
} 

Nun werden die Badges jedes Mal neu erstellt, nachdem npm install ausgeführt wurde.

Noch mehr Badges!

Anzahl veralteter Abhängigkeiten

Folgendes Badge zeigt an, wie viele Abhängigkeiten veraltet sind. Dies ist hilfreich, um immer auf dem neusten Stand zu bleiben. Um diese Anzahl herauszufinden, kann das Paket npm-check verwendet werden:

npm i -D npm-check 
const { makeBadge } = require('badge-maker');
const npmCheck = require('npm-check');

npmCheck().then(state => {
  const numOutdated = state.get('packages')
    .filter(pkg => !!pkg.bump)  // filtert Abhängigkeiten, denen ein Update (`bump`) zur Verfügung steht
    .length;
  const svgOutdated = makeBadge({
    label: 'outdated',
    message: String(numOutdated),  // Ganzzahl zu String konvertieren
    color: ((numOutdated === 0) ? 'green' : 'red')  // grüner Badge, falls 0 veraltet sind, andernfalls rot
  });
  fs.writeFile('badges/outdated.svg', svgOutdated, err => {
    if (err) console.error(err);
  });
});
 

Version einer Abhängigkeit

Um die Version einer einzelnen Abhängigkeit anzuzeigen, kann wie bei der Version des Projekts wieder auf die package.json zugegriffen werden. Dies sollte nur für elementare Abhängigkeiten geschehen (z.B. nur für angular in einem Angular-Projekt).

try {
  const angularVersion = require('../package.json').dependencies['@angular/core'];
} catch (err) {  // Fehler sollte auftreten, falls es keine `dependencies` gibt oder '@angular/core' keine Abhängigkeit ist
  const angularVersion = 'not used';
}
// makeBadge...
// writeFile... 

Letzte Modifizierung am Projekt

Um das Datum der letzten Modifizierung anzuzeigen, kann folgender Ausdruck verwendet werden. Dies ist hilfreich um in Erfahrung zu bringen, wann zuletzt am Projekt gearbeitet wurde.

const today = new Date()
  .toISOString()  // z.B. '2020-12-31T24:59:59.999Z'
  .replace(/T.*/, '');  // entfernt alles ab dem ersten 'T'
// makeBadge...
// writeFile... 

Fazit: Einfacher als gedacht! 

In diesem Beitrag wurde gezeigt, wie Badges für ein Projekt mithilfe von badge-maker (https://www.npmjs.com/package/badge-maker) erstellt werden können. Diese Badges können nützliche Informationen auf einen Blick liefern, wie zum Beispiel die aktuelle Version des Projektes. Dabei ist nicht relevant, ob das Projekt nur privat, auf einem eigenen Server, oder öffentlich verfügbar ist. Uns sind bei der Erstellung also keine Grenzen gesetzt!

Weiterführende Links

By accepting you will be accessing a service provided by a third-party external to https://blog.ordix.de/