{"id":55870,"date":"2020-01-30T00:00:00","date_gmt":"2020-01-29T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/ot-skriptov-k-sobstvennoj-platforme-kak-my-avtomatizirovali-razrabotku-v-tsian"},"modified":"2020-02-18T14:04:02","modified_gmt":"2020-02-18T11:04:02","slug":"ot-skriptov-k-sobstvennoj-platforme-kak-my-avtomatizirovali-razrabotku-v-tsian","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ot-skriptov-k-sobstvennoj-platforme-kak-my-avtomatizirovali-razrabotku-v-tsian","title":{"rendered":"Da script a piattaforma proprietaria: come abbiamo automatizzato lo sviluppo in CIAN","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Da script a piattaforma proprietaria: come abbiamo automatizzato lo sviluppo in CIAN\" src=\"\/wp-content\/uploads\/2020\/01\/965f1944c95e2020bec512a05d980a32.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDurante il RIT 2019, il nostro collega Aleksandr Korotkov ha parlato <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/watch?v=0wvUyjexoIg\">rapporto<\/a><\/noindex> dell'automazione dello sviluppo in TCIAN: per semplificare la vita e il lavoro, utilizziamo la nostra piattaforma Integro. Essa tiene traccia del ciclo di vita delle attivit\u00e0, solleva gli sviluppatori dalle operazioni routinarie e riduce notevolmente il numero di bug in produzione. In questo post, completeremo la presentazione di Aleksandr e racconteremo come abbiamo passato dalla semplice scrittura di script all'integrazione di prodotti open source attraverso la nostra piattaforma e quali sono le attivit\u00e0 della nostra squadra di automazione.<br \/>\n\u00a0<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Livello zero<\/h2>\n<p>\n<i><b>\u00abNon esiste un livello zero, non ne so nulla\u00bb<\/b><br \/>\nMaster Shifu dal film \u00abKung Fu Panda\u00bb<\/i><\/p>\n<p>L'automazione in TCIAN \u00e8 iniziata 14 anni dopo la fondazione dell'azienda. Allora, nel team di sviluppo c'erano 35 persone. Difficile da credere, vero? Certo, in qualche modo l'automazione esisteva, ma un'area separata per l'integrazione continua e la distribuzione del codice ha iniziato a formarsi nel 2015.\u00a0<\/p>\n<p>A quel tempo avevamo un enorme monolite composto da Python, C# e PHP, distribuito su server Linux\/Windows. Per il deployment di questo mostro avevamo un set di script che eseguivamo manualmente. C'era anche la costruzione del monolite, che portava dolore e sofferenza a causa dei conflitti durante la fusione dei branch, delle correzioni di difetti e della ricostruzione con \u2018un diverso set di attivit\u00e0 nel build\u2019. In modo semplificato, il processo appariva cos\u00ec:<\/p>\n<p><img decoding=\"async\" alt=\"Da script a piattaforma proprietaria: come abbiamo automatizzato lo sviluppo in CIAN\" src=\"\/wp-content\/uploads\/2020\/01\/03c4dd97e2ba0073bab1c33f6003a9ec.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuesto non ci soddisfava e volevamo costruire un processo di build e deployment ripetibile, automatizzato e gestito. Per fare ci\u00f2, avevamo bisogno di un sistema CI\/CD e sceglievamo tra la versione gratuita di Teamcity e Jenkins gratuito, poich\u00e9 avevamo gi\u00e0 lavorato con entrambi e ci soddisfacevano per il set di funzionalit\u00e0. Abbiamo scelto Teamcity come prodotto pi\u00f9 recente. All'epoca non utilizzavamo ancora un'architettura a microservizi e non prevedevamo un numero elevato di attivit\u00e0 e progetti.<\/p>\n<h2>Arriviamo all'idea di un nostro sistema<\/h2>\n<p>\nL'implementazione di Teamcity ha eliminato solo una parte del lavoro manuale: sono rimasti ancora la creazione di Pull Request, il passaggio delle attivit\u00e0 tra gli stati in Jira, la selezione delle attivit\u00e0 per il rilascio. Su questo aspetto, il sistema Teamcity non riusciva gi\u00e0 a gestire. Era necessario scegliere una strada per un'ulteriore automazione. Abbiamo valutato opzioni per lavorare con script in Teamcity o passare a sistemi di automazione esterni. Alla fine, abbiamo deciso che era necessaria la massima flessibilit\u00e0, che solo una soluzione interna poteva fornire. Cos\u00ec \u00e8 nata la prima versione del sistema di automazione interno chiamato Integro.<\/p>\n<p>Teamcity si occupa dell'automazione a livello di avvio dei processi di build e deployment, mentre Integro si \u00e8 concentrata sull'automazione di alto livello dei processi di sviluppo. Era necessario unire il lavoro con le attivit\u00e0 in Jira al trattamento del codice sorgente correlato in Bitbucket. In questo stadio, all'interno di Integro hanno cominciato a apparire i propri workflow per lavorare con diversi tipi di attivit\u00e0.\u00a0<\/p>\n<p>A causa dell'aumento dell'automazione nei processi aziendali, \u00e8 aumentato anche il numero di progetti e run in Teamcity. Cos\u00ec \u00e8 emerso un nuovo problema: un'istanza gratuita di Teamcity non era pi\u00f9 sufficiente (3 agenti e 100 progetti), abbiamo aggiunto un'altra istanza (altri 3 agenti e 100 progetti), poi ancora un'altra. Alla fine abbiamo ottenuto un sistema composto da pi\u00f9 cluster, difficile da gestire:<\/p>\n<p><img decoding=\"async\" alt=\"Da script a piattaforma proprietaria: come abbiamo automatizzato lo sviluppo in CIAN\" src=\"\/wp-content\/uploads\/2020\/01\/d95565e01e70e31f6b139dfb9b9caf95.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nQuando \u00e8 emersa la questione di una quarta istanza, abbiamo capito che non potevamo continuare cos\u00ec, poich\u00e9 i costi totali per il supporto di 4 istanze superavano ogni limite. \u00c8 emersa la questione dell'acquisto di Teamcity a pagamento o della scelta di Jenkins gratuito. Abbiamo effettuato calcoli sulle istanze e i piani di automazione e abbiamo deciso che avremmo usato Jenkins. Dopo un paio di settimane, siamo passati a Jenkins, liberandoci di parte del mal di testa associato al supporto di pi\u00f9 istanze di Teamcity. Cos\u00ec abbiamo potuto concentrarci sullo sviluppo di Integro e sull'ottimizzazione di Jenkins per le nostre esigenze.<\/p>\n<p>Con l'aumento dell'automazione di base (nella forma di creazione automatica di Pull Request, raccolta e pubblicazione della Code coverage e di altre verifiche), si \u00e8 consolidato il desiderio di abbandonare completamente i rilasci manuali e di delegare questo lavoro ai robot. In aggiunta, all'interno dell'azienda \u00e8 iniziato il passaggio ai microservizi, che richiedevano rilasci frequenti, ciascuno separatamente. Cos\u00ec, gradualmente siamo arrivati ai rilasci automatici dei nostri microservizi (per il monolite, al momento, continuiamo a rilasciarlo manualmente a causa della complessit\u00e0 del processo). Ma, come spesso accade, \u00e8 emersa una nuova difficolt\u00e0.\u00a0<\/p>\n<h2>Automatizziamo i test<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Da script a piattaforma proprietaria: come abbiamo automatizzato lo sviluppo in CIAN\" src=\"\/wp-content\/uploads\/2020\/01\/9518ee0956922c6eb615bdef068ac525.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nGrazie all'automazione dei rilasci, i processi di sviluppo si sono velocizzati, parzialmente a scapito di alcune fasi di test. Questo ha portato a una temporanea perdita di qualit\u00e0. Pu\u00f2 sembrare banale, ma con la velocizzazione dei rilasci era necessario cambiare anche la metodologia di sviluppo del prodotto. \u00c8 stato essenziale considerare l'automazione dei test, promuovere la responsabilit\u00e0 personale (qui si parla di \u00abaccettare l'idea nella propria mente\u00bb, non di penali monetarie) per gli sviluppatori riguardo al codice che producono e ai bug presenti, oltre a decidere sul rilascio o meno delle task attraverso il deploy automatico.\u00a0<\/p>\n<p>Affrontando i problemi di qualit\u00e0, siamo arrivati a due decisioni importanti: abbiamo iniziato a effettuare test canary e implementato un monitoraggio automatico per gli errori con reazione automatica al superamento della soglia. La prima decisione ha permesso di trovare errori evidenti prima che il codice arrivasse in produzione, mentre la seconda ha ridotto il tempo di risposta ai problemi in produzione. Certo, gli errori ci sono, ma spendiamo la maggior parte del tempo e delle energie non per correggerli, ma per minimizzarli.\u00a0<\/p>\n<h2>Team di automazione<\/h2>\n<p>\nAttualmente abbiamo un team di 130 sviluppatori e continuiamo <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/article\/469965\/\">a crescere<\/a><\/noindex>. Il team di integrazione e consegna continua del codice (da ora in poi, team Deploy and Integration o DI) \u00e8 composto da 7 persone e lavora in due direzioni: sviluppo della piattaforma di automazione Integro e DevOps.\u00a0<\/p>\n<p>DevOps si occupa degli ambienti Dev\/Beta del sito CIAN, dell'ambiente Integro, supporta gli sviluppatori nella risoluzione dei problemi e sviluppa nuovi approcci per scalare gli ambienti. La direzione dello sviluppo di Integro si occupa sia di Integro sia dei servizi correlati, ad esempio, plugin per Jenkins, Jira, Confluence, e sviluppa anche utility e applicazioni di supporto per i team di sviluppo.\u00a0<\/p>\n<p>Il team DI collabora con il team Piattaforma, che si occupa dello sviluppo dell'architettura, delle librerie e degli approcci allo sviluppo all'interno dell'azienda. Inoltre, qualsiasi sviluppatore all'interno di CIAN pu\u00f2 contribuire all'automazione, ad esempio, realizzando micro-automazioni secondo le esigenze del team o condividendo idee interessanti per migliorare ulteriormente l'automazione.<\/p>\n<h2>La torta stratificata dell'automazione in CIAN<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Da script a piattaforma proprietaria: come abbiamo automatizzato lo sviluppo in CIAN\" src=\"\/wp-content\/uploads\/2020\/01\/22dcd2d0cc283d53bdaac081885657f8.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nTutti i sistemi coinvolti nell'automazione possono essere suddivisi in diversi strati:<\/p>\n<ol>\n<li>Sistemi esterni (Jira, Bitbucket e altri). Questi sono gestiti dai team di sviluppo.\n<\/li>\n<li>Piattaforma Integro. Gli sviluppatori non lavorano direttamente su di essa, ma \u00e8 fondamentale per il funzionamento di tutta l'automazione.\n<\/li>\n<li>Servizi di consegna, orchestrazione e scoperta (ad esempio, Jenkins, Consul, Nomad). Questi aiutano a deployare il codice sui server e a garantire che i servizi funzionino tra loro.\n<\/li>\n<li>Livello fisico (server, OS, software correlato). Su questo livello il nostro codice opera. Pu\u00f2 essere un server fisico o virtuale (LXC, KVM, Docker).\n<\/li>\n<\/ol>\n<p>\nIn base a questo concetto, dividiamo le aree di responsabilit\u00e0 all'interno del team DI. I primi due livelli appartengono alla direzione dello sviluppo di Integro, mentre gli ultimi due livelli sono sotto la responsabilit\u00e0 di DevOps. Questa divisione consente di concentrarsi sui compiti e non ostacola l'interazione, poich\u00e9 siamo vicini l'uno all'altro e ci scambiamo costantemente conoscenze ed esperienze.<\/p>\n<h2>Integro<\/h2>\n<p>\nConcentriamoci su Integro e iniziamo con lo stack tecnologico:<\/p>\n<ul>\n<li>CentOs 7\n<\/li>\n<li>Docker + Nomad + Consul + Vault\n<\/li>\n<li>Java 11 (il vecchio monolite di Integro rimarr\u00e0 su Java 8)\n<\/li>\n<li>Spring Boot 2.X + Spring Cloud Config\n<\/li>\n<li>PostgreSql 11\n<\/li>\n<li>RabbitMQ\u00a0\n<\/li>\n<li>Apache Ignite\n<\/li>\n<li>Camunda (embedded)\n<\/li>\n<li>Grafana + Graphite + Prometheus + Jaeger + ELK\n<\/li>\n<li>Web UI: React (CSR) + MobX\n<\/li>\n<li>SSO: Keycloak\n<\/li>\n<\/ul>\n<p>\nSeguiamo il principio dello sviluppo a microservizi, anche se abbiamo un'eredit\u00e0 sotto forma di un monolite di una versione precedente di Integro. Ogni microservizio gira nel proprio container Docker, i servizi comunicano tra loro tramite richieste HTTP e messaggi RabbitMQ. I microservizi si trovano tramite Consul e fanno una richiesta a quest'ultimo, passando attraverso l'autenticazione SSO (Keycloak, OAuth 2\/OpenID Connect).<\/p>\n<p><img decoding=\"async\" alt=\"Da script a piattaforma proprietaria: come abbiamo automatizzato lo sviluppo in CIAN\" src=\"\/wp-content\/uploads\/2020\/01\/e7630c0bd62a40f397de1bf1c1097926.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCome esempio concreto, consideriamo l'interazione con Jenkins, che consiste nei seguenti passaggi:<\/p>\n<ol>\n<li>Il microservizio di gestione del workflow (da ora in poi, microservizio Flow) desidera avviare una build in Jenkins. A tal fine, trova tramite Consul l'IP:PORT del microservizio di integrazione con Jenkins (da ora in poi, microservizio Jenkins) e invia una richiesta asincrona per avviare la build in Jenkins.\n<\/li>\n<li>Il microservizio Jenkins, dopo aver ricevuto la richiesta, genera e restituisce in risposta un Job ID, che potr\u00e0 poi essere utilizzato per identificare il risultato dell'esecuzione. Allo stesso tempo, avvia la build in Jenkins attraverso una chiamata all'API REST.\n<\/li>\n<li>Jenkins esegue la build e, al termine, invia un webhook con i risultati dell'esecuzione al microservizio Jenkins.\n<\/li>\n<li>Il microservizio Jenkins riceve un webhook, genera un messaggio riguardo alla conclusione dell'elaborazione della richiesta e allega i risultati dell'esecuzione. Il messaggio generato viene inviato in coda a RabbitMQ.\n<\/li>\n<li>Attraverso RabbitMQ, il messaggio pubblicato arriva al microservizio Flow, che scopre il risultato dell'elaborazione del proprio compito confrontando il Job ID della richiesta con quello ricevuto nel messaggio.\n<\/li>\n<\/ol>\n<p>\nAttualmente abbiamo circa 30 microservizi, che possono essere suddivisi in diversi gruppi:<\/p>\n<ol>\n<li>Gestione delle configurazioni.\n<\/li>\n<li>Informativa e interazione con gli utenti (messaggeri, email).\n<\/li>\n<li>Gestione del codice sorgente.\n<\/li>\n<li>Integrazione con strumenti di deployment (jenkins, nomad, consul, ecc.).\n<\/li>\n<li>Monitoraggio (rilascio, errori, ecc.).\n<\/li>\n<li>Web utility (UI per la gestione degli ambienti di test, raccolta di statistiche, ecc.).\n<\/li>\n<li>Integrazione con task tracker e sistemi simili.\n<\/li>\n<li>Gestione del workflow per compiti diversi.\n<\/li>\n<\/ol>\n<p><\/p>\n<h2>Workflow del compito<\/h2>\n<p>\nIntegro automatizza le attivit\u00e0 legate al ciclo di vita di un compito. In senso semplificato, per ciclo di vita di un compito intendiamo il workflow di un compito in Jira. Nei nostri processi di sviluppo ci sono diverse varianti di workflow a seconda del progetto, del tipo di compito e delle opzioni selezionate in un compito specifico.\u00a0<\/p>\n<p>Consideriamo il workflow che utilizziamo pi\u00f9 frequentemente:<\/p>\n<p><img decoding=\"async\" alt=\"Da script a piattaforma proprietaria: come abbiamo automatizzato lo sviluppo in CIAN\" src=\"\/wp-content\/uploads\/2020\/01\/62555be6bab024dd30f3cf70d4fe3cba.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNello schema, l'ingranaggio indica che la transition \u00e8 attivata automaticamente da Integro, mentre la figura umana indica che la transition \u00e8 attivata manualmente da una persona. Esploriamo alcuni percorsi che un compito pu\u00f2 seguire in questo workflow.<\/p>\n<p>Completamente manuale test su DEV+BETA senza test canary (solitamente rilasciamo monoliti):<\/p>\n<p><img decoding=\"async\" alt=\"Da script a piattaforma proprietaria: come abbiamo automatizzato lo sviluppo in CIAN\" src=\"\/wp-content\/uploads\/2020\/01\/775528862e14817dff5f69db6de654dd.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPossono esserci anche altre combinazioni di transition. A volte il percorso che seguir\u00e0 un compito pu\u00f2 essere scelto tramite opzioni in Jira.<\/p>\n<h2>Movimento del compito<\/h2>\n<p>\nEsaminiamo i principali passaggi che vengono eseguiti quando il compito si muove nel workflow \"Test su DEV + test canary\":<\/p>\n<p>1. Lo sviluppatore o il PM crea un compito.<\/p>\n<p>2. Lo sviluppatore prende in carico il compito. Dopo averlo completato, lo sposta nello stato IN REVIEW.<\/p>\n<p>3. Jira invia un Webhook al microservizio Jira (responsabile dell'integrazione con Jira).<\/p>\n<p>4. Il microservizio Jira invia una richiesta al servizio Flow (responsabile per i workflow interni in cui viene svolto il lavoro) per avviare il workflow.<\/p>\n<p>5. All'interno del servizio Flow:<\/p>\n<ul>\n<li>Vengono designati i revisori per il compito (Users-microservizio, che conosce tutto sugli utenti + microservizio Jira).<\/li>\n<li>Attraverso il microservizio Source (che conosce i repository e i rami, ma non lavora direttamente con il codice), viene effettuata la ricerca dei repository contenenti il ramo del nostro compito (per semplificare la ricerca, il nome del ramo corrisponde al numero del compito in Jira). Di solito, il compito ha solo un ramo in un repository, il che semplifica la gestione della coda per il deployment e riduce la dipendenza tra i repository.<\/li>\n<li>Per ciascun ramo trovato, viene eseguita la seguente sequenza di azioni:\n<p> i) Integrazione del ramo master (Git-microservizio per lavorare con il codice).<br \/>\n ii) Il ramo viene bloccato dalle modifiche dello sviluppatore (Bitbucket-microservizio).<br \/>\n iii) Viene creato un Pull Request per quel ramo (Bitbucket-microservizio).<br \/>\n iv) Viene inviata una notifica su un nuovo Pull Request nelle chat degli sviluppatori (Notify-microservizio per le notifiche).<br \/>\n v) Viene avviata la creazione, il test e il deployment del compito su DEV (Jenkins-microservizio per l'uso di Jenkins).<br \/>\n vi) Se tutti i punti precedenti sono stati completati con successo, Integro aggiunge la propria approvazione al Pull Request (Bitbucket-microservizio).<\/li>\n<li>Integro attende l'approvazione nel Pull Request da parte dei revisori designati.<\/li>\n<li>Non appena vengono ricevute tutte le approvazioni necessarie (compresi i test automatizzati effettuati con successo), Integro sposta il compito nello stato Test su Dev (microservizio Jira).<\/li>\n<\/ul>\n<p>\n6. I tester eseguono i test sul compito. Se non ci sono problemi, spostano il compito nello stato Pronto per il Build.<\/p>\n<p>7. Integro \"vede\" che il compito \u00e8 pronto per il rilascio e avvia il suo deployment in modalit\u00e0 canary (Jenkins-microservizio). La prontezza per il rilascio \u00e8 determinata da un insieme di regole. Ad esempio, il compito \u00e8 nello stato corretto, non ci sono blocchi su altri compiti, non ci sono deployment attivi di questo microservizio, ecc.<\/p>\n<p>8. Il compito viene spostato nello stato Canary (microservizio Jira).<\/p>\n<p>9. Jenkins avvia tramite Nomad il deployment del compito in modalit\u00e0 canary (solitamente 1-3 istanze) e notifica al servizio di monitoraggio dei rilasci (DeployWatch-microservizio) riguardo al rilascio.<\/p>\n<p>10. DeployWatch \u00e8 un microservizio che raccoglie il fondo degli errori e risponde se necessario. Qualora il fondo degli errori superi la soglia (calcolata automaticamente), viene inviata una notifica agli sviluppatori tramite il microservizio Notify. Se dopo 5 minuti lo sviluppatore non interviene (non preme Revert o Stay), si avvia un rollback automatico delle istanze canary. Se il fondo non \u00e8 superato, lo sviluppatore deve avviare manualmente il deployment in produzione (premendo il pulsante nell'interfaccia). Se entro 60 minuti lo sviluppatore non ha avviato il deployment in produzione, anche le istanze canary verranno rollbackate per ragioni di sicurezza.<\/p>\n<p>11. Dopo l'avvio del deployment in produzione:<\/p>\n<ul>\n<li>Il compito viene trasferito allo stato Production (microservizio Jira).<\/li>\n<li>Il microservizio Jenkins avvia il processo di deployment e informa il microservizio DeployWatch riguardo al rilascio.<\/li>\n<li>Il microservizio DeployWatch verifica che tutti i contenitori in produzione siano stati aggiornati (si sono verificati casi in cui non tutti venivano aggiornati).<\/li>\n<li>Una notifica riguardante i risultati del deployment in produzione viene inviata tramite il microservizio Notify.<\/li>\n<\/ul>\n<p>\n12. Gli sviluppatori avranno 30 minuti per avviare il rollback del compito in produzione nel caso venga riscontrato un comportamento errato del microservizio. Trascorso questo tempo, il compito sar\u00e0 automaticamente integrato nel master (microservizio Git).<\/p>\n<p>13. Dopo un merge riuscito nel master, lo stato del compito sar\u00e0 cambiato in Closed (microservizio Jira).<\/p>\n<p>Lo schema non pretende di essere completamente dettagliato (in realt\u00e0 ci sono ancora pi\u00f9 passi), ma consente di valutare il grado di integrazione nei processi. Non consideriamo questo schema ideale e stiamo migliorando i processi di supporto automatico ai rilasci e al deployment.<\/p>\n<h2>Cosa succede dopo<\/h2>\n<p>\nAbbiamo grandi piani per lo sviluppo dell'automazione, ad esempio, eliminare le operazioni manuali nei rilasci del monolito, migliorare il monitoraggio del deployment automatico e migliorare l'interazione con gli sviluppatori.<\/p>\n<p>Ma ci fermiamo qui per ora. Abbiamo coperto superficialmente molti argomenti nell'overview dell'automazione e alcuni non sono stati trattati affatto, quindi siamo felici di rispondere a domande. Aspettiamo suggerimenti su cosa approfondire, scrivete nei commenti.<br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/cian\/blog\/486056\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0430 \u0420\u0418\u0422 2019 \u043d\u0430\u0448 \u043a\u043e\u043b\u043b\u0435\u0433\u0430 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440 \u041a\u043e\u0440\u043e\u0442\u043a\u043e\u0432 \u0441\u0434\u0435\u043b\u0430\u043b \u0434\u043e\u043a\u043b\u0430\u0434 \u043f\u0440\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432 \u0426\u0418\u0410\u041d: \u0447\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0436\u0438\u0437\u043d\u044c \u0438 \u0440\u0430\u0431\u043e\u0442\u0443, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443 Integro. \u041e\u043d\u0430 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0437\u0430\u0434\u0430\u0447, \u0441\u043d\u0438\u043c\u0430\u0435\u0442 \u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0440\u0443\u0442\u0438\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0431\u0430\u0433\u043e\u0432 \u0432 production. \u0412 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0435 \u043c\u044b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u0434\u043e\u043a\u043b\u0430\u0434 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u0430 \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0448\u043b\u0438 \u043f\u0443\u0442\u044c \u043e\u0442 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-55870","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0430 \u0420\u0418\u0422 2019.\" \/>\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\/it\/blog\/administrirovanie\/ot-skriptov-k-sobstvennoj-platforme-kak-my-avtomatizirovali-razrabotku-v-tsian\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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\udd47\u041e\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043a \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435: \u043a\u0430\u043a \u043c\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 \u0426\u0418\u0410\u041d | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0430 \u0420\u0418\u0422 2019.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ot-skriptov-k-sobstvennoj-platforme-kak-my-avtomatizirovali-razrabotku-v-tsian\" \/>\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-01-29T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:04:02+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\udd47Da script a una piattaforma propria: come abbiamo automatizzato lo sviluppo in CIAN | ProHoster","description":"A RIT 2019.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ot-skriptov-k-sobstvennoj-platforme-kak-my-avtomatizirovali-razrabotku-v-tsian","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\udd47\u041e\u0442 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u043a \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435: \u043a\u0430\u043a \u043c\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0432 \u0426\u0418\u0410\u041d | ProHoster","og:description":"\u041d\u0430 \u0420\u0418\u0422 2019.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/ot-skriptov-k-sobstvennoj-platforme-kak-my-avtomatizirovali-razrabotku-v-tsian","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-01-29T21:00:00+00:00","article:modified_time":"2020-02-18T11:04:02+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"55870","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 19:35:40","updated":"2022-09-30 17:42:13","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/55870","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=55870"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/55870\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=55870"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=55870"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=55870"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}