Veebilehe muudatuste automaatne avaldamine läbi Github Actionsi
Tere! Mina olen Krista ja ma olen Zone front-end’i tarkvaraarendaja. Nagu ka paljud teised elukutselised arendajad, tunnen ka mina vahel, et ainult tööl kirjutatud koodist ei piisa, seega kirjutan ma mõnikord enesearendamise eesmärgil koodi ka tööväliselt. Tahan järgnevalt jagada teiega oma kogemust ühe kasuliku GitHubi featuuriga, mis peaks hõlbustama veebilehe arendamise protsesse.
Oma ”enesearenduserännakutel” olen end tihti leidnud mõtlemas sellele, kuivõrd tüütu on iga väikse muudatuse järgselt oma kodulehel siseneda serveri haldusesse, sealt omakorda failide haldusesse, avada õige kaust ja asendada vanad failid uutega. Oleks ju palju lihtsam ja mugavam, kui mingitlaadi automaatika teeks selle mu eest ära… näiteks kohe pärast push’i versioonihaldussüsteemi peamisesse harusse. Seega otsustasin, et on lõpuks aeg teha oma esimene teadlikum samm CI/CD maailmas ja jagada oma avastusi ka teiega.
Pärast mõnda aega uurimist komistasin GitHubis Actions nimelise funktsionaalsuse otsa, mille põhieesmärk on arendajate töökulgu (edaspidi workflow) automatiseerida. Actionsi võimekuse hulka kuulub koodi buildimine, testide jooksutamine, aga ka koodi tarnimine GitHubi repository’st (edaspidi repo) otse serverisse.
Kas see eeldab ka mingeid lisatasusid?
Tasuta GitHubi kasutajatele on võimaldatud privaatsete repode puhul igakuiselt 2000 minutit GitHub Actionsi workflow täideviimise aega.
Avalike repode puhul on workflowde täideviimine minutitest sõltumata alati tasuta.
Lisaks tuleb arvestada, et tasuta paketis on kuni 500 MB andmemahtu, mis arvutatakse kokku kõikide sinu kasutajale kuuluvate repode peale kokku.
Eelpool välja toodud piiride ületamisel algab GitHubi hinnakirja alusel arveldus alates piiride ületamise hetkest.
Aga hakkame siis pihta…
1. Ettevalmistused
Esmalt vaatame üle, mida sul tarvis on:
- Serverit Zones (sobivad kõik meie pakutavad paketid)
Käesolevas artiklis on näitena kasutusel meie veebimajutuse Starter pakett - GitHubi kontot
- Käsurea kasutamise võimalust (SSH võtmepaari genereerimiseks)
Ja teeme mõned ettevalmistused:
- Valmista ette domeen, kuhu soovid, et su veebileht edaspidi automaatselt tarnitaks. Mina oma näites lõin serverile ”actions” nimelise alamdomeeni (ehk leht avaneb URLilt kujul actions.minudomeen.ee)
- Loo ja seadista oma veebilehe koodile GitHubi repo
VÕI forki testimiseks üks minu repodest:
- buildimist mitte-vajav leht (HTML + CSS)
- buildimist vajav leht (Vite + Vue)
2. SSH võtmepaar ja seadistus Zone’is
Genereeri SSH võtmepaar ja lisa oma Zone’is asuva serveri seadistusse avalik SSH võti.
Sellega tuleb vajadusel abiks meie SSH ühenduse loomise abiartikkel: https://help.zone.eu/kb/ssh-uhenduse-loomine
Määra Ligipääsu drop-downis, et lubad ligipääsu kõikjalt.*
* See võib-olla pani sind kulmu kergitama. Soovitan kindlasti lugeda käesoleva blogiartikli viimast sektsiooni!
3. Saladuste lisamine GitHubi repo seadistusse
Saladused on repo-põhised – kui soovid seadistada koodi tarnimise workflow’d ühte ja samasse serverisse mitmest erinevast repost, tuleb sul saladused igasse reposse eraldi lisada, välja arvatud juhul, kui repod kuuluvad organisatsioonile.
Ava GitHubis oma repo seaded ning selle vasakmenüü Security
sektsiooni alt Secrets and variables
> Actions
.
(NB! Suurendamiseks klõpsa piltil nii siin kui ka edaspidi.)
Kokku tuleb sul sinna lisada kolm saladust:
- HOST_SERVER_IP – selle leiad näiteks Minu Zone’is SSH seadistuse lehelt
- SSH_LOGIN_CREDS – kopeeri SSH seadistuse lehelt oma serveri kasutajanimi ja IP-aadress ning eralda need ätt-märgiga (virtXXXX@IPaadress)
- SSH_PRIVATE_KEY – eelmises punktis genereeritud võtmepaari privaatvõti
NB! Soovitan vajaliku info algul kopeerida eraldi tekstifaili, sest kui teed saladuste lisamisel kusagil kirjavea, saad saladuse väärtust küll muuta, kuid vana väärtust sulle ei kuvata.
Samuti tuleb eraldi tekstifaili kopeerimine kasuks juhul, kui soovid tekitada koodi tarnimise workflow’d samasse serverisse mitmest erinevast repost (nt. kui forkisid testimiseks mõlemad eelpool lingitud repod)
4. Workflow faili koostamine
Järgmiseks navigeeri repo ülamenüüst Actions
alamlehele ja loo uus workflow.
workflow faili muutmise lehel on paremal pool väga kasulik sidebar, kust leiab väljavõtte workflow dokumentatsioonist ning Actionite Marketplace.
Minul on ette valmistatud kaks workflow faili:
- esimene veebilehele, mida pole vaja buildida, ehk mille puhul toimub lihtsalt failide kopeerimine repost serverisse
- teine veebilehele, mida on enne failide kopeerimist serverisse vaja buildida. Minu näites on tegu Vite + Vue lehega.
Soovitan failide sisuga ja kasutatud Actionitega tutvumiseks võtta kõrvale just workflow faili muutmise lehel olev dokumentatsioon ja Marketplace.
Esimene näide – deploy
name: Deploy to Zone
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: production
url: https://YOURDOMAIN.EU
steps:
- name: Checkout to main
uses: actions/checkout@main
- name: Set up SSH
run: |
mkdir -p ~/.ssh/
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.HOST_SERVER_IP }} >> ~/.ssh/known_hosts
- name: Copy files to server
run: |
rsync -vrm ./* ${{ secrets.SSH_LOGIN_CREDS }}:/dataXX/virtXXXXX/domeenid/WWW.YOURDOMAIN.EU/actions
Code language: JavaScript (javascript)
Teine näide – build & deploy
name: Build & Deploy to Zone
on:
push:
branches:
- main
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout to main
uses: actions/checkout@main
- name: Set up Node
uses: actions/setup-node@v3.8.1
- name: Install dependencies
run: npm install
- name: Build project
run: npm run build
- name: Upload built files
uses: actions/upload-artifact@v3.1.3
with:
name: production-files
path: ./dist
deploy:
name: Deploy
runs-on: ubuntu-latest
needs: build
environment:
name: production
url: https://YOURDOMAIN.EU
steps:
- name: Checkout to main
uses: actions/checkout@main
- name: Download built files
uses: actions/download-artifact@v2.1.1
with:
name: production-files
path: ./dist
- name: Connect to server over SSH
run: |
mkdir -p ~/.ssh/
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.HOST_SERVER_IP }} >> ~/.ssh/known_hosts
- name: Deploy built site
run: |
rsync -vrm ./dist/ ${{ secrets.SSH_LOGIN_CREDS }}:/dataXX/virtXXXXX/domeenid/www.YOURDOMAIN.EU/actions
Code language: JavaScript (javascript)
NB! Mõlemas koodis on mõned märksõnad, mis on sul tarvis õigete väärtustega asendada:
- asenda ‘YOURDOMAIN.EU” oma domeeninimega
- dataXX oma serveri partitsiooniga (leiad näiteks Minu Zone’is serveriteenuse süsteemsetest andmetest)
- virtXXXXX oma serveri süsteemse kasutajanimega
- ning vaata kindlasti üle sihtkoha failirada rsync käsu real. (Kui soovid deploy’da otse peadomeenile ja sa pole peadomeeni juurkataloogi muutnud, siis vaheta rea lõpus
/actions
kaust/htdocs
vastu)
Samuti soovitan workflow faili muutmise lehel oleva Marketplace sektsiooni abil Actionite versioonid üle vaadata ja vajadusel failis uuemate vastu muuta.
PS! Antud rsync käsk ei kustuta sihtkoha kataloogis asuvaid faile, kuid kirjutab identse nime ja laiendiga failid üle! Kui soovid, et käsk teisiti käituks, uuri rsync käsu dokumentatsiooni.
5. Commiti ja jälgi mängu
Kui workflow fail valmis ja oma soovide järgi kohandatud, vajuta committimise nupule ja ava ülalt veelkord Actions
.
Seal peaksid nägema oma esimest workflow run’i.
Seni, kui see pole veel õnnestunud või ebaõnnestunud, on selle kõrval oranž ikoon. Kui workflow run on aga läbi saanud, võiks vaatepilt sarnaneda allolevale pildile.
GitHub Actionsi puhul on mugav, et workflow run’i kirjeldusele vajutamisel avaneb leht, kust näed täpsemalt, milline viga ebaõnnestumisel tekkis.
Vajutades ebaõnnestunud tööle vasakul Jobs all või keskel main.yml kastis, on võimalik näha, millise sammu juures täpsemalt viga tekkis koos detailsema veakirjeldusega.
Kui workflow õnnestus, siis peaks sulle oma lehte külastades vastu vaatama juba sinu GitHubi repo main harus olev seis, ning edaspidi pole sul tarvis teha muud kui kirjutada koodi ja deploymiseks pushida (või merge’ida pull request) main harusse.
Kas saaks kuidagi turvalisemalt?
Kas sarnast lahendust on võimalik kasutada ka suuremate ja missioonikriitiliste veebilehtede tarneks? Kindlasti on võimalik, kuid turvalisusele rohkem rõhku pannes tuleb see protsess märksa keerulisemaks teha. Minu poolt välja toodud lahenduse suurim murekoht on, et kogu protsess saab alguse serverist väljaspoolt, kust ühendutakse serveriga üle SSH, iga kord erinevalt IP-aadressilt (kasutame GitHubi enda majutatud jooksutajaid).
Isegi kui privaatne SSH võti on võimalikult turvaliselt talletatud, on soovituslik lisaks rakendada serveris IP-aadressidele või nende vahemikele põhinevat allowlisti. Paraku on GitHub selle tavakasutajale võimalikult keeruliseks teinud.
GitHubi enda majutatud jooksutajate puhul on kasutusel Microsoft Azure andmekeskuste IP-aadresside vahemikud, mida on võimalik pärida üle API, kuid mida vahetatakse kord nädalas, ning neidki võib olla korraga kasutusel sadu. (Käesoleva blogiartikli tarbeks veidi uurimistööd tehes leidsin, et GitHubi Meta endpointis tuleb ”actions” võtme alt välja üle 3720 CIDR notatsiooniga IP-aadresside vahemikku, mille vahel ilmselt toimub iganädalane portsu kaupa rotatsioon).
Tehniliselt on meil võimalik IP-aadresse allowlistist eemaldada ja lisada ka üle API (avalikult dokumenteerimata), kuid sadadesse ulatuvate IP-aadresside vahemikega on tõenäoliselt tegu juba mõistliku kasutuse piiri ületamisega.
Seetõttu on ka GitHub oma dokumentatsioonis märkinud, et nad ei soovita nende poolt majutatavate jooksutajate (GitHub-hosted runners) IP-aadresside vahemikke allowlisti tarbeks kasutada, vaid mõelda alternatiividele. Näiteks pakuvad nad lisaks staatilise IP-aadresside vahemikuga large runnereid, mis on tasulised ning saadaval vaid organisatsioonidele või GitHub Team / Enterprise Cloud pakettide kasutajatele. Samuti on võimalik kasutada täiesti omalt poolt üles seatud ja majutatud jooksutajaid (self-hosted runners), mille puhul GitHub lisatasu ei küsi.
Ilmselt aga veel parem on mõelda lahendusele, mille puhul kogu protsess käib serverisiseselt, näiteks Jenkinsiga.