Deploy din Gitlab CI spre un server live

Am următoarea problmă cu gitlab CI.

.gitlab-ci.yml:

deploy:
  image: tetraweb/php
  script:
  - apt-get install unzip
  - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
  - php composer-setup.php
  - php -r "unlink('composer-setup.php');"
  - php composer.phar update
  - npm install
  - npm run deploy

Build-ul este OK, toată lumea e fericită. Darrr… cum naiba îl iau de pe serverul lor și îl pun pe serverul meu?

Am pornit de la articolul ăsta, dar am ajuns într-un punct în care nu știu ce să fac mai departe.

Folosesc sftp? rsync? Altceva? Și mai ales… CUM fac asta din Gitlab CI?

2 Likes

Daca folosesti gitlab de ce nu folosesti git push ? …
Nu vad problema.

Am de rulat composer & npm, procese ce generează fișiere ce nu sunt în repo.

Scopul final este să pun fișierele pe server chiar dacă nu am composer și/sau node instalat acolo.

1 Like

Pai depinde ce ai pe serverul pe care vrei sa faci deployment-ul. Poti sa folosesti SCP, ftp, rsync, etc.
Practic mai adaugi o line de script

- scp myfile.php [email protected]:/var/www/site

Ce imi scapa acum este cum adaugi o cheie ssh pentru [email protected] ca sa poti sa adauga la argumentul -i <path_to_key> ca sa treci de autentificare. O idee de hack ar fi un echo $SSH_KEY_PARAM intr-un fisier din /tmp pe care folosiesti apoi pentru comanda de scp.

1 Like

Sper ca am inteles corect problema pe care ai pus-o, dar exact ca si ssh, scp accepta flagul -i

scp -i mykey.pem somefile.txt root[email protected]:confused:

Ma refeream ca pentru -i trebuie sa ii dai calea catre un fisier care contine cheia privata pentru autentificare. Si nu stiu unde/cum poti sa pui aceasta cheie privata pentru accesarea serverului pe care vrei sa faci deployment din gitlab. In exemplul tau mykey.pem trebuie sa exista undeva pe serverul de CI.

Să zicem că rezolv treaba cu cheile ssh (Gitlab permite adăugarea unor parametri în web ui, astfel încât nu sunt accesibile decât la build).

Problema e că atunci când te conectezi la un host nou - iar gitlab CI este o instanță nouă de fiecare dată - te întreabă dacă vrei să adaugi cheia sufletului în known_hosts.

Iar cu SCP am impresia că-i aceeași bubă ca și la (s)FTP: transferă fiecare fișier în parte; iar la ~2000 fișiere durează o grămadă doar procesul de conectare dintre servere. Nu?

scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -q

Primii doi parametrii seteaza optiuni pentru SSH/SCP, q pentru suprimarea mesajelor.

$ scp -r mydir [email protected]:/var/www/site

scp are suport pentru recurisivitate (si suporta si pattern-uri), deci nu trebuie sa le incarci fisier cu fisier

2 Likes

Ce mi-ai zis cu StrictHostKeyChecking era the missing link, ca să zic așa. Împreună cu acest ghid am reușit să fac acest script:

image: tetraweb/php
before_script:
  - apt-get update
  - apt-get install zip unzip
  - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
  - php composer-setup.php
  - php -r "unlink('composer-setup.php');"
  - php composer.phar update
  - npm install
  - npm run deploy

deploy:
  script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - mkdir -p ~/.ssh
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$PRIVATE_KEY")
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    - ssh -p2345  [email protected] "rm -rf /var/www/domain.com/htdocs/*"
    - scp -P2345 -r build/* [email protected]:/var/www/domain.com/htdocs
  artifacts:
    paths:
    - build/

Rezultatul:

Build succeeded

Duration: 2 minutes 31 seconds

Probabil durează un pic mai mult decât git pull direct pe server, dar nu deranjează. E mai cool. Și am învățat chestii noi :sunglasses:

Problema - cel puțin pentru moment - este că nu știu cum aș putea șterge din fișierele deployed ce nu mai sunt în repo (sau în build).

Momentan am ales să le șterg pur și simplu pe toate:

ssh -p2345 [email protected] "rm -rf /var/www/domain.com/htdocs/*"

Este un pic cam hacky, dar functionează.

1 Like

Eu as recomanda metoda folosita pe scara mai mare, daca tot vrei sa inveti ceva cu adevarat nou.
Se ia distributia tina (sa zicem ca ai Ubuntu) si se creaza in scriptul gitlab un packet .deb sau .ppa cu tot ce ai nevoie. Il publici, si apoi il instalezi frumos pe server cu apt. Daca aveai CentOS pe server faceai un rpm. Ar trebui sa elaborez chestia asta intr-un blogpost de research.

2 Likes

Posibil să fie mici diferențe între apps enterprise și site-uri cu 3-5000 vizitatori/zi :slight_smile:

Darrrr subiectul pare interesant. Aștept să detaliezi :wink:

1 Like

@tekkie Sa faci pachet pentru systemul de operare e cam overkill. M-a tentat si pe mine idea la un moment dat dar era prea multa bataie de cap. Mai bine Docker sau Ubuntu Snappy :slight_smile:

@iamntz pentru fisierele vechi tot ‘rm -rf’ iti recomand si eu. Ai grija sa nu stergi fisierele incarcate de utilizatori :smile: Si inca o problema ar fi ca nu iti merge siteul de cand ai sters versiunea veche si pana cand se termina de incarca fisierele.
O idee ar fi sa ai doua foldere: current si deploy (sa zicem); htdocs e symlink catre current; faci scp in folderul deploy si cand se termina ‘mv current old && mv deploy current && mkdir deploy && rm -rf old’ (stergerea am pus-o la final pentru ca dureaza mai mult).

2 Likes

Este diferenta. Dar pt enterprise te antrenezi pe jmecherii d’astea mici.
Nu stiu cum o sa stau cu timpul, e un subiect caremerita tratat nesuperficial.
Eu am ajutat in trecut devopsii cu suport pe toata partea de instalare a codului, practic le-am facut un bash script care facea niste pasi (composer install, setari permisiuni, etc). Ei au luat jucaria si au bagat-o intr-un Jenkins, i-au dat initializare, si au scos un frumos pachet RPM (ca deh, maria-sa RedHat). Si mergeam frumusel si bagam un yum install pe serverul de QA (sau unde mai era cazul), pana la urma tot la push button in Jenkins care sa faca el upgrade am ajuns, pt traceability.

3 Likes

Pentru hosting-ul pachetelor folosesc GemFury - e un hosted private repository pentru Apt/Yum/RubyGems/Npm/Composer/PyPi/Bower/NuGet. Pentru multe proiecte hostingul pe repository-ul principal public nu e o idee asa grozava. Plus mi se pare pare un pattern bun ca aplicatia in sine sa fie un pachet in limbajul de programare in care este dezvoltata, sau pentru sistemul de operare respectiv (optiune mai greoaie ce-i drept). Partea de depoly pe o masina poate fi apoi fi decat niste cod de “curatenie” si un install/update al pachetului respectiv. Docker incearca sa faca ceva de genul asta, dar nu este o solutie pentru toate setup-urile inca.

+1 pentru folosirea unui simlink, dar redenumirea ar trebui sa fie atomica. Ai o fereastra de timp in care current nu exista, care poate cauza probleme.

5 Likes

Pai ideea era sa pui fisierele din build intr-un repo privat si sa ii dai push…

Deploy before:
ssh [email protected] "git init --bare /var/www/domain.com/htdocs/my-project.git"

Deploy :

cd buildfiles
git remote add origin ssh://[email protected]/var/www/domain.com/htdocs/my-project.git
git push origin master

Iti actualizeaza doar fisierele schimbate, eventual stergi cache-ul la sfarsit.

Ai dreptate cu redenumire atomica, mi-a scapat.