ProHoster > blogg > administration > Circles of hell med GitHub Actions (bygga en CI/CD-pipeline för ett Java-projekt)
Circles of hell med GitHub Actions (bygga en CI/CD-pipeline för ett Java-projekt)
Jag mÄste ofta bygga en pipeline för att bygga projekt i Java. Ibland Àr det öppen kÀllkod, ibland inte. Jag bestÀmde mig nyligen för att försöka flytta nÄgra av mina förrÄd frÄn Travis-CI och TeamCity till GitHub Actions, och det hÀr Àr vad som kom ut ur det.
Vad ska vi automatisera?
Först behöver vi ett projekt som vi kommer att automatisera, lÄt oss göra en liten applikation i Spring boot / Java 11 / Maven. I den hÀr artikeln kommer vi inte att vara intresserade av applikationslogiken alls; infrastrukturen runt applikationen Àr viktig för oss, sÄ en enkel REST API-kontroller kommer att rÀcka för oss.
Du kan se kÀllorna hÀr: github.com/antkorwin/github-actions Alla stadier av att bygga en pipeline Äterspeglas i pull-förfrÄgningarna för detta projekt.
JIRA och planering
Det Àr vÀrt att sÀga att vi vanligtvis anvÀnder JIRA som en problemspÄrare, sÄ lÄt oss skapa en separat styrelse för det hÀr projektet och lÀgga till de första problemen dÀr:
Lite senare Ă„terkommer vi till vilka intressanta saker JIRA och GitHub kan erbjuda i kombination.
Vi automatiserar monteringen av projektet
VÄrt testprojekt Àr byggt via maven, sÄ att bygga det Àr ganska enkelt, allt vi behöver Àr mvn clean-paketet.
För att göra detta med Github Actions kommer vi att behöva skapa en fil i arkivet som beskriver vÄrt arbetsflöde, detta kan göras med en vanlig yml-fil, jag kan inte sÀga att jag gillar "yml-programmering", men vad kan vi göra - vi gör det i .github/-katalogens arbetsflöde/fil build.yml dÀr vi kommer att beskriva ÄtgÀrderna nÀr vi bygger mastergrenen:
on â det hĂ€r Ă€r en beskrivning av hĂ€ndelsen dĂ€r vĂ„rt manus kommer att lanseras.
pĂ„: pull_request/push â indikerar att detta arbetsflöde mĂ„ste startas varje gĂ„ng en push görs till mastern och pull-förfrĂ„gningar skapas.
Följande Àr en beskrivning av uppgifterna (jobb) och exekveringssteg (steg) för varje uppgift.
gÄr pÄ - hÀr kan vi vÀlja mÄl-OS, överraskande nog kan du till och med vÀlja Mac OS, men pÄ privata arkiv Àr detta ganska dyrt (jÀmfört med Linux).
anvÀndningar lÄter dig ÄteranvÀnda andra ÄtgÀrder, till exempel genom att anvÀnda actions/setup-java-ÄtgÀrden vi installerar miljön för Java 11.
Genom med vi kan specificera parametrarna med vilka vi startar ÄtgÀrden, i huvudsak Àr dessa argument som kommer att skickas till ÄtgÀrden.
Allt som ÄterstÄr Àr att köra projektbygget med Maven: run: mvn -B clean package flagga -B sÀger att vi behöver ett icke-interaktivt lÀge sÄ att maven plötsligt inte vill frÄga oss nÄgot
Bra! Nu, varje gÄng du förbinder dig till mastern, startar projektbygget.
Automatisera testlanseringar
Montering Àr bra, men i verkligheten kan ett projekt monteras sÀkert, men inte fungera. DÀrför Àr nÀsta steg att automatisera testkörningarna. Dessutom Àr det ganska bekvÀmt att titta pÄ resultatet av godkÀnda tester nÀr du gör en PR-granskning - du vet med sÀkerhet att testerna klarar och ingen glömde att driva sin filial innan du gjorde en sammanslagning.
Vi kommer att köra tester nÀr vi skapar en pull-förfrÄgan och slÄs samman i mastern, och samtidigt kommer vi att lÀgga till skapandet av en rapport om kodtÀckning.
För att tÀcka tester anvÀnder jag codecov i kombination med jacoco-plugin. codecov har sin egen ÄtgÀrd, men den behöver en token för att fungera med vÄr pull-begÀran:
${{ secrets.CODECOV_TOKEN }} â vi kommer att se den hĂ€r konstruktionen mer Ă€n en gĂ„ng, hemligheter Ă€r en mekanism för att lagra hemligheter i GitHub, dĂ€r kan vi skriva lösenord/tokens/vĂ€rdar/urls och annan data som inte bör inkluderas i förvarets kodbas.
Du kan lÀgga till en variabel till hemligheter i förvarsinstÀllningarna pÄ GitHub:
Du kan fÄ en token pÄ codecov.io Efter auktorisering via GitHub, för att lÀgga till ett offentligt projekt behöver du bara följa en lÀnk sÄ hÀr: GitHub anvÀndarnamn/[reponamn]. Ett privat arkiv kan ocksÄ lÀggas till; för att göra detta mÄste du ge codecov-rÀttigheter till applikationen i Github.
Nu kommer codecov-boten att ange var och en av vÄra pull-förfrÄgningar och lÀgga till en graf för tÀckningsÀndring:
LÄt oss lÀgga till en statisk analysator
I de flesta av mina projekt med öppen kÀllkod anvÀnder jag ekolodsmoln för statisk kodanalys, det Àr ganska enkelt att ansluta till travis-ci. SÄ det Àr ett logiskt steg nÀr man migrerar till GitHub Actions att göra detsamma. Actionmarknaden Àr en hÀftig sak, men den hÀr gÄngen svikit mig lite, för av vana hittade jag den action jag behövde och lade till den i arbetsflödet. Men det visade sig att ekolodet inte stödjer att arbeta igenom en ÄtgÀrd för att analysera projekt pÄ maven eller gradle. Det stÄr sÄklart i dokumentationen, men vem lÀser det?!
Det Àr inte möjligt genom en ÄtgÀrd, sÄ vi gör det genom mvn-plugin:
SONAR_TOKEN - kan erhÄllas pÄ sonarcloud.io och du mÄste registrera det i hemligheter. GITHUB_TOKEN - detta Àr en inbyggd token som GitHub genererar, med hjÀlp av vilken sonarcloud[bot] kommer att kunna logga in pÄ Git för att lÀmna oss meddelanden i pull-förfrÄgningar.
Dsonar.projectKey â namnet pĂ„ projektet i ekolodet, du kan se det i projektinstĂ€llningarna.
Dsonar.organisation â namnet pĂ„ organisationen frĂ„n GitHub.
Vi gör en pull-förfrÄgan och vÀntar pÄ att sonarcloud[bot] ska komma i kommentarerna:
SlÀpp hantering
Bygget har konfigurerats, testerna har körts och vi kan göra en release. LÄt oss titta pÄ hur GitHub Actions kan göra releasehantering mycket enklare.
PÄ jobbet har jag projekt vars kodbas Àr i bitbucket (allt Àr som i den dÀr berÀttelsen "Jag skriver till bitbucket under dagen, binder mig till GitHub pÄ natten"). TyvÀrr har bitbucket inga inbyggda verktyg för releasehantering. Detta Àr ett problem, för för varje release mÄste du manuellt skapa en sida i sammanflöde och slÀnga alla funktioner som ingÄr i releasen dÀr, söka igenom sinnets palats, uppgifter i jira, commits i arkivet. Det finns mÄnga chanser att göra ett misstag, du kan glömma nÄgot eller skriva in nÄgot som redan slÀpptes förra gÄngen, ibland Àr det helt enkelt inte klart vad man ska klassificera en pull-förfrÄgan som - Àr det en funktion eller en buggfix, eller redigeringstest, eller nÄgot infrastrukturellt.
Hur kan GitHub-ÄtgÀrder hjÀlpa oss? Det finns en fantastisk ÄtgÀrd - release drafter, den lÄter dig stÀlla in en release notes-filmall för att stÀlla in kategorier av pull-förfrÄgningar och automatiskt gruppera dem i release notes-filen:
Exempelmall för att stÀlla in en rapport (.github/release-drafter.yml):
Alla pull-förfrÄgningar frÄn och med nu kommer att samlas i release notes automatiskt - magi!
HÀr kan frÄgan uppstÄ: vad hÀnder om utvecklarna glömmer att sÀtta taggar i PR? Sedan Àr det inte klart vilken kategori man ska lÀgga det i, och Äterigen mÄste man hantera det manuellt, med varje PR för sig. För att ÄtgÀrda det hÀr problemet kan vi anvÀnda en annan ÄtgÀrd - etikettverifierare - den kontrollerar förekomsten av taggar pÄ pull-begÀran. Om det inte finns nÄgra taggar som krÀvs, kommer kontrollen att misslyckas och vi kommer att se ett meddelande om detta i vÄr pull-begÀran.
Nu mÄste varje pull-request markeras med en av taggarna: type:fix, type:features, type:documentation, type:tests, type:config.
Automatisk annotering av pull-förfrÄgningar
Eftersom vi berörde ett sÄdant Àmne som effektivt arbete med pull-förfrÄgningar, Àr det vÀrt att prata om en sÄdan ÄtgÀrd som labeler, den sÀtter taggar i PR baserat pÄ vilka filer som har Àndrats. Till exempel kan vi markera som [bygga] varje pull-begÀran som innehÄller Àndringar i katalogen .github/workflow.
Jag lyckades inte para ihop ÄtgÀrden som automatiskt placerar etiketter i pull-förfrÄgningar med ÄtgÀrden som kontrollerar förekomsten av obligatoriska etiketter; match-label vill inte se etiketterna som lagts till av boten. Det verkar lÀttare att skriva en egen handling som kombinerar bÄda stegen. Men Àven i denna form Àr det ganska bekvÀmt att anvÀnda; du mÄste vÀlja en etikett frÄn listan nÀr du skapar en pull-begÀran.
Det Àr dags att distribuera
Jag försökte flera distributionsalternativ via GitHub Actions (via ssh, via scp och med docker-hub), och jag kan sÀga att du med största sannolikhet kommer att hitta ett sÀtt att ladda upp binÀren till servern, oavsett hur sned din pipeline Àr Àr.
Jag gillade alternativet att hÄlla hela infrastrukturen pÄ ett stÀlle, sÄ lÄt oss titta pÄ hur man distribuerar till GitHub-paket (detta Àr ett arkiv för binÀrt innehÄll, npm, jar, docker).
Skript för att bygga en docker-bild och publicera den i GitHub-paket:
Först mÄste vi bygga JAR-filen för vÄr applikation, varefter vi berÀknar sökvÀgen till GitHub docker-registret och namnet pÄ vÄr bild. Det finns nÄgra knep hÀr som vi inte har stött pÄ Ànnu:
en konstruktion som: echo â::set-output name=NAME::VALUEâ lĂ„ter dig stĂ€lla in vĂ€rdet pĂ„ en variabel i det aktuella steget, sĂ„ att den sedan kan lĂ€sas i alla andra steg.
du kan fÄ vÀrdet pÄ variabeln som sattes in i föregÄende steg genom identifieraren för detta steg: ${{ steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}
Standardvariabeln GITHUB_REPOSITORY lagrar namnet pÄ förvaret och dess Àgare ("Àgare/reposnamn"). För att klippa allt frÄn den hÀr raden förutom namnet pÄ förvaret kommer vi att anvÀnda bash-syntax: ${GITHUB_REPOSITORY#*/}
För att indikera versionen av bilden anvÀnder vi de första siffrorna frÄn SHA-hashen för commit - GITHUB_SHA det finns ocksÄ nyanser hÀr, om du gör sÄdana builds inte bara nÀr du slÄr samman till master, utan ocksÄ enligt skapandet av pull-begÀran hÀndelse, dÄ kanske SHA inte matchar hashen som vi ser i git-historiken, eftersom ÄtgÀrderna/utcheckningsÄtgÀrden gör sin egen unika hash för att undvika dödlÀgesÄtgÀrder i PR.
Om allt fungerade bra, öppnar du paketsektionen (https://github.com/antkorwin/github-actions/packages) i förvaret, kommer du att se en ny dockarbild:
DÀr kan du ocksÄ se en lista över versioner av docker-bilden.
Allt som ÄterstÄr Àr att konfigurera vÄr server för att fungera med detta register och starta om tjÀnsten. Jag kommer förmodligen att prata om hur man gör detta genom systemd en annan gÄng.
övervakning
LÄt oss titta pÄ ett enkelt alternativ för hur man gör en hÀlsokontroll för vÄr applikation med hjÀlp av GitHub Actions. VÄr startapplikation har ett stÀlldon, sÄ vi behöver inte ens skriva ett API för att kontrollera dess status; vi har redan gjort allt för de lata. Du behöver bara dra vÀrden: SERVER-URL:PORT/actuator/health
Allt vi behöver Àr att skriva en uppgift för att kontrollera servern med cron, och om den plötsligt inte svarar oss, skickar vi ett meddelande via telegram.
LÄt oss först ta reda pÄ hur man kör ett cron-arbetsflöde:
LĂ„t oss kontrollera serverstatusen manuellt via curl:
jobs:
ping:
runs-on: ubuntu-18.04
steps:
- name: curl actuator
id: ping
run: |
echo "::set-output name=status::$(curl ${{secrets.SERVER_HOST}}/api/actuator/health)"
- name: health check
run: |
if [[ ${{ steps.ping.outputs.status }} != *"UP"* ]]; then
echo "health check is failed"
exit 1
fi
echo "It's OK"
Först sparar vi i en variabel vad servern svarade pÄ förfrÄgan, i nÀsta steg kontrollerar vi att statusen Àr UPP och, om sÄ inte Àr fallet, avslutar vi med ett fel. Om du behöver "övervÀldiga" en handling med hÀnderna, dÄ avsluta 1 - lÀmpligt vapen.
- name: send alert in telegram
if: ${{ failure() }}
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_TO }}
token: ${{ secrets.TELEGRAM_TOKEN }}
message: |
Health check of the:
${{secrets.SERVER_HOST}}/api/actuator/health
failed with the result:
${{ steps.ping.outputs.status }}
Vi skickar till telegram endast om ÄtgÀrden misslyckades i föregÄende steg. För att skicka ett meddelande anvÀnder vi appleboy/telegram-action; du kan lÀsa om hur du fÄr en bot-token och chatt-id i dokumentationen: github.com/appleboy/telegram-action
Glöm inte att skriva i hemligheterna pÄ Github: URL för servern och tokens för telegramboten.
GitHub kommer ocksÄ att hjÀlpa oss i denna rutinuppgift; till att börja med kan vi dra problem automatiskt till kod_review-kolumnen nÀr vi skickar en pull-begÀran. Allt du behöver göra Àr att följa grenens namnkonvention:
till exempel, om projektnyckeln "GitHub Actions" Àr GA, dÄ GA-8-jira-bot kan vara en gren för att implementera GA-8-uppgiften.
Integration med JIRA fungerar genom handlingar frÄn Atlassian, de Àr inte perfekta, jag mÄste sÀga att nÄgra av dem inte fungerade för mig alls. Men vi kommer bara att diskutera de som definitivt fungerar och anvÀnds aktivt.
Först mÄste du logga in pÄ JIRA med ÄtgÀrden: atlassian/gajira-login
Vi extraherar uppgiftsidentifieraren frÄn filialnamnet:
- name: Find Issue
id: find_issue
shell: bash
run: |
echo "::set-output name=ISSUE_ID::$(echo ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}')"
echo brach name: $GITHUB_HEAD_REF
echo extracted issue: ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}'
- name: Check Issue
shell: bash
run: |
if [[ "${{steps.find_issue.outputs.ISSUE_ID}}" == "" ]]; then
echo "Please name your branch according to the JIRA issue: [project_key]-[task_number]-branch_name"
exit 1
fi
echo succcessfully found JIRA issue: ${{steps.find_issue.outputs.ISSUE_ID}}
Om du söker pÄ GitHub-marknadsplatsen kan du hitta en ÄtgÀrd för denna uppgift, men jag var tvungen att skriva samma sak med grep med namnet pÄ grenen, eftersom den hÀr ÄtgÀrden frÄn Atlassian inte ville arbeta med mitt projekt pÄ nÄgot sÀtt , för att ta reda pÄ vad som var fel dÀr - lÀngre Àn att göra samma sak med hÀnderna.
Allt som ÄterstÄr Àr att flytta uppgiften till kolumnen "Kodgranskning" nÀr du skapar en pull-begÀran:
Det finns en speciell ÄtgÀrd för detta pÄ GitHub, allt den behöver Àr problem-ID som erhölls i föregÄende steg och auktoriseringen i JIRA som vi gjorde ovan.
PÄ samma sÀtt kan du dra uppgifter nÀr du slÄr samman till mastern och andra hÀndelser frÄn GitHub-arbetsflödet. I allmÀnhet beror allt pÄ din fantasi och önskan att automatisera rutinprocesser.
Resultat
Om du tittar pÄ det klassiska DEVOPS-diagrammet har vi tÀckt alla stadier, förutom kanske att fungera, jag tror att om du försöker kan du hitta nÄgra ÄtgÀrder pÄ marknaden för integration med helpdesk-systemet, sÄ vi kommer att anta att pipelinen vÀnde ut att vara grundlig och slutsatser kan dras utifrÄn dess anvÀndning.
Fördelar:
Marknadsplats med fÀrdiga ÄtgÀrder för alla tillfÀllen, det hÀr Àr vÀldigt coolt. I de flesta av dem kan du ocksÄ titta pÄ kÀllkoden för att förstÄ hur man löser ett liknande problem eller skicka en funktionsbegÀran till författaren direkt i GitHub-förvaret.
Att vÀlja mÄlplattform för montering: Linux, mac os, windows Àr en ganska intressant funktion.
Github-paket Àr en fantastisk sak, det Àr bekvÀmt att hÄlla hela infrastrukturen pÄ ett stÀlle, du behöver inte surfa genom olika fönster, allt Àr inom en radie av ett eller tvÄ musklick och Àr perfekt integrerat med GitHub Actions. Docker-registerstöd i gratisversionen Àr ocksÄ en bra fördel.
GitHub döljer hemligheter i byggloggar, sÄ att anvÀnda den för att lagra lösenord och tokens Àr inte sÄ skrÀmmande. Under alla mina experiment kunde jag aldrig se hemligheten i dess rena form i konsolen.
Gratis för Open Source-projekt
Nackdelar:
YML, ja, jag gillar inte honom. NÀr man jobbar med ett sÄdant flöde Àr det vanligaste commit-meddelandet jag har "fix yml format", dÄ glömmer man att sÀtta en flik nÄgonstans, eller sÄ skriver man den pÄ fel rad. Generellt sett Àr det inte den roligaste upplevelsen att sitta framför en skÀrm med gradskiva och linjal.
DEBUG, felsöka flödet med commits, köra en ombyggnad och utmatning till konsolen Àr inte alltid bekvÀmt, men det Àr mer av kategorin "du Àr överdriven"; du Àr van att arbeta med praktisk IDEA, nÀr du kan felsöka vad som helst .
Du kan skriva din handling pÄ vad som helst om du lindar in den i Docker, men bara javascript stöds inbyggt, naturligtvis Àr detta en smaksak, men jag skulle föredra nÄgot annat istÀllet för js.
NÀsta vecka ska jag upptrÀda med Rapportera pÄ Heisenbug 2020 Piter-konferensen. Jag ska inte bara berÀtta för dig hur du undviker misstag nÀr du förbereder testdata, utan ocksÄ dela mina hemligheter med att arbeta med datamÀngder i Java-applikationer!