{"id":85646,"date":"2020-06-18T01:42:15","date_gmt":"2020-06-17T23:42:15","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular"},"modified":"2020-06-18T01:42:15","modified_gmt":"2020-06-17T23:42:15","slug":"ci-cd-v-github-actions-dlya-proekta-na-flask-angular","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular","title":{"rendered":"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/26d0945a41bbf3c98fa92f15be5b8c6c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nN\u00eb k\u00ebt\u00eb artikull, do t\u00eb ndaj p\u00ebrvoj\u00ebn time n\u00eb konfigurimin e CI\/CD duke p\u00ebrdorur panelin e kontrollit Plesk dhe Github Actions. Sot do t\u00eb m\u00ebsojm\u00eb si t\u00eb depolojm\u00eb nj\u00eb projekt t\u00eb vog\u00ebl me emrin \"Helloworld\". Ai \u00ebsht\u00eb shkruar n\u00eb kuad\u00ebr Python Flask, me pun\u00ebtor\u00eb n\u00eb Celery dhe frontend n\u00eb Angular 8.<\/p>\n<p><b>Lidhjet p\u00ebr repozitor\u00ebt:<\/b> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\">backend<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld-front\">frontend<\/a><\/noindex>.<\/p>\n<p>N\u00eb pjes\u00ebn e par\u00eb t\u00eb artikullit do t\u00eb shohim projektin ton\u00eb dhe pjes\u00ebt e tij. N\u00eb t\u00eb dyt\u00ebn, do t\u00eb kuptojm\u00eb si t\u00eb konfigurojm\u00eb Plesk dhe t\u00eb instalojm\u00eb zgjerimet dhe komponent\u00ebt e nevojsh\u00ebm (Baza e t\u00eb Dh\u00ebnave, RabbitMQ, Redis, Docker, etj.).<\/p>\n<p>N\u00eb pjes\u00ebn e tret\u00eb, p\u00ebrfundimisht do t\u00eb kuptojm\u00eb se si t\u00eb konfiguroni pipeline p\u00ebr t\u00eb depolar projektin ton\u00eb n\u00eb serverin n\u00eb mjedisin dev dhe prod. Dhe pastaj do ta nisim faqen n\u00eb server.<\/p>\n<p>Po, harrova t\u00eb prezantohem. M\u00eb quajn\u00eb Oleg Borzov, un\u00eb jam zhvillues fullstack n\u00eb ekipin CRM p\u00ebr menaxher\u00ebt e kredive hipotekare n\u00eb Domklik. <br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1>P\u00ebrmbledhja e projektit<\/h1>\n<p>\nFillimisht, le t\u00eb shqyrtojm\u00eb dy repozitor\u00ebt e projektit - backend dhe frontend - dhe t\u00eb kalojm\u00eb p\u00ebrmes kodit.<\/p>\n<h2>Pjesa backend: Flask+Celery<\/h2>\n<p>\nP\u00ebr pjes\u00ebn backend, kam marr\u00eb nj\u00eb kombinim t\u00eb mjaft popullarizuar midis zhvilluesve Python: kuadri Flask (p\u00ebr API) dhe Celery (p\u00ebr radh\u00ebn e detyrave). Si ORM p\u00ebrdoret SQLAlchemy. P\u00ebr migrimet \u00ebsht\u00eb p\u00ebrdorur Alembic. P\u00ebr validimin e JSON n\u00eb duar - Marshmallow.<\/p>\n<p>N\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\">repotit\u00eb e tij<\/a><\/noindex> ka nj\u00eb skedar Readme.md me p\u00ebrshkrimin e detajuar t\u00eb struktur\u00ebs dhe udh\u00ebzimeve p\u00ebr fillimin e projektit.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/app_web\">API i pjes\u00ebs web<\/a><\/noindex> mjaft i thjesht\u00eb, p\u00ebrb\u00ebhet nga 6 duar:<\/p>\n<ul>\n<li><code>\/ping<\/code> \u2014 p\u00ebr kontrollimin e disponueshm\u00ebris\u00eb;<\/li>\n<li>duar p\u00ebr regjistrimin, autorizimin, deautorizimin dhe marrjen e p\u00ebrdoruesit t\u00eb autorizuar;<\/li>\n<li>duar p\u00ebr d\u00ebrgimin e email-it, e cila vendos nj\u00eb detyr\u00eb n\u00eb radh\u00ebn e Celery.<\/li>\n<\/ul>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/app_celery\">Pjesa Celery<\/a><\/noindex> p\u00ebrsa i p\u00ebrket thjesht\u00ebsis\u00eb, aty ka vet\u00ebm nj\u00eb detyr\u00eb <code>send_mail_task<\/code>.<\/p>\n<p>N\u00eb dosjen <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/conf\/\">\/conf<\/a><\/noindex> ka dy n\u00ebnfoldra: <\/p>\n<ul>\n<li><code>docker<\/code> me dy skedar\u00eb Docker (<code>base.dockerfile<\/code> p\u00ebr nd\u00ebrtimin e imazhit baz\u00eb q\u00eb ndryshohet rrall\u00eb dhe <code>Dockerfile<\/code> p\u00ebr nd\u00ebrtimet kryesore);<\/li>\n<li><code>.env_files<\/code> \u2014 me skedar\u00eb t\u00eb variablave t\u00eb mjedisit p\u00ebr mjedisa t\u00eb ndryshme. <\/li>\n<\/ul>\n<p>\nN\u00eb rr\u00ebnj\u00ebn e projektit ndodhen kat\u00ebr skedar\u00eb docker-compose:<\/p>\n<ul>\n<li><code>docker-compose.local.db.yml<\/code> p\u00ebr ngritjen e Bazeve t\u00eb Dh\u00ebnash lokale p\u00ebr zhvillimin;<\/li>\n<li><code>docker-compose.local.workers.yml<\/code> p\u00ebr ngritjen lokale t\u00eb pun\u00ebtor\u00ebve, Baz\u00ebs t\u00eb Dh\u00ebnash, Redis dhe RabbitMQ;<\/li>\n<li><code>docker-compose.test.yml<\/code> p\u00ebr ekzekutimin e testeve gjat\u00eb vendosjes;<\/li>\n<li><code>docker-compose.yml<\/code> p\u00ebr depolin.<\/li>\n<\/ul>\n<p>\nDhe folderi i fundit q\u00eb na intereson \u00ebsht\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/.ci-cd\">.ci-cd<\/a><\/noindex>. N\u00eb t\u00eb gjenden skriptet shell p\u00ebr vendosje:<\/p>\n<ul>\n<li><code>deploy.sh<\/code> \u2014 nisja e migrimit dhe depolimit. Nis n\u00eb server pas nd\u00ebrtimit dhe ekzekutimit t\u00eb testeve n\u00eb Github Actions;<\/li>\n<li><code>rollback.sh<\/code> \u2014 kthimi i konteiner\u00ebve n\u00eb versionin e m\u00ebparsh\u00ebm t\u00eb nd\u00ebrtimit;<\/li>\n<li><code>curl_tg.sh<\/code> \u2014 d\u00ebrgimi i njoftimeve p\u00ebr desplejtimin n\u00eb Telegram.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Frontend n\u00eb Angular<\/h2>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld-front\">Repoja me frontendin<\/a><\/noindex> \u00ebsht\u00eb shum\u00eb m\u00eb e thjesht\u00eb se backendi. Fronti p\u00ebrb\u00ebhet nga tre faqe:<\/p>\n<ul>\n<li>Faqja kryesore me nj\u00eb form\u00eb p\u00ebr d\u00ebrgimin e emailit dhe nj\u00eb buton p\u00ebr dalje.<\/li>\n<li>Faqja e hyrjes.<\/li>\n<li>Faqja e regjistrimit.<\/li>\n<\/ul>\n<p>\nFaqja kryesore duket askejtike:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/4db36add2c4277397724b0d71b96ff06.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nN\u00eb rr\u00ebnj\u00eb ndodhen dy skedar\u00eb <code>Dockerfile<\/code> dhe <code>docker-compose.yml<\/code>, si dhe nj\u00eb dosje e njohur p\u00ebr ne <code>.ci-cd<\/code> me nj\u00eb num\u00ebr pak m\u00eb t\u00eb vog\u00ebl skriptesh se n\u00eb repo-n e backendit (skriptet p\u00ebr ekzekutimin e testeve jan\u00eb hequr).<\/p>\n<h1>Krijojm\u00eb projektin n\u00eb Plesk<\/h1>\n<p>\nT\u00eb fillojm\u00eb me konfigurimin e Plesk dhe krijimin e nj\u00eb abonimi p\u00ebr faqen ton\u00eb.<\/p>\n<h2>Instalimi i zgjerimeve<\/h2>\n<p>\nN\u00eb Plesk na nevojiten kat\u00ebr zgjerime: <\/p>\n<ul>\n<li><code>Docker<\/code> p\u00ebr menaxhimin dhe shfaqjen vizuale t\u00eb gjendjes s\u00eb konteiner\u00ebve n\u00eb administrat\u00ebn e Plesk;<\/li>\n<li><code>Git<\/code> p\u00ebr t\u00eb konfiguruar hapat e dep limit n\u00eb server;<\/li>\n<li><code>Let's Encrypt<\/code> p\u00ebr gjenerimin (dhe rinovimin automatik) e sertifikatave falas TLS;<\/li>\n<li><code>Firewall<\/code> p\u00ebr t\u00eb konfiguruar filtrimin e trafikut t\u00eb ardhsh\u00ebm.<\/li>\n<\/ul>\n<p>\nMund t'i instalojm\u00eb ato p\u00ebrmes administrat\u00ebs Plesk n\u00eb seksionin Zgjerime:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/350cf7d7ca3ae1a965a0d3f8a73594ef.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nNe nuk do ta shqyrtojm\u00eb konfigurimin e detajuar t\u00eb zgjerimeve, p\u00ebr q\u00ebllimet tona demo do t\u00eb mjaftojn\u00eb cil\u00ebsimet e parazgjedhura.<\/p>\n<h2>Krijimi i abonimit dhe faqes<\/h2>\n<p>\nM\u00eb pas na nevojitet t\u00eb krijojm\u00eb nj\u00eb abonim p\u00ebr faqen ton\u00eb helloworld.ru dhe t\u00eb shtojm\u00eb nj\u00eb subdomain dev.helloworld.ru.<\/p>\n<ol>\n<li>Krijojm\u00eb nj\u00eb abonim p\u00ebr domainin helloworld.ru dhe tregojm\u00eb emrin e p\u00ebrdoruesit dhe fjal\u00ebkalimin p\u00ebr p\u00ebrdoruesin sistemor:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/3932dc7492aa523b6cbd540ad7a7fe6b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nN\u00eb fund t\u00eb faqes vendosim nj\u00eb kontrol <i>Sigurohuni domainin me Let&#8217;s Encrypt<\/i>, n\u00ebse duam t\u00eb konfigurojm\u00eb HTTPS p\u00ebr faqen:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f4d23a34764fdeb411fe2ca9cc95cb45.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>M\u00eb pas n\u00eb k\u00ebt\u00eb abonim krijojm\u00eb subdomain dev.helloworld.ru (p\u00ebr t\u00eb cilin gjithashtu mund t\u00eb nxjerrim nj\u00eb sertifikat falas TLS):\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/d57e6ba71454cb537917400de4275e92.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p><\/p>\n<h1>Instalimi i komponent\u00ebve serverik\u00eb<\/h1>\n<p>\nNe kemi n\u00eb dispozicion nj\u00eb server me <i>OS Debian Stretch 9.12<\/i> dhe panelin e menaxhimit t\u00eb instaluar <i>Plesk Obsidian 18.0.27<\/i>.<\/p>\n<p>Na nevojitet t\u00eb instalojm\u00eb dhe konfiguroni p\u00ebr projektin ton\u00eb:<\/p>\n<ul>\n<li>PostgreSQL (n\u00eb rastin ton\u00eb do t\u00eb jet\u00eb nj\u00eb server me dy DB p\u00ebr mjedisin dev dhe prod).<\/li>\n<li>RabbitMQ (t\u00eb nj\u00ebjt\u00ebn gj\u00eb, nj\u00eb instanc\u00eb me vhosts t\u00eb ndrysh\u00ebm p\u00ebr mjediset).<\/li>\n<li>Dy instanca Redis (p\u00ebr mjediset dev dhe prod).<\/li>\n<li>Docker Registry (p\u00ebr ruajtjen lokale t\u00eb imazheve Docker t\u00eb nd\u00ebrtuara).<\/li>\n<li>UI-interfaca p\u00ebr regjistrin Docker.<\/li>\n<\/ul>\n<p><\/p>\n<h2>PostgreSQL<\/h2>\n<p>\nN\u00eb paket\u00eb me Plesk vjen gjithashtu DB PostgreSQL, por jo versioni m\u00eb i fundit (n\u00eb koh\u00ebn e shkrimit t\u00eb k\u00ebtij artikulli Plesk Obsidian <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.plesk.com\/release-notes\/obsidian\/software-requirements\/\">mb\u00ebshteste<\/a><\/noindex> Postgres versionet 8.4\u201310.8). Ne duam p\u00ebr aplikacionin ton\u00eb versionin m\u00eb t\u00eb fundit (12.3 n\u00eb koh\u00ebn e shkrimit t\u00eb k\u00ebtij artikulli), prandaj do ta instalojm\u00eb at\u00eb manualisht.<\/p>\n<p>Ka shum\u00eb udh\u00ebzime t\u00eb detajuara p\u00ebr instalimin e Postgres n\u00eb Debian n\u00eb internet (<noindex><a rel=\"nofollow\" href=\"https:\/\/tecadmin.net\/install-postgresql-on-debian-9-stretch\/\">\u00ebsht\u00eb<\/a><\/noindex>), prandaj nuk do t'i p\u00ebrshkruaj n\u00eb detaje, vet\u00ebm do t\u00eb sjell komandat:<\/p>\n<pre><code class=\"bash\">wget -q https:\/\/www.postgresql.org\/media\/keys\/ACCC4CF8.asc -O - | sudo apt-key add -\nsudo sh -c 'echo \"deb http:\/\/apt.postgresql.org\/pub\/repos\/apt\/ stretch-pgdg main\" &gt;&gt; \/etc\/apt\/sources.list.d\/pgdg.list'\n\nsudo apt-get update\nsudo apt-get install postgresql postgresql-contrib\n<\/code><\/pre>\n<p>\nDuke marr\u00eb parasysh se postavijet e paracaktuar n\u00eb PostgreSQL jan\u00eb mjaft mesatare, \u00ebsht\u00eb e domosdoshme t\u00eb rregullojm\u00eb konfigurimin. K\u00ebt\u00eb do ta ndihmojm\u00eb me <noindex><a rel=\"nofollow\" href=\"http:\/\/pgconfigurator.cybertec.at\/\">nj\u00eb kalkulator<\/a><\/noindex>: duhet t\u00eb vendosni parametrat e serverit tuaj dhe t\u00eb z\u00ebvend\u00ebsoni konfigurimet n\u00eb skedarin <code>\/etc\/postgresql\/12\/main\/postgresql.conf<\/code>me ato t\u00eb sugjeruara. K\u00ebtu duhet t\u00eb theksohet se k\u00ebto kalkulator\u00eb nuk jan\u00eb nj\u00eb zgjidhje magjike, dhe baza duhet t\u00eb optimizohet m\u00eb n\u00eb detaje, duke u bazuar n\u00eb harduerin tuaj, aplikacionin dhe kompleksitetin e k\u00ebrkesave. Por p\u00ebr fillim, kjo \u00ebsht\u00eb e mjaftueshme.<\/p>\n<p>P\u00ebrve\u00e7 konfigurimeve t\u00eb propozuara nga kalkulatori, gjithashtu ndryshojm\u00eb n\u00eb <code>postgresql.conf<\/code>portin 5432 t\u00eb vendosur si parazgjedhje n\u00eb nj\u00eb tjet\u00ebr (n\u00eb shembullin ton\u00eb \u2014 <strong>53983<\/strong>).<\/p>\n<p>Pas ndryshimit t\u00eb skedarit t\u00eb konfigurimit, rihapim postgresql-server me komand\u00ebn:<\/p>\n<pre><code class=\"bash\">service postgresql restart\n<\/code><\/pre>\n<p>\nKemi instaluar dhe konfiguruar PostgreSQL. Tani do t\u00eb krijojm\u00eb nj\u00eb DB, p\u00ebrdoruesit p\u00ebr mjediset dev dhe prod, dhe do t'u japim p\u00ebrdoruesve t\u00eb drejtat p\u00ebr t\u00eb menaxhuar DB-n\u00eb:<\/p>\n<pre><code class=\"bash\">$ su - postgres\npostgres:~$ create database hw_dev_db_name;\nCREATE DATABASE\npostgres:~$ create user hw_dev_db_user with password 'hw_dev_db_password';\nCREATE ROLE\npostgres:~$ grant ALL privileges ON database hw_dev_db_name to hw_dev_db_user;\nGRANT\npostgres:~$ create database hw_prod_db_name;\nCREATE DATABASE\npostgres:~$ create user hw_prod_db_user with password 'hw_prod_db_password';\nCREATE ROLE\npostgres:~$ grant ALL privileges ON database hw_prod_db_name to hw_prod_db_user;\nGRANT\n<\/code><\/pre>\n<p><\/p>\n<h2>RabbitMQ<\/h2>\n<p>\nTani do t\u00eb kalojm\u00eb te instalimi i RabbitMQ \u2014 broker p\u00ebr mesazhe p\u00ebr Celery. Instalimi i tij n\u00eb Debian \u00ebsht\u00eb mjaft i thjesht\u00eb:<\/p>\n<pre><code class=\"bash\">wget https:\/\/packages.erlang-solutions.com\/erlang-solutions_1.0_all.deb\nsudo dpkg -i erlang-solutions_1.0_all.deb\n\nsudo apt-get update\nsudo apt-get install erlang erlang-nox\n\nsudo add-apt-repository 'deb http:\/\/www.rabbitmq.com\/debian\/ testing main'\nwget -O- https:\/\/www.rabbitmq.com\/rabbitmq-release-signing-key.asc | sudo apt-key add -\n\nsudo apt-get update\nsudo apt-get install rabbitmq-server\n<\/code><\/pre>\n<p>\nPas instalimit, na nevojitet t\u00eb krijojm\u00eb <i>vhosts<\/i>, p\u00ebrdoruesit dhe t'u japim t\u00eb drejtat e nevojshme:<\/p>\n<pre><code class=\"bash\">sudo rabbitmqctl add_user hw_dev_amqp_user hw_dev_amqp_password \nsudo rabbitmqctl set_user_tags hw_dev_amqp_user administrator\nsudo rabbitmqctl add_vhost hw_dev_vhost\nsudo rabbitmqctl set_permissions -p hw_dev_vhost hw_dev_amqp_user \".*\" \".*\" \".*\"\n\nsudo rabbitmqctl add_user hw_prod_amqp_user hw_prod_amqp_password \nsudo rabbitmqctl set_user_tags hw_prod_amqp_user administrator\nsudo rabbitmqctl add_vhost hw_prod_vhost\nsudo rabbitmqctl set_permissions -p hw_prod_vhost hw_prod_amqp_user \".*\" \".*\" \".*\"\n<\/code><\/pre>\n<p><\/p>\n<h2>Redis<\/h2>\n<p>\nTani do t\u00eb instalojm\u00eb dhe konfigurojm\u00eb komponentin e fundit p\u00ebr aplikacionin ton\u00eb \u2014 Redis. Ai do t\u00eb p\u00ebrdoret si backend p\u00ebr ruajtjen e rezultateve t\u00eb detyrave Celery.<\/p>\n<p>Ne do t\u00eb ngrem\u00eb dy kontejner\u00eb Docker me Redis p\u00ebr ambientet dev dhe prod duke p\u00ebrdorur zgjerimin <code>Docker<\/code> p\u00ebr Plesk.<\/p>\n<ol>\n<li>Hyni n\u00eb Plesk, kalojm\u00eb n\u00eb seksionin Shtesat, k\u00ebrkojm\u00eb shtes\u00ebn Docker dhe e instalojm\u00eb at\u00eb (na nevojitet versioni falas):\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/5638f9b40274e4f7441434279c76a426.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Kalim n\u00eb shtes\u00ebn e instaluar, gjejm\u00eb p\u00ebrmes k\u00ebrkimit imazhin <code>redis bitnami<\/code> dhe vendosim versionin e fundit:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/578bbbed6a66a60a4f7410f7d61ea542.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Hyni n\u00eb kontejnerin e shkarkuar dhe rregullojm\u00eb konfigurimin: specifikojm\u00eb portin, madh\u00ebsin\u00eb maksimale t\u00eb RAM-it, fjal\u00ebkalimin n\u00eb variablat e mjedisit dhe montojm\u00eb volum:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/8bc804b794735412f5e510b3049c5667.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Kryejm\u00eb hapat 2-3 p\u00ebr kontejnerin prod, n\u00eb cil\u00ebsimet vet\u00ebm ndryshojm\u00eb parametrat: portin, fjal\u00ebkalimin, madh\u00ebsin\u00eb e RAM-it dhe rrug\u00ebn p\u00ebr dosjen e volumit n\u00eb server:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/3af50181c8b3e1ace23a8de11826cb51.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p><\/p>\n<h2>Docker Registry<\/h2>\n<p>\nP\u00ebrve\u00e7 sh\u00ebrbimeve baz\u00eb, do t\u00eb ishte mir\u00eb t\u00eb vendosnim n\u00eb server nj\u00eb depo t\u00eb vet\u00eb vonuar t\u00eb imazheve Docker. Fatmir\u00ebsisht, vendi n\u00eb servera tani \u00ebsht\u00eb mjaft i lir\u00eb (me siguri m\u00eb lir\u00eb se pajtimi me DockerHub), dhe procesi i instalimit t\u00eb nj\u00eb depoje private \u00ebsht\u00eb shum\u00eb i thjesht\u00eb. <\/p>\n<p>Duam q\u00eb t\u00eb kemi t\u00eb instaluar:<\/p>\n<ul>\n<li>depo Docker me fjal\u00ebkalim, e qasshme me subdomen <noindex><a rel=\"nofollow\" href=\"https:\/\/docker.helloworld.ru\">https:\/\/docker.helloworld.ru<\/a><\/noindex>;<\/li>\n<li>UI-interfasha p\u00ebr shikimin e imazheve n\u00eb depo, e qasshme n\u00eb adres\u00ebn <noindex><a rel=\"nofollow\" href=\"https:\/\/docker-ui.helloworld.ru\">https:\/\/docker-ui.helloworld.ru<\/a><\/noindex>.<\/li>\n<\/ul>\n<p>\nP\u00ebr k\u00ebt\u00eb:<\/p>\n<ol>\n<li>Do t\u00eb krijojm\u00eb n\u00eb Plesk dy subdomen\u00eb n\u00eb pajtimin ton\u00eb: docker.helloworld.ru dhe docker-ui.helloworld.ru, dhe do t\u00eb konfigurojm\u00eb p\u00ebr ta certifikatat Let\u2019s Encrypt.<\/li>\n<li>N\u00eb dosjen e subdomenit docker.helloworld.ru do t\u00eb shtojm\u00eb nj\u00eb sked\u00eb <code>docker-compose.yml<\/code> me k\u00ebt\u00eb p\u00ebrmbajtje:\n<pre><code class=\"plaintext\">version: \"3\"\n\nservices:\n  docker-registry:\n    image: \"registry:2\"\n    restart: always\n    ports:\n      - \"53985:5000\"\n    environment:\n      REGISTRY_AUTH: htpasswd\n      REGISTRY_AUTH_HTPASSWD_REALM: basic-realm\n      REGISTRY_AUTH_HTPASSWD_PATH: \/auth\/.htpasswd\n      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: \/data\n    volumes:\n      - .\/.docker-registry.htpasswd:\/auth\/.htpasswd\n      - .\/data:\/data\n\n  docker-registry-ui:\n    image: konradkleine\/docker-registry-frontend:v2\n    restart: always\n    ports:\n      - \"53986:80\"\n    environment:\n      VIRTUAL_HOST: '*, https:\/\/*'\n      ENV_DOCKER_REGISTRY_HOST: 'docker-registry'\n      ENV_DOCKER_REGISTRY_PORT: 5000\n    links:\n      - 'docker-registry'\n<\/code><\/pre>\n<p>\n<\/li>\n<li>Me SSH do t\u00eb gjenerojm\u00eb sked\u00ebn .htpasswd p\u00ebr autorizimin Basic n\u00eb depo Docker:\n<pre><code class=\"plaintext\">htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password<\/code><\/pre>\n<\/li>\n<li>Do t\u00eb nd\u00ebrtosh dhe ngrit\u00ebsh kontejner\u00ebt:\n<pre><code class=\"plaintext\">docker-compose up -d<\/code><\/pre>\n<\/li>\n<li>Dhe duhet t\u00eb drejtojm\u00eb Nginx drejt kontejner\u00ebve tan\u00eb. Kjo mund t\u00eb b\u00ebhet p\u00ebrmes Plesk. <\/li>\n<\/ol>\n<p>\nVeprimet e m\u00ebposhtme duhet t\u00eb kryhen p\u00ebr subdomen\u00ebt docker.helloworld.ru dhe docker-ui.helloworld.ru:<\/p>\n<p>N\u00eb seksionin <i>Dev Tools<\/i> n\u00eb faqen ton\u00eb hyni n\u00eb <i>Rregullat e Proxy t\u00eb Dockerit<\/i>:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/d9c05901d95d61ce5db27a1a7cfddf49.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDhe shtoni nj\u00eb rregull p\u00ebr nj\u00eb proxy t\u00eb trafikut t\u00eb ardhsh\u00ebm n\u00eb kontejnerin ton\u00eb:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/faa85cf6da648ef55b7c87c44040efb1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<ol>\n<li>Kontrollojm\u00eb n\u00ebse mund t\u00eb autorizojm\u00eb n\u00eb kontejnerin ton\u00eb nga makina lokale:\n<pre><code class=\"plaintext\">$ docker login docker.helloworld.ru -u hw_docker_admin -p hw_docker_password\nWARNING! Using --password via the CLI is insecure. Use --password-stdin.\nLogin Succeeded<\/code><\/pre>\n<\/li>\n<li>Po ashtu do t\u00eb kontrollojm\u00eb funksionimin e subdomenit docker-ui.helloworld.ru:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/fdd6e1396c27c02a88bcbd7efb12f247.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDuke kliku n\u00eb Browse repositories, shfletuesi do t\u00eb tregoj\u00eb nj\u00eb dritare p\u00ebr autorizimin, ku duhet t\u00eb futni emrin e p\u00ebrdoruesit dhe fjal\u00ebkalimin p\u00ebr repositorin. Pas k\u00ebsaj, do t\u00eb na \u00e7oj\u00eb n\u00eb nj\u00eb faqe me list\u00ebn e repositor\u00ebve (n\u00eb fillim ajo do t\u00eb jet\u00eb bosh):<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f2d75edb530e9d746095ae02d7793c1f.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p><\/p>\n<h2>Hapim portat n\u00eb Plesk Firewall<\/h2>\n<p>\nPas instalimit dhe konfigurimit t\u00eb komponenteve, duhet t\u00eb hapim portat q\u00eb komponentet t\u00eb jen\u00eb t\u00eb qassh\u00ebm nga konteiner\u00ebt Docker dhe nga rrjeti i jasht\u00ebm.<\/p>\n<p>Le t\u00eb shohim si ta b\u00ebjm\u00eb k\u00ebt\u00eb, me shembullin e extensions Firewall p\u00ebr Plesk q\u00eb kemi instaluar m\u00eb par\u00eb.<\/p>\n<ol>\n<li>Kalojm\u00eb te <i>Tools &amp; Settings &gt; Settings &gt; Firewall<\/i>:<br \/>\n<img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/d54b4941944fe191574472a475cbaebe.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Kalojm\u00eb te <i>Modifiko rregullat e Plesk Firewall &gt; Shto Rregull t\u00eb Personalizuar<\/i> dhe hapim portat TCP n\u00eb subnetin Docker (<strong>172.0.0.0\/8)<\/strong>:<br \/>\nRabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614<br \/>\nRedis: 32785, 32786<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/3359845f9bd6dc303274da737d4b27a2.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Gjithashtu do t\u00eb shtojm\u00eb nj\u00eb rregull q\u00eb do t\u00eb hap\u00eb portat p\u00ebr PostgreSQL dhe panelin e menaxhimit t\u00eb RabbitMQ p\u00ebr bot\u00ebn e jashtme:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f812cfc7127da469507538ea48b2c80d.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>P\u00ebrdorim rregullat me butonin Apply Changes:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/e85444ae717aaefa796664003fc86578.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p><\/p>\n<h1>Konfigurimi i CI\/CD n\u00eb Github Actions<\/h1>\n<p>\nLe t\u00eb fillojm\u00eb me pjes\u00ebn m\u00eb interesante \u2014 konfigurimin e pipeline p\u00ebr integrimin dhe dor\u00ebzimin e projektit ton\u00eb n\u00eb server.<\/p>\n<p>Ky pipeline do t\u00eb p\u00ebrb\u00ebhet nga dy pjes\u00eb: <\/p>\n<ul>\n<li>n\u00eb nd\u00ebrtimin e imazhit dhe ekzekutimin e testeve (p\u00ebr backend) \u2014 n\u00eb an\u00ebn e Github;<\/li>\n<li>ekzekutimi i migrimeve (p\u00ebr backend) dhe shp\u00ebrndarja e konteiner\u00ebve \u2014 n\u00eb server.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Shp\u00ebrndarja n\u00eb Plesk<\/h2>\n<p>\nS\u00eb pari do t\u00eb merremi me pik\u00ebn e dyt\u00eb (sepse ndikon n\u00eb t\u00eb par\u00ebn).<\/p>\n<p>Procesi i shp\u00ebrndarjes do ta vendosim me ndihm\u00ebn e plugin-it Git p\u00ebr Plesk.<\/p>\n<p>Le t\u00eb shqyrtojm\u00eb nj\u00eb shembull me ambientin Prod p\u00ebr repositorin e Backend.<\/p>\n<ol>\n<li>Hym\u00eb n\u00eb abonimin e faqes son\u00eb Helloworld dhe kalojm\u00eb n\u00eb n\u00ebnseksionin Git:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/b55b371560ea87a2954b6553a7cefc49.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Futni n\u00eb fush\u00ebn \"Remote Git repository\" lidhjen p\u00ebr repositorin ton\u00eb n\u00eb Github dhe ndryshoni folderin nga e para <code>httpdocs<\/code> n\u00eb nj\u00eb tjet\u00ebr (p\u00ebr shembull, <code>\/httpdocs\/hw_back<\/code>):\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/db9ba9adb6e2e1bed5da7ae8e88c76e1.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Kopjojm\u00eb \u00e7el\u00ebsin publik SSH nga faza e m\u00ebparshme dhe <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/settings\/ssh\/new\">shtojm\u00eb<\/a><\/noindex> e vendosim n\u00eb konfigurimet e Github.<\/li>\n<li>Klikoni OK n\u00eb ekranin n\u00eb pik\u00ebn 2, pas s\u00eb cil\u00ebs do t\u00eb na \u00e7oj\u00eb n\u00eb faqen e repositorit n\u00eb Plesk. Tani duhet t\u00eb konfigurojm\u00eb p\u00ebrdit\u00ebsimin e repositorit gjat\u00eb komiteteve n\u00eb deg\u00ebn master. P\u00ebr k\u00ebt\u00eb kalojm\u00eb n\u00eb <i>Repository Settings<\/i> dhe ruajm\u00eb vler\u00ebn <code>Webhook URL<\/code> (do na nevojitet m\u00eb von\u00eb gjat\u00eb konfigurimit t\u00eb Github Actions):\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/14d48a357f821d734d40dc434ab3682a.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>N\u00eb fush\u00ebn e Actions n\u00eb ekranin nga pika paraprake, vendosim skriptin p\u00ebr t\u00eb nisur shp\u00ebrndarjen:\n<pre><code class=\"plaintext\">cd {REPOSITORY_ABSOLUTE_PATH}\n.ci-cd\/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID} <\/code><\/pre>\n<p>\nku: <\/p>\n<p><code>{REPOSITORY_ABSOLUTE_PATH}<\/code> \u2014 rruga e folderit prod t\u00eb repositorit backend n\u00eb server;<br \/>\n<code>{ENV}<\/code> \u2014 ambienti (dev\/prod), n\u00eb rastin ton\u00eb <code>prod<\/code>;<br \/>\n<code>{DOCKER_REGISTRY_HOST}<\/code> \u2014 hosti i repositorit ton\u00eb docker<br \/>\n<code>{TG_BOT_TOKEN}<\/code> \u2014 tokeni i botit Telegram;<br \/>\n<code>{TG_CHAT_ID}<\/code> \u2014 ID e bised\u00ebs\/kanalit p\u00ebr d\u00ebrgimin e njoftimeve.<\/p>\n<p>Shembulli i skriptit:<\/p>\n<pre><code class=\"plaintext\">cd \/var\/www\/vhosts\/helloworld.ru\/httpdocs\/hw_back\/\n.ci-cd\/deploy.sh dev docker.helloworld.ru docker_user docker_password 12345678:AAbcdEfghCH1vGbCasdfSAs0K5PALDsaw -1001234567890<\/code><\/pre>\n<\/li>\n<li>Shtojm\u00eb p\u00ebrdoruesin nga abonimi yn\u00eb n\u00eb grupin Docker (q\u00eb t\u00eb mund t\u00eb menaxhoj\u00eb kontejner\u00ebt):\n<pre><code class=\"plaintext\">sudo usermod -aG docker helloworld_admin<\/code><\/pre>\n<\/li>\n<\/ol>\n<p>\nMjedisi Dev p\u00ebr repositorin backend dhe frontend konfigurohen n\u00eb m\u00ebnyr\u00eb t\u00eb ngjashme.<\/p>\n<h2>Pipeline i deploy-it n\u00eb Github Actions<\/h2>\n<p>\nKalojm\u00eb n\u00eb konfigurimin e pjes\u00ebs s\u00eb par\u00eb t\u00eb CI\/CD pipelines ton\u00eb n\u00eb Github Actions.<\/p>\n<h3>Backend<\/h3>\n<p>\nPipeline p\u00ebrshkruhet n\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/blob\/master\/.github\/workflows\/deploy.yml\">skedarin deploy.yml<\/a><\/noindex>. <\/p>\n<p>Por para se ta shqyrtojm\u00eb, le t\u00eb plot\u00ebsojm\u00eb n\u00eb Github variable Secret q\u00eb na nevojiten. P\u00ebr k\u00ebt\u00eb kalojm\u00eb n\u00eb <i>Cil\u00ebsimet -&gt; Sekretet<\/i>:<\/p>\n<ul>\n<li><code>DOCKER_REGISTRY<\/code> \u2014 host-i i repositorit ton\u00eb Docker (docker.helloworld.ru);<\/li>\n<li><code>DOCKER_LOGIN<\/code> \u2014 logari p\u00ebr repositorin Docker;<\/li>\n<li><code>DOCKER_PASSWORD<\/code> \u2014 fjal\u00ebkalimi p\u00ebr t\u00eb;<\/li>\n<li><code>DEPLOY_HOST<\/code> \u2014 host-i ku admin panel-i Plesk \u00ebsht\u00eb e aksesueshme (p.sh.: <noindex><a rel=\"nofollow\" href=\"https:\/\/helloworld.ru\">helloworld.ru<\/a><\/noindex>:8443 ose <noindex><a rel=\"nofollow\" href=\"http:\/\/123.4.56.78\">123.4.56.78<\/a><\/noindex>:8443);<\/li>\n<li><code>DEPLOY_BACK_PROD_TOKEN<\/code> \u2014 token-i p\u00ebr deploy n\u00eb repo-prod n\u00eb server (e kemi marr\u00eb at\u00eb n\u00eb Ngritjen n\u00eb Plesk pika 4);<\/li>\n<li><code>DEPLOY_BACK_DEV_TOKEN<\/code> \u2014 token-i p\u00ebr deploy n\u00eb repo-dev n\u00eb server.<\/li>\n<\/ul>\n<p>\nProcesi i deploy-it \u00ebsht\u00eb i thjesht\u00eb dhe p\u00ebrb\u00ebhet nga tre hapa kryesor\u00eb: <\/p>\n<ul>\n<li>nd\u00ebrtimi dhe publikimi i imazhit n\u00eb repositorin ton\u00eb;<\/li>\n<li>ekzekutimi i testeve n\u00eb konteinerin e bazuar n\u00eb imazhin e sapo nd\u00ebrtuar;<\/li>\n<li>implementimi n\u00eb mjedisin e nevojsh\u00ebm n\u00eb var\u00ebsi t\u00eb deg\u00ebs (dev\/master).<\/li>\n<\/ul>\n<p><\/p>\n<h3>Frontend<\/h3>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld-front\/blob\/master\/.github\/workflows\/deploy.yml\">Skedari deploy.yml p\u00ebr repositorin frontend<\/a><\/noindex> nuk ndryshon shum\u00eb nga ai i backend-it. N\u00eb t\u00eb mungon hapi me ekzekutimin e testeve dhe emrat e token-ave p\u00ebr deploy ndryshojn\u00eb. Sektret p\u00ebr repositorin frontend, p\u00ebr m\u00eb shum\u00eb, duhet t\u00eb plot\u00ebsohen ve\u00e7mas.<\/p>\n<h1>Konfigurimi i faqes<\/h1>\n<p><\/p>\n<h2>Proximi i trafikut p\u00ebrmes Nginx<\/h2>\n<p>\nE pra, kemi arritur n\u00eb fund. Mbete vet\u00ebm t\u00eb konfigurojm\u00eb proksimin e trafikut hyr\u00ebs dhe dal\u00ebs n\u00eb kontejnerin ton\u00eb p\u00ebrmes Nginx. Ky proces e kemi shqyrtuar tashm\u00eb n\u00eb pik\u00ebn 5 t\u00eb konfigurimit t\u00eb Docker Registry. E nj\u00ebjta gj\u00eb duhet t\u00eb p\u00ebrs\u00ebritet p\u00ebr pjes\u00ebt backend dhe frontend n\u00eb mjediset dev dhe prod.<\/p>\n<p>Do t\u00eb jap disa ekran\u00eb t\u00eb konfigurimeve.<\/p>\n<h3>Backend<\/h3>\n<p>\n<img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f3c38dc1c25b648db000c72ef2d30b2a.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h3>Frontend<\/h3>\n<p>\n<img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr nj\u00eb projekt me Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/35d4d8ef3489608db1e173b7f214ca03.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<strong>Sqarim i r\u00ebnd\u00ebsish\u00ebm<\/strong>. N\u00eb konteinerin frontend do t\u00eb proksisohen t\u00eb gjitha URL-t\u00eb, p\u00ebrve\u00e7 atyre q\u00eb fillojn\u00eb me <code>\/api\/<\/code> \u2014 ato do t\u00eb proksisohen n\u00eb konteinerin backend (prandaj <strong>n\u00eb konteinerin backend t\u00eb gjith\u00eb procesor\u00ebt duhet t\u00eb fillojn\u00eb me <\/strong><strong><code>\/api\/<\/code><\/strong>).<\/p>\n<h2>P\u00ebrfundime<\/h2>\n<p>\nTani faqja jon\u00eb duhet t\u00eb jet\u00eb e aksesueshme n\u00eb adresat helloworld.ru dhe dev.helloworld.ru (mjedisi prod dhe dev p\u00ebrkat\u00ebsisht).<\/p>\n<p>T\u00eb klarojm\u00eb, m\u00ebsuam se si t\u00eb p\u00ebrgatisim nj\u00eb aplikacion t\u00eb thjesht\u00eb n\u00eb Flask dhe Angular dhe t\u00eb konfigurojm\u00eb n\u00eb Github Actions pipeline-in p\u00ebr ta ekzekutuar at\u00eb n\u00eb serverin n\u00ebn administrat\u00ebn e Plesk.<\/p>\n<p>Do t\u00eb ripjegoj lidhjet n\u00eb repositor\u00ebt me kodin: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\">backend<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld-front\">frontend<\/a><\/noindex>.<br \/>\n<br \/>Burimi: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/domclick\/blog\/506802\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 CI\/CD \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f Plesk \u0438 Github Actions. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0431\u0443\u0434\u0435\u043c \u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u043d\u0435\u0437\u0430\u043c\u044b\u0441\u043b\u043e\u0432\u0430\u0442\u044b\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00abHelloworld\u00bb. \u041e\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 Python-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0435 Flask, \u0441 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c\u0438 \u043d\u0430 Celery \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c \u043d\u0430 Angular 8. \u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438: \u0431\u044d\u043a\u0435\u043d\u0434, \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434. \u0412 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043d\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":85647,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-85646","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"sq_AL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47CI\/CD \u0432 Github Actions \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 Flask+Angular | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-06-17T23:42:15+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-06-17T23:42:15+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular | ProHoster","description":"N\u00eb k\u00ebt\u00eb artikel do t\u00eb ndaj p\u00ebrvoj\u00ebn time.","canonical_url":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sq_AL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47CI\/CD \u0432 Github Actions \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 Flask+Angular | ProHoster","og:description":"\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u0434\u0435\u043b\u044e\u0441\u044c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c.","og:url":"https:\/\/prohoster.info\/sq\/blog\/administrirovanie\/ci-cd-v-github-actions-dlya-proekta-na-flask-angular","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-06-17T23:42:15+00:00","article:modified_time":"2020-06-17T23:42:15+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"85646","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 13:12:50","updated":"2022-09-29 06:56:26","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/85646","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/comments?post=85646"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/posts\/85646\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/media\/85647"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/media?parent=85646"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/categories?post=85646"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sq\/wp-json\/wp\/v2\/tags?post=85646"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}