La vie quotidienne d'un développeur est remplie de tâches monotones et répétitives. Heureusement, nous vivons à une époque d'intelligence pré-artificielle, ce qui signifie que les ordinateurs sont parfaits pour gérer des tâches ennuyeuses et qu'ils déjà se plaindre à ce sujet! Alors mettons en place une automatisation pour rendre notre quotidien un peu moins grindy.
Les tests et le déploiement sont deux éléments essentiels du développement Web. Avec une certaine automatisation, elles deviennent des solutions communément appelées "intégration continue" (CI) et "déploiement continu" (CD). L'aspect "continu" de ces solutions signifie que vos projets seront automatiquement testés et déployés, ce qui vous permettra de vous concentrer davantage sur l'écriture de code et moins sur son suivi sur des serveurs..
Dans ce didacticiel, nous allons configurer un serveur d’intégration continue bien connu, Jenkins, et le synchroniser avec GitHub afin qu’il exécute des tests chaque fois que du nouveau code est envoyé. Après cela, nous créerons une solution pour envoyer automatiquement ce code sur notre serveur d'applications, éliminant ainsi le besoin de déployer manuellement..
Nous utiliserons DigitalOcean pour créer rapidement et facilement des serveurs privés virtuels (VPS) basés sur le cloud pour héberger notre application et Jenkins..
Remarque: Ce didacticiel suppose que vous maîtrisez les bases de la ligne de commande et que votre ordinateur dispose de Git et de Node.js..
Avant de pouvoir tester ou déployer quoi que ce soit, nous avons besoin quelque chose pour tester et déployer. Permettez-moi de vous présenter notre sympathique application de test de tutoriel, appelée à juste titre "hello-jenkins".
Nous allons écrire une simple application Node.js pour répondre à nos besoins. Cela ne fera pas beaucoup plus que d'afficher une ligne de texte dans le navigateur, mais c'est juste assez de fonctionnalités pour garantir que nous avons correctement configuré l'intégration et le déploiement continus..
Puisque nous allons stocker notre projet sur GitHub, commençons par là. Connectez-vous à (ou créez) votre compte GitHub et créez un nouveau référentiel. Nommez-le "hello-jenkins" et donnez-lui la description suivante:
Mon super exemple d'application pour tester Jenkins.
Pour plus de simplicité, gardons le dépôt Publique. Allez-y et vérifiez la Initialiser ce référentiel avec un fichier README option et sélectionnez le Nœud option du Ajouter .gitignore la liste déroulante.
Clique le Créer un référentiel bouton, et notre repo sera prêt.
Clonons maintenant notre nouveau référentiel sur notre machine locale et parcourons-le:
git clone [email protected]:/hello-jenkins.git cd bonjour-jenkins
Voici quelle sera la structure finale de notre application:
├── .gitignore ├── app.js package.json README.md script │ déploiement │ │ test └── test └── test.js
Allons-y un à un. La première étape pour créer une application Node.js consiste à créer un package.json
fichier. Voici les nôtres:
"name": "hello-jenkins", "description": "hello jenkins test app", "version": "0.0.1", "private": true, "dépendances": "express": "3.12. 0 "," devDependencies ": " mocha ":" 1.20.1 "," supertest ":" 0.13.0 "
Sous les dépendances
nous avons ajouté Express
, que nous utiliserons pour créer notre application Node.js. Sous devDependencies
nous avons ajouté moka
et supertest
, ce qui nous aidera à écrire nos tests.
Maintenant que notre package.json
est défini, installez nos dépendances d'application en lançant:
npm installer
Il est temps d'écrire notre code d'application. Créer un fichier nommé app.js
et ajoutez ce qui suit:
var express = require ('express'); var app = express (); app.get ('/', fonction (req, res) res.send ('hello world');); app.listen (process.env.PORT || 5000); module.exports = app;
Décomposons notre application simple Node.js:
Express
lib nous avons spécifié dans notre package.json
.Express
créer un nouveau app.
app
pour répondre à toutes les demandes adressées à la racine de notre site (/
) avec le texte "hello world".app
sur quel port écouter les requêtes (process.env.PORT
fait référence à la variable d’environnement appelée "PORT", et si elle n’existe pas, on utilise par défaut le port 5000).app
disponible pour les autres modules Node.js via module.exports
(cela nous sera utile plus tard lorsque nous ajouterons des tests).C'est tout! Notre application est prête - exécutons-la:
noeud app.js
Ouvrez votre navigateur préféré et accédez à http: // localhost: 5000
, et vous devriez voir Bonjour le monde assis dans toute sa glorieuse simplicité.
Ce n'est pas l'application de test la plus excitante, mais ça marche! Allez-y et fermez notre application Node.js avec Ctrl-C, et passons.
Il est temps d'écrire un test pour notre application. Après tout, si nous n'avons rien à tester, Jenkins n'aura rien à faire.!
Créez un dossier appelé tester
, et créer un fichier nommé test.js
. Ajoutez le code suivant à test / test.js
:
var request = require ('supertest'); var app = require ('… /app.js'); decrire ('GET /', function () it ('répondre avec hello world', fonction (done) request (app) .get ('/'). expect ('hello world', done);); );
Comment fonctionne notre test? Premièrement, nous importons les deux supertest
lib et notre app
. Ensuite, nous ajoutons un seul test, décrivant ce qui devrait se passer quand un OBTENIR
demande frappe la racine de notre site. Nous disons à notre test de s’attendre à ce que la réponse soit "bonjour le monde", et si c’est le cas, le test réussit..
Pour exécuter le test, nous allons utiliser la bibliothèque Mocha. Nous avons installé Mocha dans le cadre de notre devDependencies
, Nous allons donc simplement exécuter une commande qui transmet notre fichier de test à Mocha et Mocha exécutera nos tests:
./node_modules/.bin/mocha ./test/test.js
Lorsque vous avez terminé, vous devriez voir un point vert accompagné d'informations indiquant qu'un test est réussi. Cela signifie que notre test a réussi! Mais taper cette commande encore et encore produira bientôt des crampes aux doigts et des contractions oculaires, alors créons un script d'aide pour le faire pour nous (souvenez-vous que les ordinateurs ne s'ennuient pas!).
Faire un nouveau répertoire appelé scénario
, et créer un fichier nommé tester
(notez qu'il n'y a pas d'extension). Ajouter ce qui suit à script / test
:
#! / bin / sh ./node_modules/.bin/mocha ./test/test.js
Nous avons maintenant un script shell pour exécuter cette ligne épineuse pour nous. Mais avant de pouvoir l'utiliser, nous devons lui accorder des autorisations d'exécution:
chmod + x script / test
Testons-le! Courir:
./ script / test
… Et vous devriez voir le même test de réussite qu'auparavant.
Bon, nous avons une application et un test qui fonctionnent, alors poussons notre nouveau code vers GitHub:
git add. git commit -m 'Ajouter une application de nœud' Maître d'origine git push
Et c'est tout - notre application est terminée et sur GitHub!
Nous avons une application captivante et captivante ("hello world" a une sorte de poésie, tu ne conviens pas?), Mais personne ne peut la voir! Changeons cela et faisons fonctionner notre application sur un serveur.
Pour nos besoins en hébergement, nous allons nous tourner vers DigitalOcean. DigitalOcean offre un moyen simple et rapide de mettre en place des instances cloud VPS, ce qui en fait l'hôte idéal pour notre espace de jeu CI / CD..
Connectez-vous à (ou inscrivez-vous à) DigitalOcean et cliquez sur le bouton Créer une gouttelette bouton. Pour le nom d'hôte, appelez-le "hello-jenkins". L'instance de taille la plus basse (512 Mo / 1/20 Go) répondra à nos besoins et sélectionnera la région géographique la plus proche de chez vous. Ensuite, nous devons choisir l'image utilisée pour créer le droplet. DigitalOcean propose une large sélection de systèmes d'exploitation, mais ce qui est bien, c'est qu'ils fournissent également des images spécialement adaptées à certains types d'applications..
Clique le Applications onglet, et sélectionnez le node-v0.10.29 sur Ubuntu 14.04 option - cela créera un serveur bien amorcé pour notre application Node.js.
Maintenant, cliquez Créer une gouttelette, et DigitalOcean va commencer à initialiser notre serveur.
Dans une minute, notre nouveau serveur devrait être prêt et vous devriez avoir reçu un courrier électronique avec les informations d'identification racine de votre serveur. Utilisons cette information pour vous connecter:
ssh [email protected]
Le mot de passe fourni dans le courrier électronique vous sera demandé, puis immédiatement forcé de créer un nouveau mot de passe (créez un mot de passe très fort et stockez-le dans un emplacement sécurisé, comme une base de données KeePass)..
En ce moment nous sommes connectés en tant que racine
, qui est le demi-dieu tout puissant de Linux-land. Mais lourde est la tête qui porte la couronne, et opérant comme racine
est généralement une mauvaise idée. La première chose à faire est donc de créer un nouvel utilisateur - appelons-le "app":
application adduser
Vous devrez fournir un mot de passe (un différentmot de passe fort, stocké en toute sécurité), puis il va poser une série de questions facultatives.
Nous voulons passer à notre app
utilisateur, mais avant de nous déconnecter, nous devons accorder à notre nouvel utilisateur sudo
privilèges afin qu'il puisse effectuer des actions administratives:
application usermod -a -G sudo
Maintenant fermez la connexion avec sortie
, puis connectez-vous en tant que app
:
ssh [email protected]
Vous serez invité pour le app
mot de passe de l'utilisateur, et alors vous devriez être connecté et bon aller.
Mettons notre application sur la machine. Grâce aux images d'application de DigitalOcean, notre machine est livrée avec Node.js et NPM préinstallés, mais nous devons toujours installer Git:
sudo apt-get install git
On vous demandera votre mot de passe (puisque vous utilisez sudo
), et vous devrez confirmer l'installation avec Y. Une fois que Git est installé, nous pouvons l’utiliser pour obtenir notre application à partir de GitHub..
Copiez l'URL de clone HTTPS à partir de la page GitHub du projet, puis clonez le référentiel dans votre dossier personnel sur le serveur:
cd git clone https://github.com//hello-jenkins.git
Maintenant, notre application est sur notre serveur, dans un dossier appelé "hello-jenkins". Naviguons dans cela:
cd bonjour-jenkins
La première chose à faire est d’installer les dépendances de l’application:
npm install --production
Une fois que cela est fait, nous pouvons exécuter notre application! Faites-le tourner avec:
noeud app.js
… Et accédez à l'adresse IP de votre serveur dans votre navigateur.
Mais attendez, ça ne marche pas! Quel est le problème?
Eh bien, rappelons cette ligne de code dans notre app.js
:
app.listen (process.env.PORT || 5000);
Pour l'instant, nous n'avons pas de PORT
variable d’environnement définie, notre application utilise par défaut le port 5000 et vous devez ajouter le port à l’adresse IP du navigateur (http: //YOUR.SERVER.IP.ADDRESS: 5000
).
Alors, comment pouvons-nous obtenir que notre application fonctionne comme prévu, sans avoir à spécifier le port? Eh bien, lorsqu'un navigateur émet une requête HTTP, il utilise par défaut le port 80. Il suffit donc de définir notre PORT
variable d'environnement à 80
.
Nous allons définir nos variables d'environnement dans le / etc / environment
fichier sur le serveur - ce fichier est chargé lors de la connexion et le jeu de variables sera disponible globalement pour toutes les applications. Ouvrez le fichier:
sudo nano / etc / environment
Vous verrez que maintenant le CHEMIN
est défini dans ce fichier. Ajoutez la ligne suivante après celle-ci:
PORT = 80
Puis tapez Ctrl-X, Y, et Entrer pour sauvegarder et quitter. Déconnexion du serveur (sortie
) et SSH dans (cela chargera la nouvelle variable d’environnement).
Une dernière petite tâche - exécuter une application sur le port 80 nécessite des privilèges root, mais exécuter noeud sudo app.js
ne préservera pas les variables d’environnement que nous avons définies. Pour résoudre ce problème, nous activerons nœud
avoir la capacité de fonctionner sur le port 80 sans sudo
:
sudo setcap cap_net_bind_service = + ep / usr / local / bin / node
Ça devrait le faire. Maintenant, lancez:
noeud app.js
Aller vers http: //YOUR.SERVER.IP.ADDRESS
, et vous verrez Bonjour le monde!
Actuellement, notre application ne s'exécute que pendant l'exécution du processus. Si nous la fermons, notre site n'est plus disponible. Ce dont nous avons besoin, c'est d'un moyen de garder notre application Node.js en marche en arrière-plan. Pour cela, nous utiliserons pour toujours. La première étape consiste à l'installer globalement:
sudo npm install -g pour toujours
Maintenant, au lieu de démarrer notre application avec noeud app.js
, nous allons utiliser:
pour toujours démarrer app.js
Notez que, au lieu du processus suspendu à l'exécution, il se termine immédiatement et vous redonne le contrôle. En effet, le serveur Node.js s'exécute en arrière-plan. Maintenant, nous n'avons plus à nous soucier de la fermeture de notre serveur lorsque nous nous déconnectons du serveur.. pour toujours
va même automatiquement redémarrer notre application s'il se produit un crash!
Pour arrêter notre application, nous pouvons exécuter:
arrêt pour toujours
Pour l'instant, continuons, et passons à Jenkins.
Nous hébergerons notre serveur Jenkins sur un droplet DigitalOcean séparé. Tournons ça maintenant.
Créez un nouveau droplet avec le nom d’hôte "jenkins-box". Choisir 512 Mo / 1/20 Go encore une fois, avec le même emplacement et le même type d’application (node-v0.10.29 sur Ubuntu 14.04) comme avec la gouttelette précédente.
Cliquez sur Créer une gouttelette et une fois terminé, utilisez les informations d'identification qui vous ont été envoyées pour vous connecter via SSH (vous devrez définir un nouveau mot de passe, comme avant).
Comme auparavant, nous devrions créer un nouvel utilisateur avant de faire autre chose. Cette fois, appelons ça admin
:
adduser admin usermod -a -G administrateur sudo
Déconnectez-vous en tant que racine
et vous connecter en tant que nouvellement créé admin
.
Comme Jenkins a pour objectif de récupérer notre projet et d'exécuter ses tests, notre machine doit disposer de toutes les dépendances du projet. Nous avons créé cette instance avec l'application Node.js de DigitalOcean. Node.js et npm sont donc déjà installés. Mais il faut encore installer Git:
sudo apt-get install git
La prochaine étape est Jenkins. Installer Jenkins est assez simple - nous aurons apt-get
faire tous les efforts lourds. Le seul problème est que nous devons ajouter un nouveau apte
référentiel avant de commencer l'installation:
sudo wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add - sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary /> /etc/apt/sources.list.d/jenkins.list' sudo apt-get update
Maintenant nous pouvons installer Jenkins:
sudo apt-get install jenkins
Une fois terminé, Jenkins fonctionnera et sera disponible sur le port 8080. Accédez à votre navigateur. Jenkins-Box
Adresse IP sur le port 8080 et vous verrez la page de destination Jenkins.
Clique le Gérer Jenkins lien, puis le Gérer les plugins lien. Basculer vers le Disponible onglet et recherchez le Plugin GitHub. Clique le Installer case à cocher, puis le Téléchargez maintenant et installez après le redémarrage bouton.
Cela initiera la séquence d'installation. Le plugin GitHub a plusieurs dépendances, donc plusieurs plugins seront installés. Au bas de la page, cochez la case Redémarrez Jenkins lorsque l'installation est terminée et qu'aucun travail n'est en cours d'exécution. - cela incitera Jenkins à redémarrer une fois les installations terminées.
Une fois que Jenkins a redémarré, il est temps d'ajouter notre projet. Clique le Nouvel article bouton. Utilisez "hello-jenkins" pour le nom de l'élément, sélectionnez Construire un projet de logiciel libre, et cliquez sur le bouton intitulé D'accord.
Une fois le projet configuré, vous vous retrouverez sur la page des paramètres du projet. Ajoutez l'URL GitHub de notre projet au Projet GitHub boîte:
https://github.com// bonjour-jenkins
Ensuite, sélectionnez le Git option sous Gestion du code source. Dans les champs nouvellement apparus, ajoutez l’URL du dépôt de notre projet GitHub au URL du référentiel champ:
https://github.com//hello-jenkins.git
Faites défiler un peu plus bas et cliquez sur la case pour activer Construire quand un changement est poussé vers GitHub. Avec cette option cochée, notre projet se construira chaque fois que nous pousserons vers notre dépôt GitHub. Bien entendu, Jenkins doit savoir quoi faire lorsqu'il exécute une construction. Clique le Ajouter une étape de construction liste déroulante et sélectionnez Exécuter shell. Cela fera un Commander dialogue disponible, et ce que nous mettons dans ce dialogue sera exécuté quand une construction commencera. Ajoutez ce qui suit:
npm install ./script/test
Notre construction se compose de deux étapes. Tout d'abord, il installe nos dépendances d'application. Puis il exécute ./ script / test
exécuter nos tests.
Cliquez sur "sauvegarder".
Pour terminer la configuration de l’intégration, rendez-vous sur le dépôt GitHub, puis cliquez sur Réglages. Clique le Webhooks et services onglet, puis le Ajouter un service menu déroulant. Sélectionnez le Jenkins (plugin GitHub) un service.
Ajouter ce qui suit comme Jenkins hook url:
http: //JENKINS.SERVER.IP.ADDRESS: 8080 / github-webhook /
Cliquez sur Ajouter un service. Notre projet est maintenant prêt pour son premier test d'intégration continue!
Donnons-lui quelque chose à tester. S'ouvrir app.js
localement et changez cette ligne:
res.send ('bonjour le monde');
… pour ça:
res.send ('bonjour jenkins');
Enregistrez le changement et validez-le:
git add. git commit -m 'Passez à bonjour Jenkins'
Maintenant, gardez un oeil sur Jenkins pendant que vous appliquez vos modifications à GitHub:
maître d'origine git push
Après une seconde ou deux, vous devriez voir qu'un nouveau travail a été lancé pour notre bonjour-jenkins
projet à Jenkins - nos travaux d'intégration continue!
Mais… le travail échoue! Pourquoi?
Eh bien, rappelez-vous que notre test s'attend à ce que l'appel racine retourne "hello world", mais nous l'avons changé en "hello jenkins". Alors changeons les attentes de notre test. Échangez cette ligne:
request (app) .get ('/'). expect ('hello world', terminé);
… Avec cette ligne:
request (app) .get ('/'). expect ('hello jenkins', c'est fait);
Sauvegarder, valider et pousser à nouveau:
git add. git commit -m 'Basculez le test sur hello jenkins' git push origin master
Regardez Jenkins - une fois encore, vous verrez une compilation automatiquement démarrée et cette fois, elle réussit!
C'est le flux de l'intégration continue. Le serveur de test teste en permanence tout nouveau code que vous envoyez afin que vous soyez rapidement informé de tout test ayant échoué..
Bon, nous testons automatiquement nos modifications, mais qu'en est-il du déploiement de ces modifications? aucun problème!
Si vous avez surveillé de près, vous avez sans doute remarqué qu'il nous manque quelque chose dans notre projet jusqu'à présent. Dans la structure du projet au début du tutoriel, il existe une script / déployer
fichier, mais nous n’avons pas encore créé de fichier de ce type. Eh bien, maintenant nous allons!
Mais d'abord, discutons du fonctionnement du déploiement. Notre script (exécuté par l'étape de génération de Jenkin) va se connecter au serveur d'applications via SSH, accéder à notre dossier d'applications, mettre à jour l'application, puis redémarrer le serveur. Avant d'écrire notre script de déploiement, nous devons gérer la manière dont notre serveur Jenkins utilisera SSH dans notre serveur d'applications..
Jusqu'à présent, nous avons accédé à nos serveurs en saisissant manuellement les mots de passe, mais cette approche ne fonctionnera pas pour les scripts automatisés. A la place, nous allons créer une clé SSH que le serveur Jenkins utilisera pour s’authentifier auprès du serveur d’applications..
Lorsque Jenkins installe, il crée un nouvel utilisateur appelé Jenkins
. Jenkins exécute toutes les commandes avec cet utilisateur, nous devons donc générer notre clé avec le Jenkins
utilisateur pour qu'il y ait un accès approprié.
Bien connecté en tant que admin
sur le Jenkins-Box
, exécuter ce qui suit:
sudo su
Fournir votre admin
mot de passe, et ça va vous passer à la racine
utilisateur. Puis exécutez:
su Jenkins
Maintenant, vous agissez en tant que Jenkins
utilisateur. Générez une clé SSH:
ssh-keygen -t rsa
Enregistrez le fichier à l’emplacement par défaut (/var/lib/jenkins/.ssh/id_rsa
), et assurez-vous de ne pas utiliser de phrase secrète (sinon, l'accès SSH nécessitera un mot de passe et ne fonctionnera pas s'il est automatisé).
Ensuite, nous devons copier la clé publique créée. Lance ça:
cat ~ / .ssh / id_rsa.pub
… Et copiez le résultat. Ce devrait être une longue chaîne commençant par "ssh-rsa" et se terminant par "jenkins @ jenkins-box".
Déconnectez-vous de Jenkins-Box
et reconnectez-vous à notre serveur d'applications (bonjour-jenkins
) comme app
utilisateur. Nous devons créer un fichier nommé clés_autorisées
dans notre app
utilisateurs.ssh
dossier:
mkdir ~ / .ssh nano ~ / .ssh / registered_keys
Collez la clé publique que vous avez copiée, puis Ctrl-X/Y/Entrer pour sauvegarder et quitter. Pour que ce fichier fonctionne correctement, il doit disposer d'autorisations strictes:
chmod 700 ~ / .ssh chmod 600 ~ / .ssh / *
Retournez au Jenkins
boîte, passer à la Jenkins
utilisateur et vérifiez que vous pouvez vous connecter à notre serveur d'applications sans entrer de mot de passe:
ssh [email protected]
Vous devez vous connecter avec succès au serveur d'applications sans avoir à entrer le mot de passe. Une fois cela établi, nous pouvons maintenant nous tourner vers le déploiement.
Créer un fichier dans le scénario
dossier nommé déployer
(notez qu'il n'y a pas d'extension). Ajouter ce qui suit à script / déployer
:
#! / bin / sh ssh [email protected] <Passons en revue ceci:
- Tout d'abord, nous nous connectons au serveur d'applications en tant que
app
utilisateur.- Ensuite, nous naviguons dans notre dossier d'applications et mettons à jour la dernière version de GitHub..
- Après cela, nous installons nos dépendances.
- Enfin, une fois notre code d’application mis à jour, nous redémarrons notre serveur avec
recommencer à jamais
.Rendre notre nouveau fichier script exécutable:
chmod + x script / deployAjoutez ce nouveau fichier et validez-le:
git add. git commit -m 'Ajouter un script de déploiement'Mais ne poussons pas tout à fait encore. Tout d’abord, revenez à la configuration de notre projet dans Jenkins et faites défiler jusqu’à la commande build. Ajoutez cette nouvelle ligne à la fin de celle-ci:
./ script / deploySauvez le projet Jenkins.
Maintenant, allez de l'avant et appuyez sur GitHub, et regardez comment Jenkins se construit automatiquement. Une fois la construction terminée (elle devrait réussir), naviguez sur votre navigateur jusqu'à l'adresse IP de notre serveur d'applications. Presto! Notre passionnant "hello world" a été remplacé par un "hello jenkins" exaltant!
Notre application est maintenant déployée en permanence!
Tout va bien qui s'automatise bien
Phew. C'était tout le trajet!
Au final, nous avons réussi à mettre en place une intégration continue et déploiement continu, ce qui offre un très bon niveau d'automatisation dans nos vies de développeurs quotidiennes. N'oubliez pas que les ordinateurs ne s'ennuient pas. Par conséquent, même s'ils gèrent les tests et les déploiements, vous êtes libre de faire des choses importantes, comme vous faire un sandwich. Alors va faire ce sandwich et mange-le comme un champion de l'automatisation!