{"id":6615,"date":"2022-03-04T17:59:47","date_gmt":"2022-03-04T16:59:47","guid":{"rendered":"https:\/\/qdraw.nl\/blog\/?p=6615"},"modified":"2022-11-14T14:28:18","modified_gmt":"2022-11-14T13:28:18","slug":"een-eigen-npm-private-feed-maken-met-azure-devops","status":"publish","type":"post","link":"https:\/\/qdraw.nl\/blog\/technologie\/een-eigen-npm-private-feed-maken-met-azure-devops\/","title":{"rendered":"Een eigen NPM private feed maken met Azure Devops"},"content":{"rendered":"<p>In deze blogpost ga ik het hebben over een technische oplossing waarbij je software onderdelen kunt delen tussen verschillende applicaties. Dit is alleen relevant als je meerdere applicaties hebt en hier onderdelen tussen wil delen.<\/p>\n<p><a href=\"https:\/\/qdraw.medium.com\/create-your-own-npm-private-feed-with-azure-devops-54e02b81a10e\" target=\"_blank\" rel=\"noopener\">There is an English version of this blog post<\/a><\/p>\n<h2>TL;DR; (Samenvatting)<\/h2>\n<p>In deze blog koppelen we een private NPM-feed (Node Package Manager) om deze te gebruiken tijdens het ontwikkelen, in een container en in de Continuous Integration (CI) pipelines. Dit doe ik om versies te hebben van componenten. Ik gebruik hier de tools Azure DevOps, NPM, Nodejs en Docker. Om er voor te zorgen dat de authenticatie gebruiken we een Oath2 flow waarbij vlak voor de installatie (preinstall) tokens ophalen. <a href=\"https:\/\/github.com\/qdraw\/azure-devops-private-npm-artifacts-feed-demo\" target=\"_blank\" rel=\"noopener\">Er is een Github repository aanwezig waar een werkend voorbeeld wordt gegeven<\/a><\/p>\n<h2>Project wensen<\/h2>\n<p>Voor een project waar ik aan werk bestaat de wens naar losse NPM registries. NPM staat voor Node Package Manager. NPM wordt gebruikt om javascript gebaseerde projecten online te her gebruiken. Hiervoor wordt de publieke npmjs.com-feed gebruikt. Als je code wil delen tussen een beperkte set gebruikers of teams kun je private user (project) of organisation-scoped packages publiceren naar het npm registry. User (project) scoped betekent dat deze alleen binnen hetzelfde Azure DevOps project wordt gedeeld en als je organisation-scoped kiest wordt deze binnen de hele organisatie gedeeld. Deze private NPM registries hebben als voordeel dat front-end applicaties eigen ontwikkelde software onderdelen kunnen uitwisselen.  <\/p>\n<h2>Wat is Azure DevOps<\/h2>\n<p>Azure DevOps is een tool voor ontwikkelaars services waarmee teams werk kunnen plannen, samenwerken aan code-ontwikkeling en toepassingen kunnen bouwen en implementeren. Azure DevOps ondersteunt een samenwerkingscultuur en een reeks processen die ontwikkelaars, projectmanagers en bijdragers samenbrengen om software te ontwikkelen. Wij gebruiken de pipeline functionaliteiten het meeste. Dat is het centraal compileren van software en het releasen naar omgevingen. <\/p>\n<h2>Azure DevOps Artifacts<\/h2>\n<p>Naast de pipelines bestaan er ook Artifacts. Met Azure Artifacts kunnen ontwikkelaars pakketten uit verschillende feeds en openbare registers delen en gebruiken. Pakketten kunnen worden gedeeld binnen hetzelfde team, dezelfde organisatie en zelfs openbaar. Azure Artifacts ondersteunt meerdere pakkettypen, zoals NuGet, npm, Python, Maven en Azure Universal Packages.  <\/p>\n<p>Zo ziet een feed er bijvoorbeeld uit:<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-01-om-141244_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Overzicht van een private npm feed | foto 1\"\n       data-gps=\"0,0\" data-heightratio=\"0.297\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-01-om-141244_kl.jpg\" alt=\"Overzicht van een private npm feed\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABCAIAAAB2XpiaAAAAFUlEQVR4AWN5\/foNHx8vIyPT\/\/\/\/ASXsBfFROg5uAAAAAElFTkSuQmCC\" title=\"Overzicht van een private npm feed | foto 1\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Overzicht van een private npm feed ; Azure Devops, private feed\" \/><br \/>\n    <\/a><\/p>\n<h2>Docker containers<\/h2>\n<p>Voor het project gebruiken we Docker containers om de software te draaien.<br \/>\nEen container is een manier om software en alle dependencies van software bij elkaar te houden en makkelijk uit te wisselen tussen verschillende omgevingen. Een Docker-containerimage is een lichtgewicht, op zichzelf staand, uitvoerbaar softwarepakket dat alles bevat wat nodig is om een applicatie uit te voeren: code, runtime, systeemtools, systeembibliotheken en instellingen.<\/p>\n<h2>Azure\u2019s Windows only oplossing<\/h2>\n<p>De offici\u00eble tool om de authenticatie naar je private NPM feed te regelen is <a target=\"_blank\" href=\"https:\/\/www.npmjs.com\/package\/vsts-npm-auth\" rel=\"noopener\">vsts-npm-auth<\/a> alleen deze werkt alleen op Windows. Aangezien we in ons project een combinatie van Mac, Windows en Docker werken is dit geen werkbare oplossing in onze situatie.<\/p>\n<h2>Personal access tokens (PAT\u2019s)<\/h2>\n<p>Helaas werken PAT\u2019s niet goed in combinatie met het ophalen van NPM-packages uit de Azure Artifacts feed. Ik krijg hier 401 errors op en kom er niet verder mee.<\/p>\n<h2>Een alternatief: better-vsts-npm-auth<\/h2>\n<p>Ik ben verder gaan kijken en kwam het project better-vsts-npm-auth tegen. Deze tool doet een oauth2 authenticatie richting Azure DevOps en zorgt ervoor dat je als gebruiker een valide token hebt om npm packages mee op te halen<\/p>\n<h2>In de praktijk: Stappen die vooraf nodig zijn<\/h2>\n<p>De volgende stappen heb je nodig om zelf een refresh token te generen.<\/p>\n<ol>\n<li>Voordat je begint: Zorg ervoor dat op je ontwikkelmachine een recente versie van nodejs is ge\u00efnstalleerd<\/li>\n<li>Zorg ervoor dat je toegang hebt tot het Azure DevOps Artifacts gedeelte: https:\/\/dev.azure.com\/YOUR_ORG\/_packaging<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/github.com\/qdraw\/azure-devops-private-npm-artifacts-feed-demo\" target=\"_blank\" rel=\"noopener\">Ik heb onderstaande code snippets verzameld en in een losse repository gezet. Deze is op Github te vinden en daar te downloaden.<\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>Maak een nieuwe feed aan in Azure Devops<\/h2>\n<p>Binnen Azure DevOps valt dit onder Artifacts klik dan op \u201c+ Create Feed\u201d<\/p>\n<p>Je kunt hier kiezen uit twee verschillende scopes<\/p>\n<ol>\n<li>Project, dus alleen het huidige project<\/li>\n<li>Organization: binnen de huidige Azure DevOps organization<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-165505_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Voeg een nieuwe feed toe | foto 2\"\n       data-gps=\"0,0\" data-heightratio=\"0.642\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-165505_kl.jpg\" alt=\"Voeg een nieuwe feed toe\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAMElEQVR4AQ3GQQ4AEAwEwKbdtksivAH\/v\/M65jQ459bC1sdcG&#x2B;5IMsMZgKqKiJn9PGwjA0dllJjcAAAAAElFTkSuQmCC\" title=\"Voeg een nieuwe feed toe | foto 2\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Voeg een nieuwe feed toe ; Azure Devops, Add new feed\" \/><br \/>\n    <\/a><\/p>\n<h2>Installeer de global package <code>better-vsts-npm-auth<\/code><\/h2>\n<p>Op je lokale machine installeer je <code>better-vsts-npm-auth<\/code> als globaal pakket zodat deze vanaf verschillende locaties aangeroepen kan worden<\/p>\n<p>Doe dit middels het volgende commando:<\/p>\n<pre><code>\r\nnpm i -g better-vsts-npm-auth\r\n<\/code><\/pre>\n<p>&nbsp;<\/p>\n<h2>Setup voor front-end library<\/h2>\n<p>Ga naar je front-end library folder en zorg ervoor dat er twee dingen minimaal in staan.<\/p>\n<ol>\n<li> project <code>.npmrc<\/code> file <br \/>\nDe project npmrc bevat de locaties van je eigen private feeds met een prefix van een pakketnaam. Hieronder geef ik een voorbeeld van hoe ik dat toepas.<\/li>\n<li><code>package.json<\/code> bestand<br \/>\nDit bevat de namen van alle dependencies die worden gebruikt.\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<h3>1. Library Project <code>.npmrc<\/code> file<\/h3>\n<p>&nbsp;<\/p>\n<pre><code>\r\n@qdraw-components:registry=https:\/\/pkgs.dev.azure.com\/qdraw\/_packaging\/demo\/npm\/registry\/\r\nalways-auth=true\r\n<\/code><\/pre>\n<p>&nbsp;<\/p>\n<h3>2. Library Project package.json file<\/h3>\n<p>&nbsp;<\/p>\n<pre><code>\r\n{\r\n    \"name\": \"@qdraw-components\/components\",\r\n    \"version\": \"0.0.1-rc.1\",\r\n    \"description\": \"Test front-end components\",\r\n    \"scripts\": {\r\n    },\r\n    \"author\": \"\",\r\n    \"license\": \"ISC\",\r\n    \"devDependencies\": {\r\n        \"typescript\": \"^4.5.5\"\r\n    },\r\n    \"dependencies\": {\r\n    },\r\n    \"main\": \"dist\/cjs\/index.js\",\r\n    \"module\": \"dist\/esm\/index.js\",\r\n    \"files\": [\r\n        \"dist\"\r\n    ],\r\n    \"types\": \"dist\/index.d.ts\"\r\n}\r\n<\/code><\/pre>\n<p>&nbsp;<\/p>\n<h2>Authenticatie vanaf je ontwikkelmachine<\/h2>\n<p>De authenticatie verloopt vervolgens via de Azure DevOps aan de hand van de recent ge\u00efnstalleerde tool. Dit doe ik binnen de front-end library folder waar ook het bovenstaande package.json en npmrc bestand staan.<\/p>\n<pre><code>\r\nbetter-vsts-npm-auth\r\n<\/code><\/pre>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-171247_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - better-vsts-npm-auth | foto 3\"\n       data-gps=\"0,0\" data-heightratio=\"0.324\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-171247_kl.jpg\" alt=\"better-vsts-npm-auth\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABCAIAAAB2XpiaAAAAFUlEQVR4AWN5\/uI1BzsrNzcXMzMzAB&#x2B;RAvzrYDzwAAAAAElFTkSuQmCC\" title=\"better-vsts-npm-auth | foto 3\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; better-vsts-npm-auth ; Azure Devops, better-vsts-npm-auth, npmrc\" \/><br \/>\n    <\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Als ik bovenstaande url kopieer in de browser krijg ik het volgende scherm te zien. Druk op Accept om verder te gaan<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-171350_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Stateless VSTS NPM OAuth | foto 4\"\n       data-gps=\"0,0\" data-heightratio=\"0.455\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-171350_kl.jpg\" alt=\"Stateless VSTS NPM OAuth\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAIAAADwyuo0AAAAI0lEQVR4AWN5\/Ow1I8N\/bk5WDg4Olr8MDIJcbIxMzP\/\/\/wcAa8UIDzSMfPoAAAAASUVORK5CYII=\" title=\"Stateless VSTS NPM OAuth | foto 4\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Stateless VSTS NPM OAuth ; Azure Devops\" \/><br \/>\n    <\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Wanneer je op Accept klikt krijg je het Succes scherm te zien. Op dit scherm staat een command met een unieke refresh token.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-171402_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Copy this command and run it in your terminal | foto 5\"\n       data-gps=\"0,0\" data-heightratio=\"0.356\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-171402_kl.jpg\" alt=\"Copy this command and run it in your terminal\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABCAIAAAB2XpiaAAAAFUlEQVR4AWO5efMmAwMDJycnBwcHABzxAsOrDg6rAAAAAElFTkSuQmCC\" title=\"Copy this command and run it in your terminal | foto 5\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Copy this command and run it in your terminal ; Azure Devops, terminal\" \/><br \/>\n    <\/a><\/p>\n<p>&nbsp;<\/p>\n<p>We doen twee dingen met het token: Het command uitvoeren:<\/p>\n<pre><code>\r\nbetter-vsts-npm-auth config set refresh_token eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Im9PdmN6NU1fN3AtSGpJS2xGWHo5M3VfVjBabyJ9.eyJuYW1laW\r\n<\/code><\/pre>\n<p>Kopieer het token gedeelte zonder: <code>better-vsts-npm-auth config set refresh_token<\/code>. Zet dit als environment variable <br \/><code>DEMO_NPM_REFRESH_TOKEN<\/code>, hoe je dat doet staat hieronder beschreven. Deze variable hebben we later nodig in Docker. <\/p>\n<p>&nbsp;<\/p>\n<h3>1. Op Mac OS voeg je het volgende toe aan je .zprofile of .zshrc:<\/h3>\n<pre><code>\r\nnano ~\/.zprofile\r\n<\/code><\/pre>\n<pre><code>\r\nexport DEMO_NPM_REFRESH_TOKEN=\"LongTokenHere\"\r\n<\/code><\/pre>\n<p>Deze instellingen zijn pas actief na het herstarten van je terminalvenster<\/p>\n<p>&nbsp;<\/p>\n<h3>2. Op Windows voeg je het volgende toe:<\/h3>\n<ul>\n<li> Druk de volgende toetscombinatie in: Windows + R <\/li>\n<li>  Type: `sysdm.cpl` <\/li>\n<li>  Click op de Advanced tab <\/li>\n<li>  Iets boven OK &#038; Cancel click op Environment Variables&#8230;<\/li>\n<li>   Onder System Variable: Press New<\/li>\n<li>   DEMO_NPM_REFRESH_TOKEN<\/li>\n<li>   En de token (without the better-vsts prefix)<\/li>\n<li>  Druk Ok om te bevestigen<\/li>\n<\/ul>\n<p>Deze instellingen zijn pas actief na het herstarten van je Powershell venster<\/p>\n<p>&nbsp;<\/p>\n<h2>Controleer of je in de juiste omgeving bent ingelogd<\/h2>\n<p>Controleer of de app: &#8220;Stateless VSTS NPM OAuth&#8221; aanwezig is op: https:\/\/dev.azure.com\/YOUR_ORG\/_usersSettings\/authorizations <\/p>\n<p>Staat de app daar niet, dan ben je waarschijnlijk verbonden met de verkeerde organisatie. Als dit het geval is, probeer dan de url te kopi\u00ebren en te plakken in een browservenster dat zich in de priv\u00e9- of incognito modus bevindt.<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-1716002022-03-03-190734_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Controleer of de app in de lijst staat | foto 7\"\n       data-gps=\"0,0\" data-heightratio=\"0.424\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-1716002022-03-03-190734_kl.jpg\" alt=\"Controleer of de app in de lijst staat\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAIAAADwyuo0AAAAJUlEQVR4AQXCwQkAMAwDsRgc779q&#x2B;kyhVyTPnKSrtHcNTxKQ9geiCwvpur7uJAAAAABJRU5ErkJggg==\" title=\"Controleer of de app in de lijst staat | foto 7\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Controleer of de app in de lijst staat ; Azure Devops, Authorized Oauth Apps\" \/><br \/>\n    <\/a><\/p>\n<h2>Bij authenticatie problemen <\/h2>\n<p>Mochten er problemen zijn met de authenticatie verwijder dan de volgende bestanden uit je home folder. Op Mac OS zou een voorbeeld dit <code>\/Users\/dion<\/code> kunnen zijn en op Windows <code>C:\\Users\\Dion<\/code>. <\/p>\n<ol>\n<li>\u201c.vstsnpmauthrc\u201d<\/li>\n<li>\u201c.npmrc\u201d<\/li>\n<li>De environment variable  \u201cDEMO_NPM_REFRESH_TOKEN\u201d<\/li>\n<\/ol>\n<p>Beide bestanden bevatten inloggegevens en kunnen veilig worden verwijderd. Probeer het daarna opnieuw. Hieronder toon ik dat de twee bestanden aanwezig zijn<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-1716002022-03-03-191530_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Je home folder, deze bestanden kun je verwijderen om opnieuw te | foto 8\"\n       data-gps=\"0,0\" data-heightratio=\"0.702\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-1716002022-03-03-191530_kl.jpg\" alt=\"Je home folder, deze bestanden kun je verwijderen om opnieuw te\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAM0lEQVR4AQXCwQkAIAgF0IskJG7gBrn\/Sl7MBZJvvEd5MyJ4sZmRbPHjA7xuAlBVM6OqH4V8FWh0xfFFAAAAAElFTkSuQmCC\" title=\"Je home folder, deze bestanden kun je verwijderen om opnieuw te | foto 8\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Je home folder, deze bestanden kun je verwijderen om opnieuw te ; Azure Devops, home folder\" \/><br \/>\n    <\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>NPM Publish vanuit front-end library folder<\/h2>\n<p>Vanuit de front-end library folder doen we een publish naar Azure DevOps. Zorg ervoor dat bij het publiceren elke keer je in de package.json een uniek oplopend versienummer hebt.<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-171538_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - NPM Publish | foto 6\"\n       data-gps=\"0,0\" data-heightratio=\"0.407\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-171538_kl.jpg\" alt=\"NPM Publish\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAIAAADwyuo0AAAAIElEQVR4AWNZMH9lcIA3MzsTJycnCwPT37&#x2B;Mv\/\/9BnEAaUQIFGHDyMIAAAAASUVORK5CYII=\" title=\"NPM Publish | foto 6\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; NPM Publish ; Azure Devops, npm, node package manager, NPM Publish\" \/><br \/>\n    <\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Nu staat deze package in de private npm feed en dat ziet er als volgt uit.<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-172134_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Nieuw aangemaakte feed | foto 9\"\n       data-gps=\"0,0\" data-heightratio=\"0.254\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-172134_kl.jpg\" alt=\"Nieuw aangemaakte feed\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABCAIAAAB2XpiaAAAAFUlEQVR4AWP5\/u0bEzMLA8N\/BgYGACRFA\/ArEslXAAAAAElFTkSuQmCC\" title=\"Nieuw aangemaakte feed | foto 9\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Nieuw aangemaakte feed ; Azure Devops, private feed\" \/><br \/>\n    <\/a><\/p>\n<h2>Unieke prefix wanneer je meerdere private feeds hebt<\/h2>\n<p>In ons geval gebruiken we meerdere npm feeds voor verschillende onderdelen. In het bovenstaande voorbeeld gebruik ik de prefix: \u201c@qdraw-components\u201d en een slash om deze prefix af te sluiten. Het is belangrijk om de naam op deze manier op te bouwen, dan kun je dit namelijk aangeven in het project npmrc bestand. Mocht je er een feed naast hebben voor icons dan kan deze niet dezelfde prefix hebben. De prefix moet dus uniek zijn en beginnen met een apenstaartje.<\/p>\n<p>&nbsp;<\/p>\n<h2>Docker Applicatie setup<\/h2>\n<p>In de applicatie waar de front-end library wordt gebruikt doen we een volgende setup: Hetzelfde. npmrc bestand staat in de applicatiemap.<\/p>\n<h3>De project .npmrc file<\/h3>\n<pre><code>\r\n@qdraw-components:registry=https:\/\/pkgs.dev.azure.com\/qdraw\/_packaging\/demo\/npm\/registry\/\r\nalways-auth=true\r\n<\/code><\/pre>\n<p>Daarnaast heeft dit project een eigen package.json<\/p>\n<p><code>package.json<\/code><\/p>\n<pre><code>\r\n{\r\n  \"name\": \"use_app\",\r\n  \"version\": \"1.0.0\",\r\n  \"description\": \"\",\r\n  \"main\": \"index.js\",\r\n  \"scripts\": {\r\n    \"preinstall\": \"node scripts\/preinstall.js\"\r\n  },\r\n  \"author\": \"\",\r\n  \"license\": \"ISC\",\r\n  \"dependencies\": {\r\n    \"@qdraw-components\/components\": \"^0.0.1-rc.1\"\r\n  }\r\n}\r\n<\/code><\/pre>\n<p>In de preinstall wordt op basis van een refresh token een access token opgehaald zodat je private packages opgehaald en ge\u00efnstalleerd kunnen worden <\/p>\n<p><a target=\"_blank\" href=\"https:\/\/github.com\/qdraw\/azure-devops-private-npm-artifacts-feed-demo\/blob\/master\/use_app\/scripts\/preinstall.js\" rel=\"noopener\">Het bestand scripts\/preinstall.js is te vinden op Github<\/a><\/p>\n<p>In de Dockerfile wordt het bestand scripts\/cleanauth.js aangeroepen om de inloggegevens uit de container te verwijderen.<\/p>\n<p><code>scripts\/cleanauth.js<\/code><\/p>\n<pre><code>\r\n#!\/usr\/bin\/env node\r\n \r\n\/\/ remove tokens from docker image\r\n \r\nconst fs = require('fs')\r\nconst path = require('path');\r\n \r\nfunction UserProfileFolder() {\r\n    let userProfileFolder = \"~\";\r\n    if (process.env.CSIDL_PROFILE) {\r\n        userProfileFolder = process.env.CSIDL_PROFILE;\r\n    }\r\n    if (process.env.HOME) {\r\n      userProfileFolder = process.env.HOME;\r\n    }\r\n    return userProfileFolder;\r\n}\r\n \r\nconst userProfileFolder = UserProfileFolder();\r\n \r\nconst vstsNpmauthRcFilePath = path.join(userProfileFolder, '.vstsnpmauthrc');\r\nif (fs.existsSync(vstsNpmauthRcFilePath)) {\r\n    fs.unlinkSync(vstsNpmauthRcFilePath)\r\n}\r\n \r\nconst userNpmRcFilePath = path.join(userProfileFolder, '.npmrc');\r\nif (fs.existsSync(userNpmRcFilePath)) {\r\n    fs.unlinkSync(userNpmRcFilePath)\r\n}\r\n<\/code><\/pre>\n<p>Dit project heeft de volgende Dockerfile<\/p>\n<p><code>Dockerfile<\/code><\/p>\n<pre><code>\r\n# Install dependencies only when needed\r\nFROM node:16-alpine AS deps\r\nARG YOURPROJECT_NPM_REFRESH_TOKEN=default\r\nARG AZURE_AUTH_TOKEN=default\r\n \r\nRUN apk add --no-cache libc6-compat\r\nWORKDIR \/app\r\n \r\nENV YOURPROJECT_NPM_REFRESH_TOKEN=$YOURPROJECT_NPM_REFRESH_TOKEN\r\nENV AZURE_AUTH_TOKEN=$AZURE_AUTH_TOKEN\r\n \r\nCOPY use_app\/scripts\/preinstall.js .\/scripts\/preinstall.js\r\nCOPY use_app\/scripts\/cleanauth.js .\/scripts\/cleanauth.js\r\nCOPY use_app\/package.json .\/\r\n \r\nRUN node scripts\/preinstall.js\r\nRUN npm ci --prefer-offline\r\n \r\nRUN node scripts\/cleanauth.js\r\n<\/code><\/pre>\n<p>Deze Dockerfile kan op twee manieren worden aangeroepen zodat dit een docker container wordt.<\/p>\n<p>&nbsp;<\/p>\n<h3>1. Docker build command<\/h3>\n<pre><code>\r\ncd root_of_solution\r\ndocker build -f use_app\/Dockerfile . --no-cache --build-arg DEMO_NPM_REFRESH_TOKEN=${DEMO_NPM_REFRESH_TOKEN}\r\n<\/code><\/pre>\n<p>&nbsp;<\/p>\n<h3>2. Of als Docker compose<\/h3>\n<p><code>docker-compose.yml<\/code><\/p>\n<pre><code>\r\nversion: '3.4'\r\n \r\nservices:\r\n  demo.use.app:\r\n    image: ${DOCKER_REGISTRY-}demouseapp\r\n    build:\r\n      context: .\r\n      dockerfile: use_app\/Dockerfile\r\n      args:\r\n        - DEMO_NPM_REFRESH_TOKEN=${DEMO_NPM_REFRESH_TOKEN}\r\n    environment:\r\n      - DEMO=true\r\n    ports:\r\n      - \"19443:9443\"\r\n<\/code><\/pre>\n<p>&nbsp;<\/p>\n<p>Docker draait op een lokale omgeving<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-201659_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Docker | foto 10\"\n       data-gps=\"0,0\" data-heightratio=\"0.698\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-201659_kl.jpg\" alt=\"Docker\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAALUlEQVR4AQ3IwQ0AQAgCQTA8rwH7b4w&#x2B;TDx5bXZku7slkdQHQFZVqhfcxUzmAKB2CBj8Sj7AAAAAAElFTkSuQmCC\" title=\"Docker | foto 10\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Docker ; Azure Devops, npm, node package manager, Docker, container\" \/><br \/>\n    <\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>Azure DevOps Pipeline<\/h2>\n<p>Om Azure DevOps te configureren gebruik je yaml files, hierin staan alle stappen welke de build pipeline gaat uitvoeren<br \/>\nZie hiervoor: <a target=\"_blank\" href=\"https:\/\/github.com\/qdraw\/azure-devops-private-npm-artifacts-feed-demo\/blob\/master\/azure\/azure-pipelines.yml\" rel=\"noopener\">azure\/azure-pipelines.yml<\/a> en  <a target=\"_blank\" href=\"https:\/\/github.com\/qdraw\/azure-devops-private-npm-artifacts-feed-demo\/blob\/master\/azure\/templates\/build-docker.yml\" rel=\"noopener\">azure\/templates\/build-docker.yml<\/a><\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-203430_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Azure Devops Build pipeline, 403 | foto 11\"\n       data-gps=\"0,0\" data-heightratio=\"0.508\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-203430_kl.jpg\" alt=\"Azure Devops Build pipeline, 403\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAIAAADwyuo0AAAAJElEQVR4AWN5&#x2B;&#x2B;7dxL7eZcuWc\/Fws3Bycv768fPrp4&#x2B;\/\/vwGALhPD2FSWGLlAAAAAElFTkSuQmCC\" title=\"Azure Devops Build pipeline, 403 | foto 11\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Azure Devops Build pipeline, 403 ; Azure Devops, Docker, container, Azure Devops Build pipeline, 403\" \/><br \/>\n    <\/a><\/p>\n<p>Als je een organisation-scoped packages uit de Azure Artifact gebruikt dan krijg je de volgende foutmelding:<\/p>\n<p> \u201cnpm ERR! 403 403 Forbidden &#8211; GET https:\/\/pkgs.dev.azure.com\/YOURENV\/_packaging\/demo\/npm\/registry\/@qdraw-components%2fcomponents &#8211; User d9af02c4-b000-4fd4-9754-68706813d7ca\u201d<\/p>\n<p>Om deze te verhelpen voeg je de build user toe aan de private feed<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-203724_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Volg de pijl | foto 12\"\n       data-gps=\"0,0\" data-heightratio=\"0.22\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-203724_kl.jpg\" alt=\"Volg de pijl\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABCAIAAAB2XpiaAAAAFUlEQVR4AWP59u0bMzMzIyPjv\/\/\/ASZFBe\/JZTx4AAAAAElFTkSuQmCC\" title=\"Volg de pijl | foto 12\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Volg de pijl ; Azure Devops, private feed\" \/><br \/>\n    <\/a><\/p>\n<p>In de onderstaande schermafbeelding zie je hoe ik dat doe.<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-204908_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Klik Add users\/group | foto 13\"\n       data-gps=\"0,0\" data-heightratio=\"0.589\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-204908_kl.jpg\" alt=\"Klik Add users\/group\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAIAAADwyuo0AAAAI0lEQVR4AQ3HsREAIAwCQIQc&#x2B;69LoZjvfpJIaktybAO4b3M&#x2B;jVAJEQO9Vl0AAAAASUVORK5CYII=\" title=\"Klik Add users\/group | foto 13\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Klik Add users\/group ; Azure Devops, private feed\" \/><br \/>\n    <\/a><\/p>\n<h2>Build succesvol<\/h2>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-02-om-210724_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Azure Devops draait goed | foto 14\"\n       data-gps=\"0,0\" data-heightratio=\"0.611\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-02-om-210724_kl.jpg\" alt=\"Azure Devops draait goed\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAIAAADwyuo0AAAAJElEQVR4AWO5eeu2nKxMWVnpnj17WP7\/\/cvMzPz8&#x2B;fNHjx4BALLaDuB66tX1AAAAAElFTkSuQmCC\" title=\"Azure Devops draait goed | foto 14\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Azure Devops draait goed ; Azure Devops, Docker, container\" \/><br \/>\n    <\/a><\/p>\n<h2>Conclusie<\/h2>\n<p>Het was een interessante zoektocht naar de mogelijkheden van Azure DevOps en dan met name hoe ze dit onderdeel in elkaar hebben gestoken. Omdat er zo weinig van op internet te vinden was heb ik veel zelf uitgezocht en in deze blog heb ik getracht om mijn kennis zo goed mogelijk uit te schrijven.<\/p>\n<p>En het pakketje is succesvol bezorgd&#8230;<\/p>\n<p><a href=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/1000\/2022-03-03_20200819_103524_dsc02305_e_kl1k.jpg\" class=\"lightbox[blog]\"\n       title=\"Een eigen NPM private feed maken met Azure Devops - Pakket bezorger | foto 15\"\n       data-gps=\"50.838997,4.352256\" data-heightratio=\"0.728\"><br \/>\n        <noscript><img decoding=\"async\" src=\"https:\/\/media.qdraw.nl\/log\/een-eigen-npm-private-feed-maken-met-azure-devops\/500\/2022-03-03_20200819_103524_dsc02305_e_kl.jpg\" alt=\"Pakket bezorger\" \/><\/noscript><br \/>\n\t\t<img decoding=\"async\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAMElEQVR4AWPJy8u9d\/uGupqamLg4i7S0zMunTxh\/M96&#x2B;&#x2B;4SFh5vn7bv3UtJyUoJiADDEDrxtGjDeAAAAAElFTkSuQmCC\" title=\"Pakket bezorger | foto 15\" \n\t\t     alt=\"Een eigen NPM private feed maken met Azure Devops ; Pakket bezorger ; straatleven, straat, pakketbezorger, post, bezorger\" \/><br \/>\n    <\/a><\/p>\n<h2>Fout senario: Verbonden met de verkeerde tenant<\/h2>\n<p>Als je de volgende melding ziet in de preinstall.js: You are probably connected to the WRONG tenant<br \/>\nGa dan naar de switcher in Azure Devops <a href=\"https:\/\/app.vsaex.visualstudio.com\/me\">https:\/\/app.vsaex.visualstudio.com\/me<\/a> en selecteer aan de linkerkant het juiste bedrijf. Ga vervolgens weer terug naar oauth provider, dit is in de meeste gevallen: stateless-vsts-oauth.azurewebsites.net om een nieuw refresh token op te halen. Plaats deze weer als environment variablen en herstart het venster om het daarna opnieuw te proberen<\/p>\n<h2>Optionele stap: Zelf hosten van de stateless-vsts-oauth provider<\/h2>\n<p>\nMocht je de stateless-vsts-oauth zelf willen hosten bijvoorbeeld niet afhankelijk te zijn van: stateless-vsts-oauth.azurewebsites.net dan is de code te vinden op:<br \/>\n<a href=\"https:\/\/github.com\/zumwald\/stateless-vsts-oauth\">github.com\/zumwald\/stateless-vsts-oauth<\/a><\/p>\n<p>Hiervoor dien je een App te registeren op Azure Devops. <a href=\"https:\/\/app.vsaex.visualstudio.com\/app\/register\">Ga naar Azure Devops Register oauth app<\/a><br \/>\nVul hier je bedrijfsnaam en contactgegevens in. Bij Application Information vul je bij Application website het adres waar de app gehost wordt. Dit adres moet publiek beschikbaar zijn. Verder de Authorization callback URL is het zelfde adres met als toevoeging <code>\/oauth-callback<\/code>. De Authorized scopes zijn Packaging (read and Write). Verder hoef je niks aan te vinken. Klik op Create Application om verder te gaan. De App ID en de Client Secret ben je nodig in volgende stappen. Om later bij dit overzicht te komen ga je naar <a href=\"https:\/\/app.vsaex.visualstudio.com\/me\">https:\/\/app.vsaex.visualstudio.com\/me<\/a><\/p>\n<p>Gebruik het volgende format om de environment variablen te zetten<\/p>\n<pre><code>\r\nCLIENT_ID : YOUR_CLIENT_ID_GUID\r\nCLIENT_SECRET : eyJ0eXAi....\r\nPORT : 8080\r\nWEBSITE_HOSTNAME : devopsauth.example.com\r\n<\/code><\/pre>\n<p>De App ID wordt ook gebruikt in de <i>preinstall.js<\/i> en het adres waar de oauth provider is gehost. Belangrijk is dat je deze hier ook in veranderd<\/p>\n","protected":false},"excerpt":{"rendered":"In deze blogpost ga ik het hebben over een technische oplossing waarbij je software onderdelen kunt delen tussen verschillende applicaties. Dit is alleen relevant als je meerdere applicaties hebt en hier onderdelen tussen wil delen. There is an English version of this blog post TL;DR; (Samenvatting) In deze blog koppelen we een private NPM-feed (Node&#8230; <a class=\"view-article\" href=\"https:\/\/qdraw.nl\/blog\/technologie\/een-eigen-npm-private-feed-maken-met-azure-devops\/\">Bekijk artikel<\/a>","protected":false},"author":2,"featured_media":6617,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[624],"tags":[2788,2789,2790],"class_list":["post-6615","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technologie","tag-azure","tag-azure-devops","tag-continuous-integration"],"_links":{"self":[{"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/posts\/6615","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/comments?post=6615"}],"version-history":[{"count":0,"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/posts\/6615\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/media\/6617"}],"wp:attachment":[{"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/media?parent=6615"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/categories?post=6615"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qdraw.nl\/blog\/wp-json\/wp\/v2\/tags?post=6615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}