{"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 projektin n\u00eb Flask+Angular","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb 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 me p\u00ebrdorimin e panelit t\u00eb kontrollit Plesk dhe Github Actions. Sot do t\u00eb m\u00ebsojm\u00eb si t\u00eb deploy nj\u00eb projekt t\u00eb thjesht\u00eb me titullin \"Helloworld\". Ai \u00ebsht\u00eb shkruar n\u00eb framework-un Python Flask, me pun\u00ebtor\u00eb n\u00eb Celery dhe frontend n\u00eb Angular 8.<\/p>\n<p><b>Linket e depove:<\/b> <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\">back-end<\/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 hedhim nj\u00eb v\u00ebshtrim mbi projektin ton\u00eb dhe pjes\u00ebt e tij. N\u00eb t\u00eb dyt\u00ebn, do t\u00eb kuptojm\u00eb si t\u00eb konfiguroni Plesk dhe t\u00eb instaloni zgjatjet dhe komponent\u00ebt e nevojsh\u00ebm (DB, RabbitMQ, Redis, Docker, etj.).<\/p>\n<p>N\u00eb pjes\u00ebn e tret\u00eb, p\u00ebrfundimisht do t\u00eb kuptojm\u00eb si t\u00eb configure pipeline p\u00ebr t\u00eb deploy projektin ton\u00eb n\u00eb server n\u00eb mjediset dev dhe prod. Pas k\u00ebsaj, do ta lancojm\u00eb sitin n\u00eb server.<\/p>\n<p>Dhe po, harrova t\u00eb prezantohem. Emri im \u00ebsht\u00eb Oleg Borzov, un\u00eb jam zhvillues fullstack n\u00eb ekipin CRM p\u00ebr menaxher\u00ebt e kredive hipoteke n\u00eb Domklik. <br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1>P\u00ebrmbledhja e projektit<\/h1>\n<p>\nP\u00ebr fillim, do t\u00eb shqyrtojm\u00eb dy repozita t\u00eb projektit - backend dhe frontend - dhe do t\u00eb kalojm\u00eb p\u00ebrmes kodit.<\/p>\n<h2>Pjesa backend: Flask+Celery<\/h2>\n<p>\nP\u00ebr backend kam marr\u00eb nj\u00eb kombinim mjaft t\u00eb njohur nd\u00ebr zhvilluesit e Python: frameworkun Flask (p\u00ebr API) dhe Celery (p\u00ebr radh\u00ebn e detyrave). P\u00ebrdoret SQLAlchemy si ORM. P\u00ebr migrimet aplikohet Alembic. P\u00ebr v\u00ebrtetimin e JSON n\u00eb endpoint-e p\u00ebrdoret Marshmallow.<\/p>\n<p>N\u00eb <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\">repozitorit<\/a><\/noindex> ekziston nj\u00eb sked\u00eb Readme.md me nj\u00eb p\u00ebrshkrim t\u00eb detajuar t\u00eb struktur\u00ebs dhe udh\u00ebzimeve p\u00ebr nisjen e projektit.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/app_web\">API e pjes\u00ebs web<\/a><\/noindex> \u00ebsht\u00eb mjaft e thjesht\u00eb, p\u00ebrb\u00ebhet nga 6 endpoint-e:<\/p>\n<ul>\n<li><code>\/ping<\/code> \u2014 p\u00ebr kontrollimin e disponueshm\u00ebris\u00eb;<\/li>\n<li>endpoint-e p\u00ebr regjistrim, autentifikim, \u00e7autentifikim dhe p\u00ebr t\u00eb marr\u00eb p\u00ebrdoruesin e identifikuar;<\/li>\n<li>endpoint p\u00ebr d\u00ebrgimin e email-it, q\u00eb vendos nj\u00eb detyr\u00eb n\u00eb radh\u00ebn Celery.<\/li>\n<\/ul>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/app_celery\">Pjesa e Celery<\/a><\/noindex> \u00ebsht\u00eb edhe m\u00eb e thjesht\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> jan\u00eb dy n\u00ebnfoldera: <\/p>\n<ul>\n<li><code>docker<\/code> me dy skeda Docker (<code>base.dockerfile<\/code> p\u00ebr nd\u00ebrtimin e imazhit t\u00eb baz\u00ebs 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 p\u00ebr variablat mjedisore p\u00ebr ambiente t\u00eb ndryshme. <\/li>\n<\/ul>\n<p>\nN\u00eb rr\u00ebnj\u00eb t\u00eb projektit ndodhen kat\u00ebr skedar\u00eb docker-compose:<\/p>\n<ul>\n<li><code>docker-compose.local.db.yml<\/code> p\u00ebr ngritjen e baz\u00ebs s\u00eb t\u00eb dh\u00ebnave lokale p\u00ebr zhvillim;<\/li>\n<li><code>docker-compose.local.workers.yml<\/code> p\u00ebr ngritjen lokale t\u00eb punonj\u00ebsve, baz\u00ebs s\u00eb t\u00eb dh\u00ebnave, Redis dhe RabbitMQ;<\/li>\n<li><code>docker-compose.test.yml<\/code> p\u00ebr ekzekutimin e testeve gjat\u00eb shp\u00ebrndarjes;<\/li>\n<li><code>docker-compose.yml<\/code> p\u00ebr deploy.<\/li>\n<\/ul>\n<p>\nDhe folderi i fundit interesant p\u00ebr ne \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\/tree\/master\/.ci-cd\">.ci-cd<\/a><\/noindex>. N\u00eb t\u00eb gjetur skriptet shell p\u00ebr vendosjen:<\/p>\n<ul>\n<li><code>deploy.sh<\/code> \u2014 nisja e migrimit dhe vendosjes. Aktivizohet n\u00eb server pas nd\u00ebrtimit dhe p\u00ebrmbushjes s\u00eb testeve n\u00eb Github Actions;<\/li>\n<li><code>rollback.sh<\/code> \u2014 rikthimi i kontejner\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 vendosjen 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 frontend<\/a><\/noindex> \u00ebsht\u00eb shum\u00eb m\u00eb e thjesht\u00eb se ajo e backend-it. Fronti p\u00ebrb\u00ebhet nga tri faqe:<\/p>\n<ul>\n<li>Faqja kryesore me nj\u00eb form\u00eb p\u00ebr d\u00ebrgimin e email-it dhe nj\u00eb buton p\u00ebr daljen.<\/li>\n<li>Faqja e hyrjes.<\/li>\n<li>Faqja e regjistrimit.<\/li>\n<\/ul>\n<p>\nFaqja kryesore duket askeptike:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb 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 backend-it (skriptet p\u00ebr fillimin e testeve jan\u00eb larguar).<\/p>\n<h1>Krijojm\u00eb projektin n\u00eb Plesk<\/h1>\n<p>\nLe t\u00eb fillojm\u00eb me konfigurimin e Plesk dhe krijimin e abonimit p\u00ebr sajtin ton\u00eb.<\/p>\n<h2>Instalimi i shtesave<\/h2>\n<p>\nN\u00eb Plesk do na nevojiten kat\u00ebr shtesa: <\/p>\n<ul>\n<li><code>Docker<\/code> p\u00ebr menaxhimin dhe shfaqjen vizuale t\u00eb gjendjes s\u00eb kontejner\u00ebve n\u00eb adminin e Plesk;<\/li>\n<li><code>Git<\/code> p\u00ebr konfigurimin e hapit t\u00eb vendosjes n\u00eb server;<\/li>\n<li><code>Let's Encrypt<\/code> p\u00ebr gjenerimin (dhe rinovimin automatik) e certifikatave falas TLS;<\/li>\n<li><code>Firewall<\/code> p\u00ebr konfigurimin e filtrimit t\u00eb trafikut q\u00eb hyn.<\/li>\n<\/ul>\n<p>\nMund t'i instalojm\u00eb ato p\u00ebrmes adminit t\u00eb Plesk n\u00eb seksionin Shtesat:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/350cf7d7ca3ae1a965a0d3f8a73594ef.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nNe do t\u00eb merremi me konfigurimin e detajuar t\u00eb shtesave, konfigurimet e paracaktuara do t\u00eb mjaftojn\u00eb p\u00ebr q\u00ebllimet tona demo.<\/p>\n<h2>Krijimi i nj\u00eb abonimi dhe nj\u00eb faqjeje<\/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 atje subdomain-in dev.helloworld.ru.<\/p>\n<ol>\n<li>Krijojm\u00eb nj\u00eb abonim p\u00ebr domenin helloworld.ru dhe specifikojm\u00eb emrin e p\u00ebrdoruesit dhe fjal\u00ebkalimin p\u00ebr p\u00ebrdoruesin sistemik:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/3932dc7492aa523b6cbd540ad7a7fe6b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nPosht\u00eb faqes, vendosim shenj\u00ebn e kontrollit <i>Sigurohuni domenin me Let\u2019s Encrypt<\/i>, n\u00ebse d\u00ebshirojm\u00eb t\u00eb konfigurojm\u00eb HTTPS p\u00ebr faqen:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb 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-in dev.helloworld.ru (p\u00ebr t\u00eb cilin gjithashtu mund t\u00eb l\u00ebshojm\u00eb nj\u00eb certifikat\u00eb falas TLS):\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb 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 me panelin e menaxhimit t\u00eb instaluar <i>Plesk Obsidian 18.0.27<\/i>.<\/p>\n<p>Na nevojitet t\u00eb instalojm\u00eb dhe konfigurojm\u00eb 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 ambientet dev dhe prod).<\/li>\n<li>RabbitMQ (po ashtu, nj\u00eb instanc\u00eb me vhosts t\u00eb ndrysh\u00ebm p\u00ebr ambientet).<\/li>\n<li>Dy instanca Redis (p\u00ebr ambientet dev dhe prod).<\/li>\n<li>Docker Registry (p\u00ebr ruajtjen lokale t\u00eb imazheve t\u00eb p\u00ebrmbledhura Docker).<\/li>\n<li>UI-interfaca p\u00ebr Docker registry.<\/li>\n<\/ul>\n<p><\/p>\n<h2>PostgreSQL<\/h2>\n<p>\nMe Plesk vjen edhe nj\u00eb DBMS PostgreSQL, megjithat\u00eb jo n\u00eb versionin m\u00eb t\u00eb ri (n\u00eb momentin e shkrimit t\u00eb artikullit Plesk Obsidian <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.plesk.com\/release-notes\/obsidian\/software-requirements\/\">mb\u00ebshteste<\/a><\/noindex> Ne duam t\u00eb vendosim versionin m\u00eb t\u00eb fundit t\u00eb Postgres (12.3 n\u00eb momentin e shkruajtjes s\u00eb k\u00ebtij artikulli) p\u00ebr aplikacionin ton\u00eb, prandaj do ta instalojm\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\/\">shembull<\/a><\/noindex>), prandaj nuk do t\u00eb p\u00ebrshkruaj me detaje, vet\u00ebm do t\u2019i jap 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 q\u00eb PostgreSQL ka konfigurime mjaft mesatare nga fabrika, \u00ebsht\u00eb e nevojshme t\u00eb rregullojm\u00eb konfigurimin. K\u00ebt\u00eb do ta ndihmojm\u00eb <noindex><a rel=\"nofollow\" href=\"http:\/\/pgconfigurator.cybertec.at\/\">llogarit\u00ebs<\/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. Duhet p\u00ebrmendur se kalkulator\u00ebt e till\u00eb nuk jan\u00eb zgjidhja magjike, dhe baza duhet t\u00eb tuneohet m\u00eb sakt\u00ebsisht, duke u bazuar n\u00eb harduerin tuaj, aplikacionin dhe kompleksitetin e k\u00ebrkesave. Por p\u00ebr fillimin, 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 n\u00eb m\u00ebnyr\u00eb t\u00eb paracaktuar me nj\u00eb tjet\u00ebr (n\u00eb shembullin ton\u00eb \u2014 <strong>53983<\/strong>).<\/p>\n<p>Pas ndryshimit t\u00eb skedarit t\u00eb konfigurimit, rishtazgjedhim postgresql-server me komand\u00ebn:<\/p>\n<pre><code class=\"bash\">service postgresql restart\n<\/code><\/pre>\n<p>\nNe kemi instaluar dhe konfiguruar PostgreSQL. Tani do t\u00eb krijojm\u00eb BAZAT e t\u00eb dh\u00ebnave, p\u00ebrdoruesit p\u00ebr ambientet dev dhe prod, dhe do t'u japim p\u00ebrdoruesve t\u00eb drejtat p\u00ebr t\u00eb menaxhuar baz\u00ebn e t\u00eb dh\u00ebnave:<\/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>\nT\u00eb kalojm\u00eb te instalimi i RabbitMQ \u2014 brokeri i mesazheve p\u00ebr Celery. Instalimi \u00ebsht\u00eb mjaft i thjesht\u00eb n\u00eb Debian:<\/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, ne duhet 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 me ndihm\u00ebn e zgjatjes <code>Docker<\/code> p\u00ebr Plesk.<\/p>\n<ol>\n<li>Hym\u00eb n\u00eb Plesk, kalojm\u00eb te seksioni Zgjerime, k\u00ebrkojm\u00eb zgjerimin Docker dhe e instalojm\u00eb (na nevojitet versioni falas):\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/5638f9b40274e4f7441434279c76a426.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Kalo n\u00eb zgjerimin e instaluar, k\u00ebrko me k\u00ebrkimin imazhin <code>redis bitnami<\/code> dhe vendos versionin m\u00eb t\u00eb fundit:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/578bbbed6a66a60a4f7410f7d61ea542.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Hym\u00eb n\u00eb kontejnerin e shkarkuar dhe korrigjojm\u00eb konfigurimin: p\u00ebrcaktojm\u00eb portin, madh\u00ebsin\u00eb maksimale t\u00eb RAM-it, fjal\u00ebkalimin n\u00eb variablat e mjedisit, dhe montojm\u00eb v\u00ebllimin:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb 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, vet\u00ebm ndryshojm\u00eb parametrat: portin, fjal\u00ebkalimin, madh\u00ebsin\u00eb e RAM-it dhe rrug\u00ebn p\u00ebr dosjen e v\u00ebllimit n\u00eb server:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb 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 bazike, do t\u00eb ishte mir\u00eb t\u00eb vendosnim n\u00eb serverin ton\u00eb nj\u00eb repository t\u00eb vetin t\u00eb imazheve Docker. Fatmir\u00ebsisht, vendi n\u00eb servera tani \u00ebsht\u00eb mjaft i lir\u00eb (me siguri m\u00eb i lir\u00eb se abonimi n\u00eb DockerHub), dhe procesi i instalimit t\u00eb nj\u00eb repository privat \u00ebsht\u00eb shum\u00eb i thjesht\u00eb. <\/p>\n<p>Ne duam q\u00eb t\u00eb kemi instaluar:<\/p>\n<ul>\n<li>nj\u00eb repository Docker me fjal\u00ebkalim, t\u00eb aksesuesh\u00ebm p\u00ebrmes nj\u00eb subdomeni <noindex><a rel=\"nofollow\" href=\"https:\/\/docker.helloworld.ru\">https:\/\/docker.helloworld.ru<\/a><\/noindex>;<\/li>\n<li>UI-i nd\u00ebrfaqes p\u00ebr shikimin e imazheve n\u00eb repositorin, e aksesueshme nga <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 podomene n\u00eb abonimin ton\u00eb: docker.helloworld.ru dhe docker-ui.helloworld.ru, dhe do t'i konfiguroni p\u00ebr ta p\u00ebrdorur certifikat\u00ebn Let\u2019s Encrypt.<\/li>\n<li>N\u00eb dosjen e podomenit docker.helloworld.ru do t\u00eb shtojm\u00eb skedarin <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>P\u00ebrmes SSH do t\u00eb gjenerojm\u00eb skedarin .htpasswd p\u00ebr autorizimin Basic n\u00eb repositorin 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\u00ebrtojm\u00eb dhe ngrem\u00eb kontenier\u00ebt:\n<pre><code class=\"plaintext\">docker-compose up -d<\/code><\/pre>\n<\/li>\n<li>Dhe duhet t\u00eb drejtojm\u00eb Nginx n\u00eb kontenier\u00ebt 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 podomene docker.helloworld.ru dhe docker-ui.helloworld.ru:<\/p>\n<p>N\u00eb seksionin <i>Dev Tools<\/i> n\u00eb faqen ton\u00eb shkojm\u00eb tek <i>Docker Proxy Rules<\/i>:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/d9c05901d95d61ce5db27a1a7cfddf49.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDhe shtojm\u00eb nj\u00eb rregull p\u00ebr t\u00eb prokuruar trafikun e hyrjes n\u00eb kontenierin ton\u00eb:<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/faa85cf6da648ef55b7c87c44040efb1.png\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<ol>\n<li>Po shikojm\u00eb n\u00ebse mund t\u00eb autorizohemi 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\nK\u00cbRC\u00cbNIM! P\u00ebrdorimi i --password p\u00ebrmes CLI \u00ebsht\u00eb i pasigurt. P\u00ebrdorni --password-stdin.\nAutorizimi u krye me sukses<\/code><\/pre>\n<\/li>\n<li>Gjithashtu do t\u00eb kontrollojm\u00eb funksionimin e subdomain-it docker-ui.helloworld.ru:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/fdd6e1396c27c02a88bcbd7efb12f247.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nKur t\u00eb klikoni n\u00eb Browse repositories, shfletuesi do t\u00eb hap\u00eb nj\u00eb dritare p\u00ebr autorizim, ku do t'ju duhet t\u00eb jepni emrin e p\u00ebrdoruesit dhe fjal\u00ebkalimin p\u00ebr depozit\u00ebn. Pas k\u00ebsaj, do t\u00eb na \u00e7oj\u00eb n\u00eb faqen me list\u00ebn e depozitave (tani p\u00ebr ju ajo do t\u00eb jet\u00eb bosh):<\/p>\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f2d75edb530e9d746095ae02d7793c1f.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<\/ol>\n<p><\/p>\n<h2>Hapni portat n\u00eb Plesk Firewall<\/h2>\n<p>\nPas instalimit dhe konfigurimit t\u00eb komponent\u00ebve, na nevojitet t\u00eb hapim portat q\u00eb komponent\u00ebt t\u00eb jen\u00eb t\u00eb aksesuesh\u00ebm nga kontejner\u00ebt Docker dhe rrjeti i jasht\u00ebm.<\/p>\n<p>Le t\u00eb shohim se si ta b\u00ebjm\u00eb k\u00ebt\u00eb me shembullin e zgjerimit t\u00eb Firewall p\u00ebr Plesk q\u00eb kemi instaluar m\u00eb par\u00eb.<\/p>\n<ol>\n<li>Kalojm\u00eb n\u00eb <i>Tools &amp; Settings &gt; Settings &gt; Firewall<\/i>:<br \/>\n<img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/d54b4941944fe191574472a475cbaebe.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Kalojm\u00eb n\u00eb <i>Modifikoni Rregullat e Plesk Firewall &gt; Shto Rregull t\u00eb Personalizuar<\/i> dhe hapni portat TCP t\u00eb m\u00ebposhtme p\u00ebr subnet-in 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 projektin n\u00eb 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 portet 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 projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/f812cfc7127da469507538ea48b2c80d.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Zbatoni rregullat me butonin Apply Changes:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb 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>\nT\u00eb kalojm\u00eb n\u00eb pjes\u00ebn m\u00eb t\u00eb interesant\u00eb \u2014 konfigurimin e pipeline-it p\u00ebr integrimin dhe shp\u00ebrndarjen e vazhdueshme t\u00eb projektit ton\u00eb n\u00eb server.<\/p>\n<p>Ky ky\u00e7 do t\u00eb p\u00ebrb\u00ebhet nga dy pjes\u00eb: <\/p>\n<ul>\n<li>nd\u00ebrtimi i imazhit dhe ekzekutimi i testeve (p\u00ebr backend) \u2014 n\u00eb an\u00ebn e Github;<\/li>\n<li>nj\u00eb hap\u00ebsir\u00eb (p\u00ebr backend) dhe depozitimi i kontejner\u00ebve \u2014 n\u00eb server.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Depoja n\u00eb Plesk<\/h2>\n<p>\nT\u00eb merremi fillimisht me pik\u00ebn e dyt\u00eb (sepse varet nga e para).<\/p>\n<p>Procesi i depoy-it do t\u00eb konfigurohet me ndihm\u00ebn e shtes\u00ebs Git p\u00ebr Plesk.<\/p>\n<p>T\u00eb shqyrtojm\u00eb nj\u00eb shembull me ambientin Prod p\u00ebr depozit\u00ebn e Backend.<\/p>\n<ol>\n<li>Hyrim n\u00eb abonimin e faqes son\u00eb Helloworld dhe kaloni n\u00eb n\u00ebnseksionin Git:\n<p><img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/b55b371560ea87a2954b6553a7cefc49.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>Ngjitim n\u00eb fush\u00ebn \"Remote Git repository\" lidhjen me depozit\u00ebn ton\u00eb n\u00eb Github dhe ndryshojm\u00eb dosjen e paracaktuar <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 projektin n\u00eb 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 etapa 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 kalojm\u00eb n\u00eb faqen e depozit\u00ebs n\u00eb Plesk. Tani na nevojitet t\u00eb konfigurojm\u00eb azhurnimin e depozit\u00ebs p\u00ebr ndodhit\u00eb n\u00eb deg\u00ebn master. P\u00ebr k\u00ebt\u00eb kaloni n\u00eb <i>Cil\u00ebsimet e Depozit\u00ebs<\/i> dhe ruani vler\u00ebn <code>Webhook URL<\/code> (do t\u00eb 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 projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/14d48a357f821d734d40dc434ab3682a.png\" style=\"display:block;margin: 0 auto;\" \/><\/li>\n<li>N\u00eb fush\u00ebn e veprimeve n\u00eb ekranin nga pika e m\u00ebparshme shkruani skriptin p\u00ebr t\u00eb nisur depoy-in:\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 dosjes prod backend-repozitorit n\u00eb server;<br \/>\n<code>{ENV}<\/code> \u2014 mjedisi (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 bot-it te 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 backend-repozitorin dhe frontend konfigurohen nj\u00ebsoj.<\/p>\n<h2>Pipeline i dep\u00ebrtimit n\u00eb Github Actions<\/h2>\n<p>\nKalojm\u00eb te konfigurimi i pjes\u00ebs s\u00eb par\u00eb t\u00eb CI\/CD pipeline ton\u00eb n\u00eb Github Actions.<\/p>\n<h3>Backend<\/h3>\n<p>\nPajisja 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, plot\u00ebsojm\u00eb n\u00eb Github variablat e nevojshme Sekrete. P\u00ebr k\u00ebt\u00eb kalojm\u00eb n\u00eb <i>Settings -&gt; Secrets<\/i>:<\/p>\n<ul>\n<li><code>DOCKER_REGISTRY<\/code> \u2014 hosti i repositorit ton\u00eb Docker (docker.helloworld.ru);<\/li>\n<li><code>DOCKER_LOGIN<\/code> \u2014 p\u00ebrdoruesi p\u00ebr repositorin Docker;<\/li>\n<li><code>DOCKER_PASSWORD<\/code> \u2014 password-i p\u00ebr t\u00eb;<\/li>\n<li><code>DEPLOY_HOST<\/code> \u2014 hosti, ku \u00ebsht\u00eb e aksesueshme administrata Plesk (shembull: <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 tokeni p\u00ebr dep\u00ebrtimin n\u00eb repositorin prod n\u00eb server (e kemi marr\u00eb n\u00eb Shtrirjen n\u00eb Plesk pika 4);<\/li>\n<li><code>DEPLOY_BACK_DEV_TOKEN<\/code> \u2014 tokeni p\u00ebr dep\u00ebrtimin n\u00eb repositorin dev n\u00eb server.<\/li>\n<\/ul>\n<p>\nProcesi i deployment-it \u00ebsht\u00eb i thjesht\u00eb dhe p\u00ebrb\u00ebhet nga tri hapa kryesor\u00eb: <\/p>\n<ul>\n<li>nd\u00ebrtimi dhe publikimi i imazhit n\u00eb depozit\u00ebn ton\u00eb;<\/li>\n<li>kryerja e testeve n\u00eb kontejnerin bazuar n\u00eb imazhin e sapo nd\u00ebrtuar;<\/li>\n<li>vendosja n\u00eb mjedisin e duhur 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 depozit\u00ebn frontale<\/a><\/noindex> nuk ndryshon shum\u00eb nga ai i pasm\u00eb. Aty nuk ka hapin e kryerjes s\u00eb testeve dhe emrat e tokeneve p\u00ebr deployment ndryshojn\u00eb. Sekretet p\u00ebr depozit\u00ebn frontale, p\u00ebr fat t\u00eb mir\u00eb, duhet t\u00eb plot\u00ebsohen ve\u00e7mas.<\/p>\n<h1>Konfigurimi i faqes<\/h1>\n<p><\/p>\n<h2>Proksimi i trafikut p\u00ebrmes Nginx<\/h2>\n<p>\nP\u00ebrfundimisht, 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 trajtuar tashm\u00eb n\u00eb pik\u00ebn 5 t\u00eb konfigurimit t\u00eb Docker Registry. E nj\u00ebjta gj\u00eb duhet p\u00ebrs\u00ebritur p\u00ebr pjes\u00ebt frontale dhe t\u00eb pasme n\u00eb mjediset dev dhe prod.<\/p>\n<p>Do t\u00eb sjell disa shkrepje t\u00eb konfigurimeve.<\/p>\n<h3>Backend<\/h3>\n<p>\n<img decoding=\"async\" alt=\"CI\/CD n\u00eb Github Actions p\u00ebr projektin n\u00eb 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 projektin n\u00eb Flask+Angular\" src=\"\/wp-content\/uploads\/2020\/06\/35d4d8ef3489608db1e173b7f214ca03.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<strong>Sh\u00ebnim i r\u00ebnd\u00ebsish\u00ebm<\/strong>. N\u00eb kontejnerin frontend do t\u00eb proksohen t\u00eb gjitha URL-t\u00eb p\u00ebrve\u00e7 atyre q\u00eb fillojn\u00eb me <code>\/api\/<\/code> \u2014 ato do t\u00eb proksohen n\u00eb kontejnerin backend (prandaj <strong>n\u00eb kontejnerin backend t\u00eb gjitha trajtuesit duhet t\u00eb fillojn\u00eb me <\/strong><strong><code>\/api\/<\/code><\/strong>).<\/p>\n<h2>P\u00ebrfundimet<\/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\u00ebs).<\/p>\n<p>N\u00eb p\u00ebrmbledhje, m\u00ebsuam si t\u00eb p\u00ebrgatisim nj\u00eb aplikacion t\u00eb thjesht\u00eb n\u00eb Flask dhe Angular dhe si t\u00eb konfiguroni nj\u00eb pipeline n\u00eb Github Actions p\u00ebr ta deployuar n\u00eb nj\u00eb server q\u00eb p\u00ebrdor Plesk.<\/p>\n<p>Do ta p\u00ebrs\u00ebris lidhjet p\u00ebr repozitor\u00ebt me kodin: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/olegborzov\/helloworld_back\">back-end<\/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 4.9.10 - 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 \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\" \/>\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) 4.9.10\" \/>\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 \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\" \/>\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 artikull do t\u00eb ndaj p\u00ebrvoj\u00ebn time n\u00eb konfigurimin e CI\/CD me panelin e kontrollit Plesk dhe Github Actions. Sot do t\u00eb m\u00ebsojm\u00eb si t\u00eb deployojm\u00eb nj\u00eb projekt t\u00eb thjesht\u00eb me emrin \u201eHelloworld\u201d. Ai \u00ebsht\u00eb shkruar n\u00eb framework-un Python Flask, me worker-a n\u00eb Celery dhe frontend n\u00eb Angular 8. Lidhjet p\u00ebr repozitor\u00ebt: backend, frontend. N\u00eb pjes\u00ebn e par\u00eb t\u00eb artikullit do t\u00eb shikojm\u00eb projektin ton\u00eb.","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 \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","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"},"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}]}}