NPM Packages über den GitHub NPM Feed veröffentlichen
GitHub bietet eigene Package Feeds für NPM, NuGet usw. an. Diese bieten eine Alternative zu den offiziellen Feeds und haben den Vorteil, dass alles direkt in GitHub integriert ist. Du musst also keine Accounts bei den offiziellen Feeds erstellen und Secrets für den Zugriff in deinen CI/CD Pipelines hinterlegen. In diesem Beitrag zeige ich dir, wie du in wenigen Schritten mit einer GitHub Action ein NPM Package über den GitHub NPM Feed veröffentlichen kannst.
Der GitHub Actions Workflow
Damit wir ein NPM Package veröffentlichen können, müssen wir es natürlich zunächst erstellen. Dazu erstellen wir einen GitHub Actions Workflow. Als Basis dient der Workflow aus einem früheren Beitrag, den ich zum Erstellen einer Static Site verwendet hatte:
name: build-and-publish
on: push
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Restore Node Modules
uses: actions/cache@v2
with:
path: node_modules
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-modules-
- name: Install Dependencies
run: yarn --frozen-lockfile
- name: Build Package
run: yarn build
In diesem Fall erstellt der Befehl yarn build
anstatt der Static Site das NPM Package. Auf die Details gehen wir hier nicht ein, da diese davon abhängig sind mit welcher Toolchain du dein NPM Package erstellst. Wir gehen für den weiteren Verlauf davon aus, dass das NPM Package im Verzeichnis dist/package
erstellt wurde. Wichtig ist lediglich, dass in diesem Verzeichnis schlussendlich eine Datei package.json
existiert, die den Names des Packages und die Version enthält:
{
"name": "test-github-npm-feed",
"version": "1.0.0"
}
NPM bzw. Yarn konfigurieren
Als nächstes müssen wir NPM bzw. Yarn so konfigurieren, dass beim Veröffentlichen des Packages der richtige Package Feed bzw. die richtige Registry verwendet wird. Normallerweise verwenden NPM und Yarn den standard Package Feed von NPM, welcher über die URL https://registry.npmjs.org
angesprochen wird. Wir wollen unser Package jedoch im GitHub Package Feed veröffentlichen, welcher unter der URL https://npm.pkg.github.com
verfügbar ist. Damit beim Veröffentlichen des Packages auch dieser Feed verwendet wird, konfigurieren wir dies über die entsprechende GitHub Action actions/setup-node
:
name: build-and-publish
on: push
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Restore Node Modules
uses: actions/cache@v2
with:
path: node_modules
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-modules-
- name: Install Dependencies
run: yarn --frozen-lockfile
- name: Build Package
run: yarn build
- name: Prepare Publish
uses: actions/setup-node@v1
with:
registry-url: 'https://npm.pkg.github.com'
Package veröffentlichen
Nachdem wir Yarn konfiguriert haben, können wir als nächstes das NPM Package veröffentlichen. Für den Zugriff auf den Package Feed müssen wir Yarn ein Access Token mitgeben. Da bei GitHub aber wie bereits erwähnt alles integriert ist, müssen wir dieses Token nirgends hinterlegen. Es steht dem Workflow bereits zur Verfügung und wir können es direkt verwenden:
name: build-and-publish
on: push
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v2
- name: Restore Node Modules
uses: actions/cache@v2
with:
path: node_modules
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-modules-
- name: Install Dependencies
run: yarn --frozen-lockfile
- name: Build Package
run: yarn build
- name: Prepare Publish
uses: actions/setup-node@v1
with:
registry-url: 'https://npm.pkg.github.com'
- name: Publish Package
run: yarn publish dist/package
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GitHub unterstützt nur Scoped Packages
Damit haben wir eigentlich alles beisammen, was wir für die Veröffentlichung des Packages benötigen. Der GitHub Actions Workflow schlägt jedoch fehl:
Die Fehlermeldung ist nicht wirklich hilfreich. Angeblich wurde kein Token gefunden, obwohl wir eines angegeben haben. Das Problem liegt aber wo anders, und zwar bei unserem Package Namen. Momentan heisst unser Package test-github-npm-feed
. Dies ist ein ganz normaller und valider Name für ein NPM Package. Laut der GitHub Dokumentation unterstützt der GitHub NPM Feed jedoch nur Scoped Packages. Das sind Packages, die ein Scope Prefix haben. Das Scope Prefix definiert sozusagen, wer der Besitzer des Packages ist. Wir müssen unser package.json
also noch anpassen und unseren GitHub Benutzernamen als Scope hinzufügen. In meinem Fall sieht dass dann so aus:
{
"name": "@raeffs/test-github-npm-feed",
"version": "1.0.0"
}
Anschliessend läuft der Workflow ohne Fehler durch und unser Package wird veröffentlicht:
Mehrere Packages pro Repository
Neben dem Scope Prefix gibt es noch eine weitere Voraussetzung, dass die Veröffentlichung des Packages auf dem GitHub Feed funktioniert: Das Package muss gleich heissen wie das Repository, in dem der GitHub Actions Workflow läuft. Dies war bereits der Fall und deshalb hat die Veröffentlichung auch funktioniert. Doch was, wenn wir mehrere unterschiedliche Packages in unserem Repository haben und diese veröffentlichen möchten?
Damit dies klappt, müssen wir im package.json
neben dem Namen und der Version zusätzlich noch die URL des Repositories angeben:
{
"name": "@raeffs/my-package",
"repository": "https://github.com/raeffs/test-github-npm-feed",
"version": "1.0.0"
}
Dann klappt die Veröffentlichung auch wenn der Package Name nicht mit dem Repository Namen übereinstimmt.