Sette opp kontinuerlig integrasjon og kontinuerlig distribusjon med Jenkins

Det daglige livet til en utvikler er fylt med monotone og repeterende oppgaver. Heldigvis lever vi i en pre-artificial intelligence-alder, noe som betyr at datamaskiner er gode til å håndtere kjedelige gjerninger og de knapt noensinne klage på det! Så la oss sette opp litt automatisering for å gjøre vår daglige grind litt mindre grindy.

Testing og distribusjon er to integrerte elementer i webutvikling. Med litt automatisering blandet inn, blir de løsninger som kalles kontinuerlig integrasjon (CI) og "kontinuerlig distribusjon" (CD). Det "kontinuerlige" aspektet av disse løsningene betyr at prosjektene dine blir testet og distribuert automatisk, slik at du kan fokusere mer på å skrive kode og mindre på å herding den på servere.

I denne veiledningen vil vi sette opp en populær kontinuerlig integrasjonsserver kalt Jenkins og synkronisere den med GitHub, slik at den vil kjøre tester hver gang ny kode trykkes. Deretter lager vi en løsning for å automatisk skyve den koden til vår appserver, og eliminerer behovet for å distribuere manuelt.

Vi bruker DigitalOcean for raskt og enkelt å lage skybaserte virtuelle private servere (VPS) for å være vert for vår app og Jenkins.

Merk: Denne opplæringen forutsetter at du har en grunnleggende kunnskap om å jobbe på kommandolinjen, og at maskinen din har både Git og Node.js installert.

Vår Supereksempel App

Før vi kan teste eller distribuere noe, trenger vi noe å teste og distribuere. Tillat meg å introdusere deg til vår vennlige opplæringsprøveapp, aptly kalt "hei-jenkins".

Vi skal skrive en enkel Node.js app for å passe våre formål. Det vil ikke gjøre mye mer enn å vise en tekstlinje i nettleseren, men det er bare nok funksjonalitet for å sikre at vi har satt opp kontinuerlig integrasjon og kontinuerlig distribusjon.

Git Up på GitHub

Siden vi lagrer vårt prosjekt på GitHub, la oss begynne der. Logg inn på (eller opprett) GitHub-kontoen din og opprett et nytt lager. Gi det navnet "hello-jenkins" og gi den følgende beskrivelse:

My super sample app for å teste ut Jenkins.

For enkelhet, la oss holde repoen Offentlig. Gå videre og sjekk Initialiser dette depotet med et README alternativet, og velg node alternativ fra Legg til .gitignore nedtrekksliste.

Klikk på Opprett arkiv knappen, og vår repo vil være klar.

La oss nå klone vårt nye lager ned til vår lokale maskin og navigere inn i den:

git klone [email protected]:/hello-jenkins.git cd hei-jenkins

Vår Node App

Her er hva den endelige strukturen av appen vår vil være:

├── .gitignore ├── app.js ├── package.json ├── README.md ├── script │ ├─ - distribuere │ └── test └── test └── test.js

La oss takle denne en-for-en. Det første trinnet for å bygge noen Node.js app er å lage en package.json fil. Her er vår:

"navn": "hello-jenkins", "beskrivelse": "hallo jenkins test app", "versjon": "0.0.1", "privat": true, "avhengigheter": "express": "3.12. 0 "," devDependencies ": " mocha ":" 1.20.1 "," supertest ":" 0.13.0 "

Under avhengig vi har lagt til uttrykke, som vi skal bruke til å opprette vår Node.js-app. Under devDependencies vi har lagt til mocha og supertest, som begge vil hjelpe oss med å skrive våre tester.

Nå som vår package.json er definert, installer våre appavhengigheter ved å kjøre:

npm installasjon

Det er på tide å skrive vår appkode. Opprett en fil som heter app.js og legg til følgende for det:

var express = kreve ('express'); var app = express (); app.get ('/', funksjon (req, res) res.send ('hej verden');); app.listen (process.env.PORT || 5000); module.exports = app;

La oss bryte ned vår enkle Node.js-app:

  • Først importerer vi uttrykke lib spesifisert i vår package.json.
  • Vi bruker uttrykke å opprette en ny app.
  • Vi forteller oss app å svare på alle forespørsler som rammer til roten til nettstedet vårt (/) med teksten "hallo verden".
  • Deretter forteller vi oss app på hvilken port for å lytte etter forespørsler (process.env.PORT refererer til miljøvariabelen kalt "PORT", og hvis den ikke eksisterer, er vi i stedet standard til port 5000).
  • Endelig gjør vi vår app tilgjengelig for andre Node.js moduler gjennom module.exports (dette vil komme til nytte senere når vi legger til tester).

Det er det! Vår app er klar - la oss kjøre den:

node app.js

Åpne favorittleseren din og naviger til http: // localhost: 5000, og du bør se Hei Verden sitter i all sin strålende plainness.

Det er ikke den mest spennende testappen, men det fungerer! Fortsett og avslutt vår Node.js app med Ctrl-C, og la oss gå videre.

Noen tester er i orden

Det er på tide å skrive en test for vår app - tross alt, hvis vi ikke har noe å teste, vil Jenkins ikke ha noe å gjøre!

Opprett en mappe som heter test, og i den opprette en fil som heter test.js. Legg til følgende kode til test / test.js:

var request = krever ('supertest'); var app = krever ('... /app.js'); beskriv ('GET /', funksjon () det ('svar med hei verden', funksjon (ferdig) request (app) .get ('/'). forvente ('hallo verden', ferdig);); );

Hvordan fungerer testen vår? Først importerer vi begge supertest lib og vår app. Deretter legger vi til en enkelt test som beskriver hva som skal skje når a  forespørsel treffer roten til nettstedet vårt. Vi forteller vår test for å forvente at svaret skal være "hallo verden", og hvis det er, går testen.

For å kjøre testen bruker vi Mocha-biblioteket. Vi installerte Mokka som en del av vår devDependencies, så vi vil bare kjøre en kommando som passerer vår testfil til Mokka og Mokka vil kjøre våre tester:

./node_modules/.bin/mocha ./test/test.js

Når du er ferdig, bør du se en grønn prikk sammen med informasjon som sier at en test har passert. Det betyr at vår test var vellykket! Men å skrive den kommandoen igjen og igjen, vil snart gi fingerkramper og øyeforandringer, så la oss lage et hjelpeskript for å gjøre det for oss (husk, datamaskiner blir ikke kjedelig!).

Lag en ny katalog som heter manus, og i den opprette en fil som heter test (Legg merke til at det ikke er noen forlengelse). Legg til følgende til script / test:

#! / bin / sh ./node_modules/.bin/mocha ./test/test.js

Der - nå har vi et skallskript for å utføre den gnarly linjen for oss. Men før vi kan bruke det, må vi gi det kjørbare tillatelser:

chmod + x script / test

La oss teste det! Løpe:

./ Script / test

... og du bør se samme passeringstest som før.

Tid til å trykke

OK, vi har en fungerende app og en arbeidstest, så la oss trykke vår nye kode til GitHub:

git add. git commit -m 'Legg node app' git push opphavsmester

Og det er det - vår app er ferdig og på GitHub!

Vår App Gets Serveres

Vi har en fengslende og fengslende app ("hallo verden" har en slags poesi til det, er du ikke enig?), Men ingen kan se det! La oss endre det og få appen vår å kjøre på en server.

For våre hosting behov, vil vi gå til DigitalOcean. DigitalOcean gir en rask og enkel måte å snurre opp VPS Cloud-instanser, noe som gjør den til den perfekte vert for vår CI / CD-lekeplass.

Den første dråpen

Logg inn på (eller registrer deg for) DigitalOcean og klikk på Lag dråpe knapp. For vertsnavnet, ring det "hei-jenkins". Den laveste størrelsen forekomsten (512/1/20 GB) vil tilpasse våre behov, og velg det geografiske området nærmest deg. Deretter må vi velge bildet som ble brukt til å lage dråpen. DigitalOcean tilbyr et bredt utvalg av operativsystemer å velge mellom, men det som er veldig fint er at de også gir bilder skreddersydd spesielt for bestemte applikasjonstyper.

Klikk på applikasjoner kategorien, og velg node-v0.10.29 på Ubuntu 14.04 alternativ - dette vil skape en server som er pent oppstartet for vår Node.js app.

Klikk nå Lag dråpe, og DigitalOcean kommer i gang med å initialisere vår server.

Konfigurer serveren

Innen et minutt burde vår nye server være klar, og du burde ha mottatt en epost med serverens rotenavn. La oss bruke den informasjonen til å logge inn:

ssh [email protected]

Du blir bedt om å oppgi passordet som er oppgitt i e-posten, og umiddelbart tvunget til å opprette et nytt passord (gjør det noe veldig sterkt, og lagre det på et sikkert sted, som en KeePass-database).

Akkurat nå er vi logget inn som rot, som er den allmektige demigoden av Linux-land. Men tung er hodet som bærer kronen, og opererer som rot er vanligvis en dårlig ide. Så det første vi vil gjøre er å opprette en ny bruker - la oss kalle det "app":

adduser app

Du må oppgi et passord (a forskjelligsterkt passord, lagret sikkert), og så spør det en rekke valgfrie spørsmål.

Vi ønsker å bytte til vår app bruker, men før vi logger ut, må vi gi vår nye bruker sudo privilegier, slik at det vil være i stand til å utføre administrative handlinger:

usermod -a -G sudo app

Nå lukk forbindelsen med exit, og koble deretter til som app:

ssh [email protected]

Du blir bedt om å app brukerens passord, og da bør du være innlogget og god å gå.

Installer vår app

La oss få vår app på maskinen. Takket være DigitalOceans applikasjonsbilder kommer maskinen vår med Node.js og npm forhåndsinstallert, men vi må fortsatt installere Git:

sudo apt-get install git

Du blir bedt om passordet ditt (siden du bruker sudo), og du må bekrefte installasjonen med Y. Når Git er installert, kan vi bruke den til å få vår app fra GitHub.

Kopier HTTPS-klonadressen fra prosjektets GitHub-side, og klon deretter repoen til hjemmemappen på serveren:

cd git klone https://github.com//hello-jenkins.git

Nå er vår app på vår server, i en mappe som heter "hallo-jenkins." La oss navigere inn i det:

cd hei-jenkins

Det første vi må gjøre er å installere appavhengighetene:

npm installasjon - produksjon

Når det er gjort, kan vi kjøre vår app! Spinn det opp med:

node app.js

... og naviger til serverens IP-adresse i nettleseren din.

Men vent, det virker ikke! Hva er greia?

Vel, la oss huske denne koden i vår app.js:

app.listen (process.env.PORT || 5000);

Akkurat nå har vi ikke en HAVN miljøvariabel sett, så vår app er standard for port 5000, og du må legge til porten til IP-adressen i nettleseren (http: //YOUR.SERVER.IP.ADDRESS: 5000).

Så hvordan får vi vår app til å fungere som forventet, og trenger å spesifisere porten? Vel, når en nettleser gjør en HTTP-forespørsel, blir den standard til port 80. Så vi trenger bare å sette vår HAVN miljøvariabel til 80.

Vi stiller våre miljøvariabler i / Etc / miljø fil på serveren - denne filen blir lastet ved innlogging, og variablene som er satt, vil være tilgjengelige globalt for alle applikasjoner. Åpne filen:

sudo nano / etc / miljø

Du ser det akkurat nå STI blir satt i denne filen. Legg til følgende linje etter den:

PORT = 80

Skriv deretter inn Ctrl-X, Y, og Tast inn å lagre og avslutte. Logout av serveren (exit) og SSH tilbake i (dette vil laste inn den nye miljøvariabelen).

En siste liten chore - å kjøre en app på port 80 krever root privilegier, men utfører sudo node app.js vil ikke bevare miljøvariablene vi har satt opp. For å komme seg rundt dette, aktiverer vi node å ha muligheten til å kjøre på port 80 sans sudo:

sudo setcap cap_net_bind_service = + ep / usr / local / bin / node

Det burde gjøre det. Kjør nå:

node app.js

Navigere til http: //YOUR.SERVER.IP.ADDRESS, og du vil se Hei Verden!

Hold den i gang

For øyeblikket kjører appen bare når vi kjører prosessen. Hvis vi lukker det, er nettstedet vårt ikke lenger tilgjengelig. Det vi trenger er en måte å holde vår Node.js app kjører i bakgrunnen. For det vil vi bruke for alltid. Det første trinnet er å installere det globalt:

sudo npm installere -g for alltid

Nå, i stedet for å starte vår app med node app.js, vi skal bruke:

for alltid begynne app.js

Legg merke til at i stedet for prosessen som henger på utførelse, går den ut umiddelbart og gir deg kontrollen tilbake. Dette skyldes at Node.js-serveren kjører i bakgrunnen. Nå trenger vi ikke å bekymre oss for at serveren slår seg ned når vi logger ut av serveren. for alltid Vil til og med automatisk starte appen vår om det skjer krasj!

For å stoppe vår app kan vi kjøre:

for alltid stopall

For nå, la oss fortsette å løpe, og fortsett til Jenkins.

En tid til å teste

Vi vil være vert for vår Jenkins-server på en separat DigitalOcean-dråpe. La oss spinne opp nå.

Den andre dråpen

Opprett en ny dråpe med vertsnavnet "jenkins-box". Velge 512/1/20 GB igjen, sammen med samme sted og samme søknadstype (node-v0.10.29 på Ubuntu 14.04) som med forrige dråpe.

Klikk Lag dråpe og når det er ferdig, bruk legitimasjonene som er sendt til deg, for å logge deg på via SSH (du må sette et nytt passord, akkurat som før).

Som før bør vi opprette en ny bruker før vi gjør noe annet. Denne gangen la vi kalle det admin:

adduser admin usermod -a -G sudo admin

Logg av som rot og logg inn som den nyopprettede admin.

Siden hensikten med Jenkins er å hente vårt prosjekt og kjøre sine tester, må vår maskin ha alle prosjektets avhengigheter installert. Vi spunnet opp denne forekomsten med DigitalOcean's Node.js-applikasjon, så Node.js og npm er allerede installert. Men vi trenger fortsatt å installere Git:

sudo apt-get install git

Lei Butler

Neste opp er Jenkins. Det er ganske enkelt å installere Jenkins - vi har apt-get gjør alt tungt løft. Den eneste fangsten er at vi må legge til en ny apt depot før du starter installasjonen:

sudo wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add-sudo sh-c 'ekko deb http://pkg.jenkins-ci.org/debian binær /> /etc/apt/sources.list.d/jenkins.list' sudo apt-get update

Nå kan vi installere Jenkins:

sudo apt-get install jenkins

Når du er ferdig, kjører Jenkins og er tilgjengelig på port 8080. Naviger nettleseren din til Jenkins-box IP-adresse i port 8080, og du vil se Jenkins destinasjonsside.

Klikk på Administrer Jenkins lenke, og deretter Administrer plugger link. Bytt til Tilgjengelig kategorien, og søk etter GitHub Plugin. Klikk på Installere boksen, og deretter Last ned nå og installer etter omstart knapp.

Dette vil starte installeringssekvensen. GitHub-pluginet har flere avhengigheter, så flere plugins blir installert. Nederst på siden, sjekk Start Jenkins på nytt når installasjonen er fullført, og ingen jobber kjører - Dette vil be Jenkins å starte på nytt når installasjonene er ferdige.

Når Jenkins har startet på nytt, er det på tide å legge til prosjektet vårt. Klikk på Ny gjenstand knapp. Bruk "hei-jenkins" for varenavnet, velg Bygg et kostnadsfritt programvareprosjekt, og klikk på knappen merket OK.

Når prosjektet er satt opp, finner du deg selv på prosjektets innstillingsside. Legg til prosjektets GitHub URL til GitHub prosjekt eske:

https://github.com// Hei-Jenkins

Deretter velger du Git alternativ under Kildekodehåndtering. I feltene som nylig ble vist, legger du til nettadressen til vår GitHub-prosjektrepo til Oppslagsadresse felt:

https://github.com//hello-jenkins.git

Rull litt lenger ned og klikk på boksen for å aktivere Bygg når en endring skyves til GitHub. Med dette valget sjekket, vil prosjektet vårt bygge hver gang vi skyver til vår GitHub repo. Selvfølgelig, vi trenger Jenkins å vite hva de skal gjøre når det kjører en bygning. Klikk på Legg til byggesteg rullegardinmenyen, og velg Utfør shell. Dette vil gjøre en Kommando dialog tilgjengelig, og hva vi legger inn i denne dialogen, vil bli kjørt når en bygning starter. Legg til følgende for det:

npm installere ./script/test

Vår bygg består av to trinn. Først installerer den vår appavhengighet. Så kjører det ./ Script / test å kjøre testene våre.

Klikk på "Lagre".

For å fullføre etableringen av integrasjonen, gå over til GitHub repo, og klikk innstillinger. Klikk på Webhooks & Services kategorien, og deretter Legg til tjeneste fall ned. Velg Jenkins (GitHub plugin) service.

Legg til følgende som Jenkins krok url:

http: //JENKINS.SERVER.IP.ADDRESS: 8080 / github-webhook /

Klikk Legg til tjeneste. Vårt prosjekt er nå klart for sin første kontinuerlige integreringstest!

La oss gi det noe å teste. Åpne opp app.js lokalt og endre denne linjen:

res.send ('hei verden');

… til dette:

res.send ('hei jenkins');

Lagre endringen og forplikte den:

git add. git commit -m 'Bytt til hei jenkins'

Nå hold øye med Jenkins mens du presser endringene dine til GitHub:

git push origin master

Etter et sekund eller to, bør du se at en ny jobb er startet for vår Hello-Jenkins prosjekt i Jenkins - våre kontinuerlige integrasjonsarbeid!

Den kontinuerlige integrasjonsflyten

Men ... jobben mislykkes! Hvorfor?

Vel, husk at vår test forventer roten til å returnere "hallo verden", men vi har endret den til "hallo jenkins". Så la oss forandre forventningene til testen vår. Bytt denne linjen:

forespørsel (app) .get ('/'). forvente ('hallo verden', ferdig);

... med denne linjen:

forespørsel (app) .get ('/'). forvente ('hallo jenkins', ferdig);

Lagre, begå og trykk igjen:

git add. git commit -m 'Bytt test til hei jenkins' git push origin master

Se Jenkins - igjen, du vil se at en konstruksjon starter automatisk, og denne gangen lykkes det!

Dette er strømmen av kontinuerlig integrasjon. Testserveren tester kontinuerlig en ny kode du trykker på, slik at du raskt blir informert om eventuelle sviktende tester.

Få det distribuert

OK, så vi tester automatisk våre endringer, men hva med implementering av disse endringene? Ikke noe problem!

Hvis du har sett nøye på, har du uten tvil lagt merke til at noe mangler fra vårt prosjekt hittil. I prosjektstrukturen i begynnelsen av opplæringen eksisterer det a script / distribuere fil, men vi har ennå ikke laget en slik fil. Vel, nå vil vi!

Nøkkelen til godkjenning

Men først, la oss diskutere hvordan distribusjonen vil fungere. Skriptet vårt (drevet av Jenkins byggesteg) logger inn på appserveren via SSH, navigerer til vår appmappe, oppdaterer appen og starter deretter serveren på nytt. Før du skriver vårt distribusjonsskript, må vi håndtere hvordan vår Jenkins-server vil SSH inn i vår appserver.

Så langt har vi tilgang til våre servere ved å skrive inn passord manuelt, men denne tilnærmingen fungerer ikke for automatiserte skript. I stedet lager vi en SSH-nøkkel som Jenkins-serveren vil bruke til å autentisere seg med appserveren.

Når Jenkins installerer, oppretter det en ny bruker som heter Jenkins. Jenkins kjører alle kommandoer med denne brukeren, så vi må generere nøkkelen vår med Jenkins brukeren slik at den har riktig tilgang til den.

Mens du er logget inn som admin på Jenkins-box, utfør følgende:

sudo su

Gi din admin passord, og det vil bytte deg til rot bruker. Kjør deretter:

su jenkins

Nå opptrer du som Jenkins bruker. Generer en SSH-nøkkel:

ssh-keygen -t rsa

Lagre filen i standardplasseringen (/var/lib/jenkins/.ssh/id_rsa), og pass på at du ikke bruker en passordfrase (ellers vil SSH-tilgang kreve et passord og vil ikke fungere når det er automatisert).

Deretter må vi kopiere den offentlige nøkkelen som ble opprettet. Kjør dette:

katt ~ / .ssh / id_rsa.pub

... og kopier utgangen. Det skal være en lang streng som starter med "ssh-rsa" og slutter med "jenkins @ jenkins-box".

Logg ut av Jenkins-box og logg tilbake til vår app server (Hello-Jenkins) som app bruker. Vi må opprette en fil som heter authorized_keys i vår app brukerens.ssh mappe:

mkdir ~ / .ssh nano ~ / .ssh / authorized_keys

Lim inn den offentlige nøkkelen du kopierte, og deretter Ctrl-X/Y/Tast inn å lagre og avslutte. For at denne filen skal fungere riktig, må den ha strenge tillatelser angitt på den:

chmod 700 ~ / .ssh chmod 600 ~ / .ssh / *

Gå tilbake til Jenkins boks, bytt til Jenkins bruker, og bekreft at du kan logge inn på vår appserver uten å skrive inn et passord:

ssh [email protected]

Du må logge inn på appserveren uten å måtte skrive inn passordet. Med det etablerte, kan vi nå henvende seg til distribusjon.

Send det automatisk

Lag en fil i manus mappen heter utplassere (Legg merke til at det ikke er noen forlengelse). Legg til følgende til script / distribuere:

#! / bin / sh ssh [email protected] <

La oss gå gjennom dette:

  • Først logger vi inn på appserveren som app bruker.
  • Deretter navigerer vi inn i vår appmappe og oppdaterer til den nyeste versjonen fra GitHub.
  • Deretter installerer vi våre avhengigheter.
  • Til slutt, når vår app-kode er oppdatert, starter vi på nytt vår server med for alltid restartall.

Gjør vår nye skriptfil kjørbar:

chmod + x script / distribuere

Legg til denne nye filen og forplikte den:

git add. git commit -m 'Add deploy script'

Men la oss ikke presse helt ennå. Først, gå tilbake til vår prosjektkonfigurasjon i Jenkins, og bla ned til byggekommandoen. Legg til denne nye linjen på slutten av den:

./ Script / distribuere

Lagre Jenkins-prosjektet.

Gå nå og trykk til GitHub, og se etter som Jenkins bygger automatisk. Når bygningen er ferdig (det bør lykkes), naviger nettleseren din til vår appserveres IP. Presto! Vår spennende "hallo verden" er blitt erstattet med en spennende "hallo jenkins"!

Vår app blir nå kontinuerlig distribuert!

Alt er bra som automatiserer godt

Puh. Det var ganske turen!

Til slutt har vi opprettet både kontinuerlig integrasjon og kontinuerlig distribusjon, noe som gir et veldig godt nivå av automatisering i våre daglige utvikler liv. Husk at datamaskiner ikke kjeder seg, så mens de håndterer testing og distribusjon, er du fri til å gjøre viktige ting, som å lage deg selv en sandwich. Så vær så smørbrød, og spis den som en automasjonskamp!