La vita quotidiana di uno sviluppatore è piena di compiti monotoni e ripetitivi. Fortunatamente, viviamo in un'età dell'intelligenza pre-artificiale, il che significa che i computer sono bravi a gestire le faccende noiose e difficilmente mai lamentatevi! Quindi impostiamo un po 'di automazione per rendere la nostra routine quotidiana un po' meno grindy.
Test e implementazione sono due elementi fondamentali dello sviluppo web. Con un po 'di automazione integrata, diventano soluzioni comunemente chiamate "continuous integration" (CI) e "continuous deployment" (CD). L'aspetto "continuo" di queste soluzioni significa che i tuoi progetti verranno automaticamente testati e implementati, consentendoti di concentrarti maggiormente sulla scrittura di codice e meno sul herding sui server.
In questo tutorial, creeremo un popolare server di integrazione continua chiamato Jenkins e lo sincronizzeremo con GitHub in modo che esegua i test ogni volta che viene inviato un nuovo codice. Dopodiché, creeremo una soluzione per spingere automaticamente quel codice sul nostro server delle app, eliminando la necessità di una distribuzione manuale.
Useremo DigitalOcean per creare rapidamente e facilmente server virtuali virtuali (VPS) basati su cloud per ospitare la nostra app e Jenkins.
Nota: questo tutorial presume che tu abbia una conoscenza di base sul funzionamento della riga di comando e che sul tuo computer siano installati Git e Node.js.
Prima di poter testare o implementare qualsiasi cosa, abbiamo bisogno qualcosa per testare e distribuire. Permettetemi di presentarvi la nostra amichevole app di tutorial test, giustamente chiamata "ciao-jenkins".
Scriveremo una semplice app Node.js per soddisfare i nostri scopi. Non farà molto di più che visualizzare una riga di testo nel browser, ma questa è solo una funzionalità sufficiente per garantire che abbiamo impostato correttamente l'integrazione continua e la distribuzione continua.
Dato che archiviamo il nostro progetto su GitHub, iniziamo da lì. Accedi a (o crea) il tuo account GitHub e crea un nuovo repository. Chiamalo "ciao-jenkins" e dagli la seguente descrizione:
La mia app super campione per testare Jenkins.
Per semplicità, continuiamo il repository Pubblico. Vai avanti e controlla il Inizializza questo repository con un README opzione e selezionare il Nodo opzione dal Aggiungi .gitignore menu `A tendina.
Clicca il Crea repository pulsante, e il nostro pronti contro termine sarà pronto.
Ora cloniamo il nostro nuovo repository sul nostro computer locale e naviga in esso:
git clone [email protected]:/hello-jenkins.git cd ciao-jenkins
Ecco quale sarà la struttura finale della nostra app:
├── .gitignore ├── app.js ├── package.json ├── README.md ├── script │ ├── distribuisci │ └── test └── test └── test.js
Affrontiamo questo uno per uno. Il primo passo per creare qualsiasi app Node.js è creare un package.json
file. Ecco la nostra:
"name": "hello-jenkins", "description": "hello jenkins test app", "version": "0.0.1", "private": true, "dependencies": "express": "3.12. 0 "," devDependencies ": " mocha ":" 1.20.1 "," supertest ":" 0.13.0 "
Sotto dipendenze
abbiamo aggiunto esprimere
, che utilizzeremo per aiutare a creare la nostra app Node.js. Sotto devDependencies
abbiamo aggiunto moca
e Supertest
, entrambi i quali ci aiuteranno a scrivere i nostri test.
Ora che il nostro package.json
è definito, installa le nostre dipendenze dell'app eseguendo:
installazione di npm
È tempo di scrivere il nostro codice app. Crea un file chiamato app.js
e aggiungi il seguente:
var express = require ('express'); var app = express (); app.get ('/', function (req, res) res.send ('hello world');); app.listen (process.env.PORT || 5000); module.exports = app;
Analizziamo la nostra semplice app Node.js:
esprimere
lib abbiamo specificato nel nostro package.json
.esprimere
per creare un nuovo App.
App
rispondere a tutte le richieste che colpiscono alla radice del nostro sito (/
) con il testo "ciao mondo".App
su quale porta ascoltare le richieste (process.env.PORT
si riferisce alla variabile d'ambiente chiamata "PORT", e se non esiste, preferiamo invece la porta 5000).App
disponibile per altri moduli Node.js tramite module.exports
(questo ti tornerà utile più tardi quando aggiungeremo dei test).Questo è tutto! La nostra app è pronta - corriamola:
nodo app.js
Apri il tuo browser preferito e naviga verso http: // localhost: 5000
, e dovresti vedere Ciao mondo seduto in tutta la sua gloriosa semplicità.
Non è l'app di test più eccitante, ma funziona! Vai avanti e chiudi la nostra app Node.js con Ctrl-C, e andiamo avanti.
È tempo di scrivere un test per la nostra app - dopotutto, se non abbiamo nulla da testare, allora Jenkins non avrà nulla da fare!
Crea una cartella chiamata test
, e in esso crea un file chiamato test.js
. Aggiungere il seguente codice a test / test.js
:
var request = require ('supertest'); var app = require ('... /app.js'); define ('GET /', function () it ('rispondi con Hello world', function (done) request (app) .get ('/'). expect ('hello world', done);); );
Come funziona il nostro test? Innanzitutto, importiamo entrambi Supertest
lib e nostro App
. Quindi aggiungiamo un singolo test, descrivendo cosa dovrebbe accadere quando a OTTENERE
richiesta colpisce la radice del nostro sito. Diciamo al nostro test che aspettiamo che la risposta sia "ciao mondo", e se lo è, passa il test.
Per eseguire il test, useremo la libreria Mocha. Abbiamo installato Mocha come parte del nostro devDependencies
, quindi eseguiremo semplicemente un comando che passa il nostro file di test a Mocha e Mocha eseguirà i nostri test:
./node_modules/.bin/mocha ./test/test.js
Al termine, dovresti vedere un punto verde insieme a informazioni che dicono che è passato un test. Ciò significa che il nostro test ha avuto successo! Ma digitando quel comando più e più volte produrrà presto crampi alle dita e contrazioni agli occhi, quindi facciamo uno script di aiuto per farlo per noi (ricorda, i computer non si annoiano!).
Crea una nuova directory chiamata copione
, e in esso crea un file chiamato test
(notare che non c'è estensione). Aggiungi il seguente a script / Test
:
#! / bin / sh ./node_modules/.bin/mocha ./test/test.js
Lì - ora abbiamo uno script di shell per eseguire quella linea gnarly per noi. Ma prima che possiamo usarlo, dobbiamo concedergli autorizzazioni eseguibili:
chmod + x script / test
Proviamoci! Correre:
./ Script / test
... e dovresti vedere lo stesso test di passaggio di prima.
Bene, abbiamo un'app funzionante e un test di lavoro, quindi spingiamo il nostro nuovo codice su GitHub:
aggiungi git. git commit -m 'Aggiungi app nodo' git push origine master
E questo è tutto: la nostra app è fatta e su GitHub!
Abbiamo un'app avvincente e accattivante ("ciao mondo" ha una sorta di poesia, non sei d'accordo?), Ma nessuno può vederlo! Cambiamo e facciamo funzionare la nostra app su un server.
Per le nostre esigenze di hosting, ci rivolgeremo a DigitalOcean. DigitalOcean fornisce un modo semplice e veloce per creare istanze cloud VPS, rendendolo l'ospite perfetto per il nostro parco giochi CI / CD.
Accedi a (o registrati) DigitalOcean e fai clic su Crea Droplet pulsante. Per il nome host, chiamalo "ciao-jenkins". L'istanza di dimensione più bassa (512/1 / 20GB) soddisferà le nostre esigenze e selezionerà la regione geografica più vicina a te. Successivamente, dobbiamo scegliere l'immagine utilizzata per creare il droplet. DigitalOcean offre una vasta gamma di sistemi operativi tra cui scegliere, ma ciò che è veramente bello è che forniscono anche immagini su misura per determinati tipi di applicazioni.
Clicca il applicazioni scheda e selezionare il node-v0.10.29 su Ubuntu 14.04 opzione - questo creerà un server che è ben avviato per la nostra app Node.js.
Ora fai clic Crea Droplet, e DigitalOcean inizierà a inizializzare il nostro server.
Entro un minuto il nostro nuovo server dovrebbe essere pronto e dovresti aver ricevuto un'e-mail con le credenziali di root del tuo server. Utilizziamo queste informazioni per accedere:
ssh [email protected]
Ti verrà richiesta la password fornita nell'e-mail, quindi dovrai immediatamente creare una nuova password (renderla qualcosa di molto forte e memorizzarla in un luogo sicuro, come un database KeePass).
In questo momento siamo registrati come radice
, che è l'onnipotente semidio di Linux-land. Ma pesante è la testa che indossa la corona e opera come radice
è generalmente una cattiva idea. Quindi la prima cosa che vorremmo fare è creare un nuovo utente - chiamiamolo "app":
app adduser
Dovrai fornire una password (a diversopassword sicura, archiviata in modo sicuro), quindi richiederà una serie di domande opzionali.
Vogliamo passare al nostro App
utente, ma prima di uscire, dobbiamo concedere il nostro nuovo utente sudo
privilegi in modo che abbia la capacità di eseguire azioni amministrative:
usermod -a -G app sudo
Ora chiudi la connessione con Uscita
, e quindi connetti come App
:
ssh [email protected]
Ti verrà richiesto il App
la password dell'utente, quindi è necessario effettuare l'accesso e andare.
Portiamo la nostra app sulla macchina. Grazie alle immagini dell'applicazione di DigitalOcean, la nostra macchina viene fornita con Node.js e npm preinstallati, ma dobbiamo ancora installare Git:
sudo apt-get install git
Ti verrà richiesta la tua password (dal momento che stai usando sudo
), e dovrai confermare l'installazione con Y. Una volta installato Git, possiamo utilizzarlo per ottenere la nostra app da GitHub.
Copia l'URL clone HTTPS dalla pagina GitHub del progetto, quindi clona il repository nella tua cartella Inizio sul server:
cd git clone https://github.com//hello-jenkins.git
Ora la nostra app è sul nostro server, in una cartella chiamata "ciao-jenkins". Passiamo a questo:
cd ciao-jenkins
La prima cosa che dobbiamo fare è installare le dipendenze dell'app:
installazione di npm - produzione
Una volta fatto, possiamo eseguire la nostra app! Spin it up con:
nodo app.js
... e accedi all'indirizzo IP del tuo server nel browser.
Ma aspetta, non funziona! Qual è l'accordo?
Bene, ricordiamo questa linea di codice nella nostra app.js
:
app.listen (process.env.PORT || 5000);
In questo momento, non abbiamo un PORTA
variabile di ambiente impostata, quindi la nostra app è quella predefinita per la porta 5000 ed è necessario aggiungere la porta all'indirizzo IP nel browser (http: //YOUR.SERVER.IP.ADDRESS: 5000
).
Quindi, come possiamo far funzionare la nostra app come previsto, senza dover specificare la porta? Bene, quando un browser fa una richiesta HTTP, ha come valore predefinito la porta 80. Quindi dobbiamo solo impostare la nostra PORTA
variabile di ambiente a 80
.
Imposteremo le nostre variabili di ambiente nel / Etc / environment
file sul server - questo file viene caricato all'accesso e le variabili impostate saranno disponibili globalmente su tutte le applicazioni. Apri il file:
sudo nano / etc / environment
Lo vedrai proprio ora SENTIERO
è impostato in questo file. Aggiungi la seguente riga dopo:
PORT = 80
Quindi digita Ctrl-X, Y, e accedere per salvare ed uscire. Disconnettersi al server (Uscita
) e SSH di nuovo (questo caricherà la nuova variabile di ambiente).
Un ultimo piccolo problema: l'esecuzione di un'app sulla porta 80 richiede i privilegi di root, ma l'esecuzione sudo node app.js
non conserverà le variabili di ambiente che abbiamo impostato. Per ovviare a questo, abiliteremo nodo
avere la possibilità di funzionare sulla porta 80 sans sudo
:
sudo setcap cap_net_bind_service = + ep / usr / local / bin / node
Questo dovrebbe farlo. Ora esegui:
nodo app.js
Navigare verso http: //YOUR.SERVER.IP.ADDRESS
, e vedrai Ciao mondo!
Al momento la nostra app funziona solo mentre stiamo eseguendo il processo - se lo chiudiamo, il nostro sito non è più disponibile. Ciò di cui abbiamo bisogno è un modo per mantenere la nostra app Node.js in esecuzione in background. Per quello, useremo per sempre. Il primo passo è installarlo globalmente:
sudo npm install -g per sempre
Ora, invece di avviare la nostra app con nodo app.js
, useremo:
inizia per sempre app.js
Si noti che al posto del processo che pende dall'esecuzione, si esce immediatamente e si ottiene il controllo posteriore. Questo perché il server Node.js è in esecuzione in background. Ora non dobbiamo preoccuparci che il nostro server si spenga quando effettuiamo il logout del server. per sempre
riavvierà automaticamente la nostra app anche in caso di crash!
Per interrompere la nostra app, possiamo eseguire:
per sempre
Per ora, continuiamo a correre e passiamo a Jenkins.
Ospiteremo il nostro server Jenkins su un droplet DigitalOcean separato. Facciamo girare questo ora.
Crea un nuovo droplet con il nome host "jenkins-box". Scegliere 512/1 / 20GB di nuovo, insieme alla stessa posizione e allo stesso tipo di applicazione (node-v0.10.29 su Ubuntu 14.04) come con la gocciolina precedente.
Clic Crea Droplet e una volta terminato, usa le credenziali inviate via email per accedere tramite SSH (dovrai impostare una nuova password, proprio come prima).
Come prima, dovremmo creare un nuovo utente prima di fare qualsiasi altra cosa. Questa volta chiamiamolo Admin
:
adduser admin usermod -a -G sudo admin
Disconnettersi come radice
e accedere come appena creato Admin
.
Poiché lo scopo di Jenkins è recuperare il nostro progetto ed eseguire i suoi test, la nostra macchina deve avere tutte le dipendenze del progetto installate. Abbiamo trasformato questa istanza con l'applicazione Node.js di DigitalOcean, quindi Node.js e npm sono già installati. Ma dobbiamo ancora installare Git:
sudo apt-get install git
Il prossimo è Jenkins. Installare Jenkins è abbastanza semplice, lo faremo apt-get
fai tutto il sollevamento pesante. L'unico problema è che dobbiamo aggiungere un nuovo adatto
repository prima di avviare l'installazione:
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
Ora possiamo installare Jenkins:
sudo apt-get install jenkins
Una volta completato, Jenkins sarà in esecuzione e disponibile sulla porta 8080. Navigare nel browser in Jenkins-box
Indirizzo IP sulla porta 8080 e vedrai la pagina di destinazione di Jenkins.
Clicca il Gestisci Jenkins link, e quindi il Gestisci i plugin collegamento. Passare al A disposizione scheda e cerca il GitHub Plugin. Clicca il Installare checkbox, e poi il Scarica ora e installa dopo il riavvio pulsante.
Questo avvierà la sequenza di installazione. Il plugin GitHub ha diverse dipendenze, quindi verranno installati più plug-in. In fondo alla pagina, controlla il Riavvia Jenkins quando l'installazione è completa e nessun lavoro è in esecuzione - questo richiederà a Jenkins di riavviarsi una volta completate le installazioni.
Una volta che Jenkins è stato riavviato, è tempo di aggiungere il nostro progetto. Clicca il Nuovo oggetto pulsante. Usa "ciao-jenkins" per il nome dell'oggetto, seleziona Costruisci un progetto software gratuito, e fare clic sul pulsante etichettato ok.
Una volta impostato il progetto, ti troverai nella pagina delle impostazioni del progetto. Aggiungi l'URL GitHub del nostro progetto al Progetto GitHub scatola:
https://github.com// Hello-Jenkins
Quindi, selezionare il Idiota opzione sotto Gestione del codice sorgente. Nei campi appena apparsi, aggiungi l'URL al nostro repository di progetto GitHub al URL del repository campo:
https://github.com//hello-jenkins.git
Scorri un po 'più in basso e fai clic sulla casella per abilitare Costruisci quando una modifica viene inviata a GitHub. Con questa opzione selezionata, il nostro progetto si costruirà ogni volta che effettueremo il push del nostro repo GitHub. Certo, abbiamo bisogno che Jenkins sappia cosa fare quando esegue una build. Clicca il Aggiungi step di costruzione menu a discesa e selezionare Esegui shell. Questo farà un Comando dialogo disponibile, e ciò che inseriremo in questo dialogo verrà eseguito quando una costruzione inizia. Aggiungi il seguente:
npm install ./script/test
La nostra build consiste in due passaggi. Innanzitutto, installa le nostre dipendenze dell'app. Quindi esegue ./ Script / test
per eseguire i nostri test.
Clicca "Salvare".
Per completare la configurazione dell'integrazione, andare al repository GitHub e fare clic su impostazioni. Clicca il Webhooks e servizi scheda, quindi il Aggiungi servizio cadere in picchiata. Seleziona il Jenkins (plugin GitHub) servizio.
Aggiungi il seguente come il URL di Jenkins:
http: //JENKINS.SERVER.IP.ADDRESS: 8080 / github-webhook /
Clic Aggiungi servizio. Il nostro progetto è ora pronto per il suo primo test di integrazione continua!
Diamo qualcosa da testare. Aprire app.js
localmente e cambia questa linea:
res.send ('ciao mondo');
… a questo:
res.send ('ciao jenkins');
Salva la modifica e confermala:
aggiungi git. git commit -m 'Passa a ciao jenkins'
Ora tieni d'occhio Jenkins mentre trasmetti le tue modifiche a GitHub:
git push origin master
Dopo un secondo o due, dovresti vedere che è stato avviato un nuovo lavoro per il nostro Hello-Jenkins
progetto in Jenkins - la nostra integrazione continua funziona!
Ma ... il lavoro fallisce! Perché?
Bene, ricorda che il nostro test si aspetta che la chiamata di root restituisca "Ciao mondo", ma l'abbiamo modificata in "ciao jenkins". Quindi cambiamo le aspettative del nostro test. Scambia questa riga:
richiesta (app) .get ('/'). expect ('ciao mondo', fatto);
... con questa linea:
richiesta (app) .get ('/'). expect ('ciao jenkins', fatto);
Salva, conferma e invia nuovamente:
aggiungi git. git commit -m 'Passa test al master di origine git push di hello jenkins
Guarda Jenkins: ancora una volta vedrai che una build viene avviata automaticamente e questa volta ha successo!
Questo è il flusso di integrazione continua. Il server di test sta continuamente testando qualsiasi nuovo codice che si preme per essere rapidamente informato di eventuali test non riusciti.
Bene, quindi stiamo testando automaticamente le nostre modifiche, ma per quanto riguarda la distribuzione di tali modifiche? Nessun problema!
Se hai osservato da vicino, hai sicuramente notato che manca qualcosa dal nostro progetto fino ad ora. Nella struttura del progetto all'inizio del tutorial, esiste a script / deploy
file, ma non abbiamo ancora creato alcun file di questo tipo. Bene, ora lo faremo!
Ma prima, discutiamo di come funzionerà la distribuzione. Il nostro script (gestito dal passo di costruzione di Jenkin) accederà al server dell'app tramite SSH, naviga nella nostra cartella app, aggiorna l'app e quindi riavvia il server. Prima di scrivere il nostro script di distribuzione, dobbiamo gestire il modo in cui il nostro server Jenkins eseguirà SSH nel nostro server delle applicazioni.
Finora, abbiamo accesso ai nostri server inserendo manualmente le password, ma questo approccio non funziona per gli script automatici. Invece, creeremo una chiave SSH che il server Jenkins utilizzerà per autenticarsi con il server dell'app.
Quando installa Jenkins, crea un nuovo utente chiamato Jenkins
. Jenkins esegue tutti i comandi con questo utente, quindi abbiamo bisogno di generare la nostra chiave con il Jenkins
utente in modo che abbia l'accesso appropriato ad esso.
Mentre sei loggato come Admin
sul Jenkins-box
, eseguire quanto segue:
sudo su
Fornisci il tuo Admin
password, e ti passerà al radice
utente. Quindi eseguire:
su jenkins
Ora ti stai comportando come il Jenkins
utente. Genera una chiave SSH:
ssh-keygen -t rsa
Salva il file nel percorso predefinito (/var/lib/jenkins/.ssh/id_rsa
), e assicurati di non usare una passphrase (altrimenti l'accesso SSH richiederà una password e non funzionerà automaticamente).
Successivamente, dobbiamo copiare la chiave pubblica che è stata creata. Esegui questo:
cat ~ / .ssh / id_rsa.pub
... e copia l'output. Dovrebbe essere una lunga stringa che inizia con "ssh-rsa" e termina con "jenkins @ jenkins-box".
Esci Jenkins-box
e accedere nuovamente al nostro server delle applicazioni (Hello-Jenkins
) come il App
utente. Dobbiamo creare un file chiamato authorized_keys
nel nostro App
l'utente.SSH
cartella:
mkdir ~ / .ssh nano ~ / .ssh / authorized_keys
Incolla la chiave pubblica che hai copiato e poi Ctrl-X/Y/accedere per salvare ed uscire. Affinché questo file funzioni correttamente, è necessario disporre di autorizzazioni rigorose su di esso:
chmod 700 ~ / .ssh chmod 600 ~ / .ssh / *
Tornate al Jenkins
casella, passare al Jenkins
utente e verificare che sia possibile accedere al nostro server app senza immettere una password:
ssh [email protected]
È necessario accedere correttamente al server dell'app senza inserire la password. Con quello stabilito, possiamo ora passare alla distribuzione.
Crea un file nel copione
cartella denominata schierare
(notare che non c'è estensione). Aggiungi il seguente a script / deploy
:
#! / bin / sh ssh [email protected] <Passiamo attraverso questo:
- Innanzitutto, accediamo al server dell'app come
App
utente.- Quindi navighiamo nella nostra cartella dell'app e aggiorniamo l'ultima versione da GitHub.
- Successivamente, installiamo le nostre dipendenze.
- Infine, una volta aggiornato il codice dell'app, riavviamo il nostro server con
per sempre riavvio
.Rendi eseguibile il nostro nuovo file script:
chmod + x script / deployAggiungi questo nuovo file e confermalo:
aggiungi git. git commit -m 'Aggiungi script di distribuzione'Ma non spingiamo ancora abbastanza. Per prima cosa, torna alla configurazione del nostro progetto in Jenkins e scorri fino al comando di compilazione. Aggiungi questa nuova linea alla fine di esso:
./ Script / deploySalva il progetto Jenkins.
Ora vai avanti e spingi su GitHub, e osserva come Jenkins costruisce automaticamente. Una volta che la compilazione è terminata (dovrebbe avere successo), naviga il tuo browser sull'IP del nostro server delle applicazioni. Presto! Il nostro entusiasmante "ciao mondo" è stato sostituito da un esilarante "ciao jenkins"!
La nostra app viene ora distribuita continuamente!
Va bene che si automatizza bene
Uff. E 'stata abbastanza la corsa!
Alla fine, abbiamo impostato con successo sia l'integrazione continua e implementazione continua, che fornisce un livello molto elevato di automazione nella nostra vita quotidiana degli sviluppatori. Ricorda, i computer non si annoiano, quindi mentre gestiscono i test e la distribuzione, sei libero di fare cose importanti, come prepararti un panino. Quindi vai a fare quel sandwich e mangiarlo come un campione d'automazione!