{"id":93885,"date":"2020-09-10T19:42:23","date_gmt":"2020-09-10T17:42:23","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov"},"modified":"2020-09-10T19:42:23","modified_gmt":"2020-09-10T17:42:23","slug":"continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov","title":{"rendered":"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/ed8a32ae63b8dccfc8b4893ab27f1527.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vamos discutir por que ferramentas de CI e CI s\u00e3o coisas bem diferentes.<\/p>\n<p><\/p>\n<p>Qual dor o CI pretende resolver, de onde surgiu a ideia, quais as \u00faltimas evid\u00eancias de que funciona, como entender se voc\u00ea tem uma pr\u00e1tica real e n\u00e3o apenas um Jenkins instalado.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>A ideia de fazer uma apresenta\u00e7\u00e3o sobre Integra\u00e7\u00e3o Cont\u00ednua surgiu h\u00e1 um ano, quando estava em entrevistas em busca de emprego. Falei com 10-15 empresas, e apenas uma conseguiu explicar claramente o que \u00e9 CI e como percebeu que n\u00e3o o tinha. As outras falavam coisas sem sentido sobre Jenkins \ud83d\ude42 Bem, temos Jenkins, ele faz compila\u00e7\u00f5es, CI! Na apresenta\u00e7\u00e3o, tentarei explicar o que realmente \u00e9 Integra\u00e7\u00e3o Cont\u00ednua e por que Jenkins e ferramentas semelhantes t\u00eam rela\u00e7\u00e3o muito fraca com isso.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/a57813a652c0d788e5a927dc8a7130ba.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E ent\u00e3o, o que normalmente vem \u00e0 mente ao ouvir a palavra CI? A maioria das pessoas pensar\u00e1 em Jenkins, Gitlab CI, Travis, etc.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/c9799c11ba7bb7bbdb2048c2f314b22a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mesmo se fizermos uma busca, esses ferramentas aparecer\u00e3o.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/028ef088b28b73e7905b1666d9d53d1b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Se voc\u00ea perguntar a algu\u00e9m, logo ap\u00f3s listar as ferramentas, eles dir\u00e3o que CI \u00e9 quando sua Pull Request em um commit dispara uma compila\u00e7\u00e3o e a execu\u00e7\u00e3o de testes.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/f37ba8f985c10900f669540e063c5e43.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Integra\u00e7\u00e3o Cont\u00ednua n\u00e3o \u00e9 sobre ferramentas, n\u00e3o \u00e9 sobre compila\u00e7\u00f5es com testes em uma branch! Integra\u00e7\u00e3o Cont\u00ednua \u00e9 a pr\u00e1tica de integrar c\u00f3digo novo com muita frequ\u00eancia e para isso n\u00e3o \u00e9 necess\u00e1rio criar Jenkins, GitLab, etc.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/c3a12b4a875050550b42714607e787c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Antes de entendermos como \u00e9 um CI pleno, vamos primeiro nos aprofundar no contexto das pessoas que o criaram e sentir a dor que estavam tentando resolver.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/2ab9c0f4dba2887fed5744c8b021b424.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E a dor que resolveram foi a da colabora\u00e7\u00e3o em equipe!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/11a5f3b1075f8b8d0f169fe07adf6c91.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vamos olhar exemplos das dificuldades que os desenvolvedores enfrentam ao trabalhar em equipe. Aqui temos um projeto, a branch master no git e dois desenvolvedores.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/8138a52376e87239ff5f7b0af5cd8fee.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E eles come\u00e7aram a trabalhar como todos j\u00e1 est\u00e3o acostumados. Pegaram uma tarefa no Jira, criaram uma feature branch e come\u00e7aram a escrever c\u00f3digo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/54720c40d9bbd9631b411a2a26c4083f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Um terminou a feature mais r\u00e1pido e fez o merge na master.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/4593dc3cf33a44bf3a4d8166be9bc5da.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O outro levou mais tempo, fez o merge depois e encontrou um conflito. Agora, em vez de escrever as features necess\u00e1rias para o neg\u00f3cio, o desenvolvedor gasta seu tempo e esfor\u00e7o resolvendo conflitos.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/c947601fb1dd3b3dd64bac455dc6691a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Quanto mais complicado for unir sua funcionalidade ao reposit\u00f3rio principal, mais tempo gastaremos com isso. E este \u00e9 apenas um exemplo bastante simples. Imagine se houver 10, 15 ou at\u00e9 100 pessoas na empresa contribuindo para um \u00fanico reposit\u00f3rio. Voc\u00ea enlouqueceria tentando resolver todos esses conflitos. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/16c6b8b51ae462f1e0acb966a93c0ae5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>H\u00e1 um caso um pouco diferente. Temos um reposit\u00f3rio principal e v\u00e1rios desenvolvedores que est\u00e3o fazendo algo.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/21b78ad8d0cb7cb5bded6ef9d49707c5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Eles criaram um branch cada um.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/b85d8aa0080f08c1ad8ad83f3a9ab084.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Um deles fez o merge, tudo certo, completou a tarefa.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/e96d4fd52c39089e3377ed85adeeb591.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O segundo desenvolvedor, enquanto isso, completou sua tarefa. Suponha que ele a tenha enviado para revis\u00e3o. Em muitas empresas, existe a pr\u00e1tica de revis\u00e3o. Por um lado, essa pr\u00e1tica \u00e9 boa e \u00fatil, mas, por outro, pode nos atrasar em muitos aspectos. N\u00e3o vamos nos aprofundar nisso, mas aqui est\u00e1 um \u00f3timo exemplo do que pode ocorrer com uma hist\u00f3ria problem\u00e1tica de revis\u00e3o. Voc\u00ea submeteu um pull request para revis\u00e3o. O desenvolvedor n\u00e3o tem mais nada a fazer. O que ele come\u00e7a a fazer? Ele come\u00e7a a pegar outras tarefas. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/7b8e121be99432606056acf11e20f518.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Durante esse tempo, o segundo desenvolvedor fez mais alguma coisa. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/ceaa5ba5b3b5014fad527362f5794e94.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O primeiro completou a terceira tarefa. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/9c27663e63bb9489ecffc5a1f73abb87.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E ap\u00f3s um tempo consider\u00e1vel, sua revis\u00e3o foi testada, e ele tenta fazer o merge. E o que acontece? Ele encontra uma enorme quantidade de conflitos. Por qu\u00ea? Porque enquanto seu pull request ficou pendente de revis\u00e3o, o c\u00f3digo j\u00e1 foi alterado significativamente. <\/p>\n<p><\/p>\n<p>Al\u00e9m do problema dos conflitos, h\u00e1 tamb\u00e9m o problema das comunica\u00e7\u00f5es. Enquanto voc\u00ea tem um branch pendente de revis\u00e3o, enquanto ele est\u00e1 esperando, enquanto voc\u00ea leva um tempo consider\u00e1vel para finalizar a funcionalidade, voc\u00ea para de acompanhar o que mais est\u00e1 mudando na base de c\u00f3digo do seu servi\u00e7o. Pode ser que o que voc\u00ea est\u00e1 tentando resolver j\u00e1 tenha sido resolvido ontem, e voc\u00ea poderia reutilizar algum m\u00e9todo. Mas voc\u00ea n\u00e3o ver\u00e1 isso, porque sempre estar\u00e1 trabalhando com um branch desatualizado. E esse branch desatualizado sempre resulta em voc\u00ea ter que resolver um conflito de merge. <\/p>\n<p><\/p>\n<p>Portanto, se estamos trabalhando em equipe, ou seja, n\u00e3o apenas uma pessoa mexendo no reposit\u00f3rio, mas sim de 5 a 10 pessoas, quanto mais tempo demoramos para adicionar nosso c\u00f3digo ao reposit\u00f3rio principal, mais sofremos com a necessidade de fazer um merge no final. E quanto mais conflitos houver, e quanto mais antiga for a vers\u00e3o com a qual estamos trabalhando, mais problemas teremos.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/55c070f65a4d3838fb8c02bb9684c76b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Trabalhar em conjunto \u00e9 doloroso! Sempre estamos atrapalhando uns aos outros. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/b914c50aad6f3c9f97edcad7e71ba627.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Esse problema foi notado h\u00e1 mais de 20 anos. A primeira men\u00e7\u00e3o \u00e0 pr\u00e1tica de Integra\u00e7\u00e3o Cont\u00ednua que encontrei foi na programa\u00e7\u00e3o extrema.<\/p>\n<p><\/p>\n<p>Programa\u00e7\u00e3o extrema \u00e9 o primeiro framework \u00e1gil. A p\u00e1gina foi criada em 1996. A ideia era usar algumas pr\u00e1ticas de programa\u00e7\u00e3o, planejamento e outras coisas para que o desenvolvimento fosse o mais flex\u00edvel poss\u00edvel, para que pud\u00e9ssemos reagir mais rapidamente a mudan\u00e7as e requisitos de nossos clientes. E h\u00e1 24 anos, come\u00e7aram a perceber que, se voc\u00ea faz algo por muito tempo \u00e0 parte, gasta mais tempo com isso devido a conflitos. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/93a80838bdb3b297557dbf2ac7587965.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Agora vamos analisar a express\u00e3o \"Integra\u00e7\u00e3o Cont\u00ednua\" palavra por palavra. Se traduzirmos literalmente, \u00e9 integra\u00e7\u00e3o cont\u00ednua. Mas o qu\u00e3o cont\u00ednua ela \u00e9 n\u00e3o est\u00e1 muito claro, ela \u00e9, na verdade, bastante intermitente. E o quanto ela \u00e9 uma integra\u00e7\u00e3o tamb\u00e9m n\u00e3o \u00e9 muito \u00f3bvio. <\/p>\n<p><\/p>\n<p>E por isso trago agora cita\u00e7\u00f5es da programa\u00e7\u00e3o extrema. Vamos analisar as duas palavras separadamente. <\/p>\n<p><\/p>\n<p>Integra\u00e7\u00e3o \u2014 Como j\u00e1 mencionei, buscamos que cada engenheiro trabalhe com a vers\u00e3o mais atual do c\u00f3digo, para que ele adicione seu c\u00f3digo o mais frequentemente poss\u00edvel \u00e0 branch principal, para que sejam pequenas branches. Porque se forem grandes, podemos facilmente ficar presos por uma semana com conflitos de merge. Especialmente se estivermos em um ciclo de desenvolvimento longo, como o waterfall, onde o desenvolvedor foi trabalhar por um m\u00eas em algum enorme recurso. E, no est\u00e1gio de integra\u00e7\u00e3o, pode ficar preso por muito tempo. <\/p>\n<p><\/p>\n<p>Integra\u00e7\u00e3o \u2014 \u00e9 quando pegamos nossa branch e a integramos ao master, fazemos o merge. H\u00e1 uma variante suprema, quando habilitamos o desenvolvedor transbase, onde buscamos que escrevamos direto no master sem branches desnecess\u00e1rias.<\/p>\n<p><\/p>\n<p>Em resumo, a integra\u00e7\u00e3o \u00e9 pegar seu c\u00f3digo e lev\u00e1-lo para o master. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/8950103e6a59ed7132ec321ac6abe600.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O que se entende por \"continuous\" aqui, o que \u00e9 continuidade? A pr\u00e1tica implica que o desenvolvedor busca integrar seu c\u00f3digo o mais r\u00e1pido poss\u00edvel. Esse \u00e9 seu objetivo ao executar qualquer tarefa - fazer com que seu c\u00f3digo apare\u00e7a no mestre o mais r\u00e1pido poss\u00edvel. Em um mundo ideal, os desenvolvedores fariam isso a cada poucas horas. Ou seja, voc\u00ea pega uma pequena tarefa, mescla-a no mestre. Tudo \u00f3timo. Voc\u00ea almeja isso. E deve fazer isso continuamente. Assim que voc\u00ea faz algo, voc\u00ea imediatamente o insere no mestre. <\/p>\n<p><\/p>\n<p>E o desenvolvedor que faz algo \u00e9 respons\u00e1vel pelo que ele fez, garantindo que funcione e que nada seja quebrado. Aqui geralmente surge a quest\u00e3o dos testes. Queremos executar alguns testes em nosso commit, em nosso merge, para garantir que tudo funcione. E \u00e9 aqui que o Jenkins pode ajudar.<\/p>\n<p><\/p>\n<p>Mas com as hist\u00f3rias: vamos fazer as mudan\u00e7as pequenas, vamos fazer as tarefas pequenas, e vamos tentar fazer a tarefa e imediatamente integr\u00e1-la no mestre - aqui nenhum Jenkins vai ajudar. Porque o Jenkins vai te ajudar exclusivamente a executar os testes. <\/p>\n<p><\/p>\n<p>Voc\u00ea pode se virar sem eles. Isso n\u00e3o vai te atrapalhar em nada. Porque o objetivo da pr\u00e1tica \u00e9 mesclarse o mais frequentemente poss\u00edvel, para n\u00e3o gastar uma quantidade enorme de tempo em conflitos futuros. <\/p>\n<p><\/p>\n<p>Vamos imaginar que estamos no ano de 2020, mas por algum motivo estamos sem internet. E estamos trabalhando localmente. N\u00e3o temos Jenkins. Isso \u00e9 normal. Voc\u00ea ainda pode criar uma branch local. Voc\u00ea escreveu algum c\u00f3digo nela. Fez uma tarefa em 3-4 horas. Mudou para o mestre, fez git pull, mesclou sua branch. Pronto. Se voc\u00ea fizer isso frequentemente \u2013 parab\u00e9ns, voc\u00ea tem Integra\u00e7\u00e3o Cont\u00ednua!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/1f2117b65994b940edb04e0e119f6e8a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Quais s\u00e3o as evid\u00eancias no mundo moderno de que vale a pena investir esfor\u00e7o nisso? Porque, no geral, \u00e9 complexo. Se voc\u00ea tentar trabalhar assim, vai perceber que isso envolve algum planejamento, e voc\u00ea precisar\u00e1 dedicar mais tempo \u00e0 decomposi\u00e7\u00e3o das tarefas. Porque se voc\u00ea for fazer man..., n\u00e3o conseguir\u00e1 se mesclar rapidamente e, consequentemente, acabar\u00e1 em apuros. Voc\u00ea n\u00e3o ter\u00e1 mais as pr\u00e1ticas. <\/p>\n<p><\/p>\n<p>E isso ser\u00e1 caro. N\u00e3o ser\u00e1 poss\u00edvel trabalhar a partir de amanh\u00e3 em Continuous Integration. Todos voc\u00eas v\u00e3o demorar muito para se acostumar, v\u00e3o levar muito tempo para aprender a decompor tarefas, e v\u00e3o levar muito tempo para se acostumar a refazer a pr\u00e1tica de revis\u00e3o, se \u00e9 que a t\u00eam. Porque nosso objetivo \u00e9 que o merge aconte\u00e7a hoje. E se voc\u00eas fazem a revis\u00e3o ao longo de tr\u00eas dias, ent\u00e3o voc\u00eas t\u00eam problemas e o Continuous Integration n\u00e3o funciona. <\/p>\n<p><\/p>\n<p>Mas temos algumas evid\u00eancias atuais que nos dizem que vale a pena investir nessa pr\u00e1tica?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/2026a8f1d72fb05613511e7bab57e8ec.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A primeira coisa que me veio \u00e0 mente foi o State of DevOps. \u00c9 uma pesquisa que a equipe realiza h\u00e1 7 anos. Atualmente, eles fazem isso como uma organiza\u00e7\u00e3o independente, mas sob o Google.<\/p>\n<p><\/p>\n<p>E a pesquisa deles, em 2018, mostrou uma correla\u00e7\u00e3o entre empresas que tentam usar branches de curta dura\u00e7\u00e3o, que se integram rapidamente e com frequ\u00eancia; elas t\u00eam indicadores de desempenho de TI muito melhores.<\/p>\n<p><\/p>\n<p>Quais s\u00e3o esses indicadores? S\u00e3o 4 m\u00e9tricas que eles coletam de todas as empresas em seus question\u00e1rios: frequ\u00eancia de deploy, tempo para mudan\u00e7as, tempo para restaurar o servi\u00e7o e taxa de falhas nas mudan\u00e7as.<\/p>\n<p><\/p>\n<p>E, em primeiro lugar, h\u00e1 essa correla\u00e7\u00e3o; sabemos que as empresas que fazem merges frequentemente t\u00eam m\u00e9tricas muito melhores. Eles dividem as empresas em v\u00e1rias categorias: empresas lentas, que produzem algo lentamente, performers medianos, high performers e a elite. A elite \u00e9 composta por Netflix, Amazon, que s\u00e3o super \u00e1geis, fazem tudo rapidamente, de forma bonita e com qualidade.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/4fd98ef48a5cffdd6ae2ceea93dbb0bf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>A segunda hist\u00f3ria aconteceu literalmente h\u00e1 um m\u00eas. No Technology Radar, surgiu uma nota maravilhosa sobre o Gitflow. O Gitflow se diferencia dos outros por ter branches que vivem por um longo tempo. Existem branches de release que duram muito, e branches de features que tamb\u00e9m vivem muito. Essa pr\u00e1tica no Technology Radar foi movida para HOLD. Por qu\u00ea? Porque as pessoas enfrentam a dor da integra\u00e7\u00e3o. <\/p>\n<p><\/p>\n<p>Se voc\u00ea tem uma branch que vive muito tempo, ela acaba se estragando, e come\u00e7amos a gastar mais tempo para fazer alguma mudan\u00e7a nela. <\/p>\n<p><\/p>\n<p>E recentemente, o autor do Gitflow disse que se voc\u00ea est\u00e1 buscando a Integra\u00e7\u00e3o Cont\u00ednua, se deseja integrar com a maior frequ\u00eancia poss\u00edvel, ent\u00e3o o Gitflow \u00e9 uma m\u00e1 ideia. Ele acrescentou em um artigo que se voc\u00ea tem um backend onde pode se esfor\u00e7ar para isso, o Gitflow \u00e9 desnecess\u00e1rio, pois o Gitflow vai desaceler\u00e1-lo e criar problemas de integra\u00e7\u00e3o. <\/p>\n<p><\/p>\n<p>Isso n\u00e3o significa que o Gitflow seja ruim e que n\u00e3o deva ser utilizado. Ele \u00e9 para outros casos. Por exemplo, quando voc\u00ea precisa suportar v\u00e1rias vers\u00f5es de um servi\u00e7o ou aplicativo, ou seja, quando \u00e9 preciso dar suporte por um per\u00edodo prolongado. <\/p>\n<p><\/p>\n<p>Mas se voc\u00ea conversar com pessoas que sustentam tais servi\u00e7os, ouvir\u00e1 muitas queixas sobre como essa vers\u00e3o era 3.2, que foi lan\u00e7ada h\u00e1 4 meses, e que essa corre\u00e7\u00e3o n\u00e3o foi inclu\u00edda. Agora, para integr\u00e1-la, \u00e9 necess\u00e1rio fazer uma por\u00e7\u00e3o de altera\u00e7\u00f5es. E ent\u00e3o eles ficam presos novamente, passando uma semana tentando mesclar uma nova funcionalidade. <\/p>\n<p><\/p>\n<p>Como Alexander Kovalev corretamente observou no chat, correla\u00e7\u00e3o n\u00e3o \u00e9 o mesmo que causalidade. \u00c9 isso mesmo. Ou seja, n\u00e3o h\u00e1 uma rela\u00e7\u00e3o direta de que se voc\u00ea tem Integra\u00e7\u00e3o Cont\u00ednua, todas as m\u00e9tricas ser\u00e3o \u00f3timas. Mas h\u00e1 uma correla\u00e7\u00e3o positiva, onde se um existe, o outro provavelmente tamb\u00e9m existe. N\u00e3o \u00e9 uma certeza, mas \u00e9 prov\u00e1vel. \u00c9 apenas uma correla\u00e7\u00e3o. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/d5fc050550b0e9f86a1fdf85fff32fa5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Parece que j\u00e1 estamos fazendo algo, parece que estamos mesclando, mas como saber se realmente temos Integra\u00e7\u00e3o Cont\u00ednua, que estamos mesclando com frequ\u00eancia suficiente?<\/p>\n<p><\/p>\n<p>Jez Humble \u00e9 o autor do Handbook, Accelerate, do site Continuous Delivery e do livro \"Continuous Delivery\". Ele prop\u00f5e o seguinte teste:<\/p>\n<p><\/p>\n<ul>\n<li>O c\u00f3digo do engenheiro entra no master diariamente. <\/li>\n<li>Para cada commit, voc\u00ea executa testes unit\u00e1rios.<\/li>\n<li>Se o build no master falhar, ele \u00e9 corrigido em cerca de 10 minutos.<\/li>\n<\/ul>\n<p><\/p>\n<p>Ele sugere usar esse teste para garantir que voc\u00ea realmente possui a pr\u00e1tica. <\/p>\n<p><\/p>\n<p>O que eu encontro um pouco controverso. Ou seja, se voc\u00ea pode consertar em 10 minutos, significa que voc\u00ea tem Integra\u00e7\u00e3o Cont\u00ednua, isso soa um pouco estranho, na minha opini\u00e3o, mas faz sentido. Por qu\u00ea? Porque, se voc\u00ea faz merges com frequ\u00eancia, isso significa que suas mudan\u00e7as s\u00e3o pequenas. Se uma pequena mudan\u00e7a causar a quebra da build do master, voc\u00ea poder\u00e1 encontrar o problema rapidamente, porque a altera\u00e7\u00e3o \u00e9 pequena. Voc\u00ea teve um pequeno merge, onde mudaram 20-30 linhas. E, consequentemente, voc\u00ea pode entender rapidamente qual foi a raz\u00e3o, porque as mudan\u00e7as s\u00e3o m\u00ednimas e voc\u00ea tem uma \u00e1rea de busca muito restrita para o problema. <\/p>\n<p><\/p>\n<p>E mesmo que ap\u00f3s o lan\u00e7amento nosso prod quebre, se tivermos a pr\u00e1tica de Integra\u00e7\u00e3o Cont\u00ednua, ser\u00e1 muito mais f\u00e1cil agir, porque as mudan\u00e7as s\u00e3o pequenas. Sim, isso afetar\u00e1 o planejamento. Isso ser\u00e1 doloroso. E talvez o mais dif\u00edcil nessa pr\u00e1tica seja se acostumar a dividir as tarefas, ou seja, como fazer algo em algumas horas e ao mesmo tempo passar pela revis\u00e3o, se voc\u00ea a tiver. A revis\u00e3o \u00e9 uma dor separada. <\/p>\n<p><\/p>\n<p>Os testes unit\u00e1rios s\u00e3o apenas um assistente que te ajuda a entender se a sua integra\u00e7\u00e3o foi bem-sucedida, se nada foi quebrado. Na minha opini\u00e3o, isso tamb\u00e9m n\u00e3o \u00e9 um ponto obrigat\u00f3rio, porque o sentido da pr\u00e1tica n\u00e3o est\u00e1 nisso. <\/p>\n<p><\/p>\n<p>Isso \u00e9 um resumo sobre Integra\u00e7\u00e3o Cont\u00ednua. \u00c9 tudo o que h\u00e1 nessa pr\u00e1tica. Estou aberto a perguntas. <\/p>\n<p><\/p>\n<p>Resumindo, apenas mais uma vez:<\/p>\n<p><\/p>\n<ul>\n<li>Integra\u00e7\u00e3o Cont\u00ednua n\u00e3o \u00e9 Jenkins, n\u00e3o \u00e9 Gitlab.<\/li>\n<li>N\u00e3o \u00e9 uma ferramenta, \u00e9 uma pr\u00e1tica de que fazemos merges do nosso c\u00f3digo no master o mais frequentemente poss\u00edvel. <\/li>\n<li>Fazemos isso para evitar a imensa dor que surge com os merges no futuro, ou seja, estamos sentindo uma pequena dor agora para n\u00e3o sentir uma grande dor mais tarde. Esse \u00e9 todo o sentido. <\/li>\n<li>H\u00e1 uma comunica\u00e7\u00e3o atrav\u00e9s do c\u00f3digo, mas eu raramente vejo isso, mas tamb\u00e9m foi pensado para isso.<\/li>\n<\/ul>\n<p><\/p>\n<p><strong>Perguntas<\/strong><\/p>\n<p><\/p>\n<p><em>O que fazer com tarefas n\u00e3o decompostas?<\/em><\/p>\n<p><\/p>\n<p>Decompor. Qual \u00e9 o problema? Voc\u00ea pode dar um exemplo de que h\u00e1 uma tarefa que n\u00e3o pode ser decomposta?<\/p>\n<p><\/p>\n<p><em>Existem tarefas que n\u00e3o podem ser decompostas de forma alguma, por exemplo, aquelas que requerem uma expertise muito profunda e que realmente podem levar um m\u00eas para um resultado razo\u00e1vel.<\/em> <\/p>\n<p><\/p>\n<p>Se eu entendi corretamente, h\u00e1 uma tarefa grande e complexa cujo resultado s\u00f3 ser\u00e1 vis\u00edvel em um m\u00eas?<\/p>\n<p><\/p>\n<p><em>Sim, isso mesmo. O resultado s\u00f3 poder\u00e1 ser avaliado depois de pelo menos um m\u00eas.<\/em> <\/p>\n<p><\/p>\n<p>Certo. Em geral, isso n\u00e3o \u00e9 um problema. Por qu\u00ea? Porque, neste caso, quando falamos sobre branches, n\u00e3o estamos falando de uma branch com uma feature. As features podem ser grandes e complexas. Elas podem envolver muitos componentes. E, talvez, n\u00e3o possamos complet\u00e1-las em uma \u00fanica branch. Isso \u00e9 normal. Precisamos apenas dividir essa hist\u00f3ria. Se a feature n\u00e3o estiver completamente pronta, isso n\u00e3o significa que algumas partes do c\u00f3digo n\u00e3o podem ser merged. Voc\u00ea adicionou, por exemplo, uma migra\u00e7\u00e3o e dentro da feature h\u00e1 algumas etapas. Voc\u00ea pode ter uma etapa \u2013 fazer a migra\u00e7\u00e3o, adicionar um novo m\u00e9todo. E voc\u00ea j\u00e1 pode fazer o merge dessas coisas diariamente. <\/p>\n<p><\/p>\n<p><em>Certo. Qual \u00e9 o sentido disso?<\/em><\/p>\n<p><\/p>\n<p>Qual \u00e9 o sentido de fazer merge de pequenas partes diariamente?<\/p>\n<p><\/p>\n<p><em>Sim.<\/em><\/p>\n<p><\/p>\n<p>Se algo quebrar, voc\u00ea perceber\u00e1 imediatamente. Voc\u00ea tem um pequeno peda\u00e7o que causou um erro, e \u00e9 mais f\u00e1cil corrigir isso. O sentido \u00e9 que fazer o merge de um pequeno trecho agora \u00e9 muito mais simples do que fazer o merge de algo grande em algumas semanas. E o terceiro ponto \u00e9 que outros engenheiros estar\u00e3o trabalhando com a vers\u00e3o atualizada do c\u00f3digo. Eles ver\u00e3o que algumas migra\u00e7\u00f5es foram adicionadas e que h\u00e1 um novo m\u00e9todo que eles tamb\u00e9m podem querer usar. Todos poder\u00e3o ver o que est\u00e1 acontecendo no seu c\u00f3digo. \u00c9 exatamente para essas tr\u00eas raz\u00f5es que essa pr\u00e1tica \u00e9 implementada. <\/p>\n<p><\/p>\n<p><em>Obrigado, quest\u00e3o encerrada!<\/em><\/p>\n<p><\/p>\n<p><em>(Oleg Soroka) Posso adicionar algo? Voc\u00ea falou tudo certo, quero apenas acrescentar uma frase.<\/em><\/p>\n<p><\/p>\n<p>Certo.<\/p>\n<p><\/p>\n<p><em>Na Integra\u00e7\u00e3o Cont\u00ednua, o c\u00f3digo \u00e9 merged na branch principal n\u00e3o quando a feature est\u00e1 completamente pronta, mas quando o build parou de falhar. E voc\u00ea pode fazer commits no master quantas vezes quiser por dia. O segundo aspecto \u2013 se voc\u00ea n\u00e3o consegue, por algum motivo, dividir uma tarefa de um m\u00eas em tarefas de pelo menos tr\u00eas dias, sem contar tr\u00eas horas, ent\u00e3o voc\u00ea tem um grande problema. E o fato de voc\u00ea n\u00e3o ter Integra\u00e7\u00e3o Cont\u00ednua \u00e9 a menor das suas preocupa\u00e7\u00f5es. Isso significa que voc\u00ea tem problemas com a arquitetura e pr\u00e1ticas de engenharia est\u00e3o em zero. Porque mesmo que seja uma pesquisa, de qualquer forma, deve ser estruturada na forma de hip\u00f3teses ou ciclos.<\/em> <\/p>\n<p><\/p>\n<p><em>Falamos sobre 4 m\u00e9tricas que diferenciam empresas bem-sucedidas das que ficam para tr\u00e1s. \u00c9 necess\u00e1rio alcan\u00e7ar essas 4 m\u00e9tricas primeiro. Se voc\u00ea leva um m\u00eas para realizar uma tarefa m\u00e9dia, eu come\u00e7aria a me concentrar primeiramente nessa m\u00e9trica. Reduziria-a inicialmente para 3 dias. Depois disso, come\u00e7aria a pensar sobre Continuous.<\/em><\/p>\n<p><\/p>\n<p>Entendi corretamente que voc\u00ea acha que, se qualquer tarefa leva um m\u00eas, n\u00e3o faz sentido investir em pr\u00e1ticas de engenharia?<\/p>\n<p><\/p>\n<p><em>Voc\u00ea tem Continuous Integration. E h\u00e1 um ponto em que voc\u00ea conserta uma corre\u00e7\u00e3o ou reverte em 10 minutos. Imagine que voc\u00ea o lan\u00e7ou. E mais, voc\u00ea tem at\u00e9 continuous deployment, voc\u00ea o lan\u00e7ou no prod e apenas depois percebeu que algo deu errado. E voc\u00ea precisa reverter, mas j\u00e1 ocorreu a migra\u00e7\u00e3o do banco de dados. A sua vers\u00e3o do esquema do banco de dados j\u00e1 est\u00e1 na pr\u00f3xima, al\u00e9m disso, um backup j\u00e1 foi feito e dados foram registrados.<\/em><\/p>\n<p><\/p>\n<p><em>E qual \u00e9 a sua alternativa? Se voc\u00ea reverte o c\u00f3digo, ele n\u00e3o pode mais funcionar com esse banco de dados atualizado.<\/em><\/p>\n<p><\/p>\n<p>O banco s\u00f3 avan\u00e7a, sim. <\/p>\n<p><\/p>\n<p><em>As pessoas que t\u00eam uma m\u00e1 pr\u00e1tica de engenharia provavelmente tamb\u00e9m n\u00e3o leram um livro grosso sobre... O que fazer com o backup? Se voc\u00ea est\u00e1 se recuperando de um backup, significa que voc\u00ea est\u00e1 perdendo dados que foram acumulados durante esse tempo. Por exemplo, voc\u00ea trabalhou por tr\u00eas horas com a nova vers\u00e3o do banco de dados, e usu\u00e1rios se registraram l\u00e1. Voc\u00ea decide voltar para um backup antigo, porque com a nova vers\u00e3o o esquema n\u00e3o funciona, portanto, voc\u00ea perdeu esses usu\u00e1rios. E eles est\u00e3o insatisfeitos e reclamando.<\/em><\/p>\n<p><\/p>\n<p><em>Para dominar todo o espectro de pr\u00e1ticas que suportam Continuous Integration e Continuous Delivery, n\u00e3o \u00e9 suficiente apenas aprender a escrever... Primeiro, pode haver um n\u00famero excessivo de pr\u00e1ticas, o que seria impratic\u00e1vel. Al\u00e9m disso, existem muitas outras pr\u00e1ticas como a Scientific. H\u00e1 uma pr\u00e1tica que o GitHub popularizou em um determinado momento. Isso acontece quando voc\u00ea executa simultaneamente o c\u00f3digo antigo e o novo. \u00c9 quando voc\u00ea est\u00e1 trabalhando em uma feature incompleta, mas que pode retornar algum valor: seja como uma fun\u00e7\u00e3o ou como uma API Rest. Voc\u00ea executa tanto o novo quanto o antigo c\u00f3digo e compara a diferen\u00e7a entre eles. E se houver uma diferen\u00e7a, voc\u00ea registra esse evento. Assim, voc\u00ea sabe que sua nova feature est\u00e1 pronta para ser liberada em cima da antiga, se n\u00e3o houver diverg\u00eancias entre os dois durante um determinado per\u00edodo.<\/em> <\/p>\n<p><\/p>\n<p><em>Existem centenas dessas pr\u00e1ticas. Eu recomendaria come\u00e7ar com o transbase development. N\u00e3o \u00e9 100% baseado em Continuous Integration, mas as pr\u00e1ticas s\u00e3o as mesmas, uma n\u00e3o vive sem a outra.<\/em> <\/p>\n<p><\/p>\n<p>Voc\u00ea mencionou o transbase development como um exemplo de onde olhar as pr\u00e1ticas ou est\u00e1 sugerindo que as pessoas comecem a usar o transbase development?<\/p>\n<p><\/p>\n<p><em>Olhar, pois eles n\u00e3o poder\u00e3o us\u00e1-lo. Para utiliz\u00e1-lo, \u00e9 necess\u00e1rio ler bastante. E quando surge a pergunta para a pessoa: \"O que fazer com uma feature que leva um m\u00eas?\", isso significa que ela n\u00e3o leu sobre transbase development. Eu n\u00e3o recomendaria isso por enquanto. Eu recomendaria focar exclusivamente no tema de como dividir arquitetonicamente grandes tarefas em menores. Essa \u00e9 a ess\u00eancia da decomposi\u00e7\u00e3o.<\/em><\/p>\n<p><\/p>\n<p><em>Decomposi\u00e7\u00e3o \u00e9 uma das ferramentas do arquiteto. Primeiro fazemos a an\u00e1lise, depois a decomposi\u00e7\u00e3o, depois a s\u00edntese, e por fim a integra\u00e7\u00e3o. Assim, tudo se encaixa. E antes de chegar ao Continuous Integration, ainda precisamos passar pela decomposi\u00e7\u00e3o. No primeiro est\u00e1gio, surgem quest\u00f5es, e j\u00e1 estamos falando do quarto est\u00e1gio, ou seja, quanto mais frequentemente fizermos a integra\u00e7\u00e3o, melhor. \u00c9 ainda um pouco cedo para isso; seria melhor primeiro dividir seu mon\u00f3lito.<\/em> <\/p>\n<p><\/p>\n<p><em>\u00c9 necess\u00e1rio desenhar algumas setas e quadrados em algum esquema. Voc\u00ea n\u00e3o pode dizer que agora vou mostrar o diagrama arquitet\u00f4nico de um novo aplicativo e mostrar um quadrado, dentro do qual h\u00e1 um bot\u00e3o verde para o aplicativo. De qualquer forma, haver\u00e1 mais quadrados e setas. Em qualquer diagrama que eu vi, havia mais de um. E a decomposi\u00e7\u00e3o, mesmo no n\u00edvel da representa\u00e7\u00e3o gr\u00e1fica, j\u00e1 est\u00e1 sendo feita. Portanto, os quadrados podem ser feitos independentes. Caso contr\u00e1rio, eu tenho grandes perguntas para o arquiteto.<\/em> <\/p>\n<p><\/p>\n<p>H\u00e1 uma pergunta no chat: \"Se a revis\u00e3o \u00e9 obrigat\u00f3ria e leva muito tempo, um dia ou mais?\".<\/p>\n<p><\/p>\n<p>Voc\u00eas t\u00eam problemas com a pr\u00e1tica. A revis\u00e3o n\u00e3o deve levar um dia ou mais. \u00c9 a mesma quest\u00e3o do anterior, s\u00f3 que um pouco mais suave. Se uma revis\u00e3o leva um dia, significa que provavelmente est\u00e1 revisando alguma mudan\u00e7a muito grande. Portanto, \u00e9 preciso fazer mudan\u00e7as menores. No desenvolvimento Transbase, que Oleg recomendou, existe uma abordagem que se chama revis\u00e3o cont\u00ednua. A ideia \u00e9 que fazemos um pull request t\u00e3o pequeno intencionalmente, porque buscamos fundir constantemente e aos poucos. Assim, o pull request altera uma abstra\u00e7\u00e3o ou 10 linhas. Com isso, a revis\u00e3o leva apenas alguns minutos. <\/p>\n<p><\/p>\n<p>Se a revis\u00e3o leva um dia ou mais, significa que algo est\u00e1 errado. Primeiro, pode ser que voc\u00eas tenham problemas com a arquitetura. Ou \u00e9 um trecho grande de c\u00f3digo, com 1.000 linhas, por exemplo. Ou sua arquitetura \u00e9 t\u00e3o complexa que a pessoa n\u00e3o consegue entender. Este \u00e9 um problema secund\u00e1rio, mas tamb\u00e9m ter\u00e1 que ser resolvido. Talvez a revis\u00e3o nem seja necess\u00e1ria. Voc\u00ea tamb\u00e9m deveria pensar sobre isso. A revis\u00e3o \u00e9 algo que te ret\u00e9m. Ela traz seus benef\u00edcios de forma geral, mas \u00e9 preciso entender por que voc\u00eas est\u00e3o fazendo isso. Isso \u00e9 uma forma de transmitir informa\u00e7\u00f5es rapidamente para voc\u00eas, \u00e9 uma forma de estabelecer alguns padr\u00f5es internos ou o qu\u00ea? Por que voc\u00eas precisam disso? Porque a revis\u00e3o precisa ser feita de forma bem r\u00e1pida ou deve ser cancelada. Isso \u00e9 como o desenvolvimento Transbase \u2013 \u00e9 uma hist\u00f3ria muito bonita, mas apenas para pessoas experientes. <\/p>\n<p><\/p>\n<p>Quanto \u00e0s 4 m\u00e9tricas, eu ainda recomendaria colet\u00e1-las para entender a que isso leva. Olhar os n\u00fameros, visualizar a imagem, qu\u00e3o ruim tudo est\u00e1. <\/p>\n<p><\/p>\n<p><em>(Dmitry) Estou pronto para discutir isso com voc\u00ea. N\u00fameros e m\u00e9tricas s\u00e3o \u00f3timos, pr\u00e1ticas tamb\u00e9m s\u00e3o \u00f3timas. Mas \u00e9 preciso entender se isso \u00e9 necess\u00e1rio para o neg\u00f3cio. Existem neg\u00f3cios que n\u00e3o precisam dessa velocidade de mudan\u00e7a. Conhe\u00e7o empresas onde n\u00e3o se pode fazer mudan\u00e7as a cada 15 minutos. E n\u00e3o \u00e9 porque elas s\u00e3o ruins. \u00c9 um ciclo de vida. E para implementar recursos como branches e toggles, \u00e9 necess\u00e1rio profundo conhecimento.<\/em> <\/p>\n<p><\/p>\n<p>\u00c9 complicado. Se voc\u00ea quiser ler mais sobre a hist\u00f3ria do recurso toggle, recomendo muito. <noindex><a rel=\"nofollow\" href=\"https:\/\/trunkbaseddevelopment.com\/\">https:\/\/trunkbaseddevelopment.com\/<\/a><\/noindex>. E h\u00e1 um \u00f3timo artigo de Martin Fowler sobre toggles: sobre os tipos, ciclos de vida, etc. O recurso toggle \u00e9 complexo. <\/p>\n<p><\/p>\n<p><em>E voc\u00ea ainda n\u00e3o respondeu \u00e0 pergunta: 'Jenkins \u00e9 necess\u00e1rio ou n\u00e3o?'<\/em><\/p>\n<p><\/p>\n<p>Jenkins n\u00e3o \u00e9 necess\u00e1rio em nenhum caso, na verdade. Se formos s\u00e9rios, ferramentas como Jenkins e Gitlab trazem conveni\u00eancia. Voc\u00ea ver\u00e1 se a compila\u00e7\u00e3o foi bem-sucedida ou n\u00e3o. Elas podem ajudar, mas n\u00e3o trazem a pr\u00e1tica. Elas podem apenas mostrar um c\u00edrculo \u2013 OK, n\u00e3o OK. E isso se voc\u00ea ainda estiver escrevendo testes, porque se n\u00e3o houver testes, isso \u00e9 quase sem sentido. Portanto, \u00e9 necess\u00e1rio porque \u00e9 mais conveniente, mas, no geral, voc\u00ea pode viver sem ele e n\u00e3o perder\u00e1 muito. <\/p>\n<p><\/p>\n<p><em>Ou seja, se voc\u00ea tem pr\u00e1ticas, isso significa que ele n\u00e3o \u00e9 necess\u00e1rio?<\/em><\/p>\n<p><\/p>\n<p>Exatamente. Recomendo o teste de Jez Humble. Tenho uma rela\u00e7\u00e3o ambivalente com o \u00faltimo ponto. Mas, de maneira geral, se voc\u00ea tem tr\u00eas coisas: voc\u00ea est\u00e1 fazendo merges constantemente, voc\u00ea executa testes em commits na master, e corrige rapidamente a build na master, ent\u00e3o, talvez voc\u00ea n\u00e3o precise de mais nada. <\/p>\n<p><\/p>\n<p><em>Enquanto aguardamos perguntas dos participantes, eu tenho uma pergunta. N\u00f3s falamos sobre c\u00f3digo de produto. Voc\u00ea usou isso para c\u00f3digo de infraestrutura? \u00c9 o mesmo c\u00f3digo, tem os mesmos princ\u00edpios e o mesmo ciclo de vida, ou existem ciclos de vida e princ\u00edpios diferentes? Normalmente, quando todos falam sobre Integra\u00e7\u00e3o e Desenvolvimento Cont\u00ednuos, esquecem que tamb\u00e9m existe c\u00f3digo de infraestrutura. E, ultimamente, isso tem crescido cada vez mais. Dever\u00edamos aplicar todas essas regras l\u00e1?<\/em><\/p>\n<p><\/p>\n<p>N\u00e3o \u00e9 s\u00f3 que dever\u00edamos, seria \u00f3timo, porque isso definitivamente tornar\u00e1 a vida mais f\u00e1cil. Assim que trabalhamos com c\u00f3digo, n\u00e3o com scripts em bash, mas temos um c\u00f3digo adequado.<\/p>\n<p><\/p>\n<p><em>Espere, espere, um script em bash tamb\u00e9m \u00e9 c\u00f3digo. N\u00e3o mexa no meu velho amor.<\/em> <\/p>\n<p><\/p>\n<p>Bem, n\u00e3o vou pisotear suas mem\u00f3rias. Eu tenho uma avers\u00e3o pessoal ao bash. Ele quebra de forma feia e estranha o tempo todo. E quebra frequentemente de maneira imprevis\u00edvel, por isso n\u00e3o gosto dele. Mas bem, vamos supor que voc\u00ea tenha um c\u00f3digo em bash. Pode ser que eu realmente n\u00e3o entenda e que existam frameworks decentes para testes. Eu simplesmente n\u00e3o estou por dentro. E acabamos obtendo os mesmos benef\u00edcios.<\/p>\n<p><\/p>\n<p>Assim que come\u00e7amos a trabalhar com infraestrutura como c\u00f3digo, enfrentamos os mesmos problemas que os desenvolvedores. H\u00e1 alguns meses, me deparei com uma situa\u00e7\u00e3o em que um colega me enviou um pull request de 1.000 linhas em bash. E voc\u00ea fica preso na revis\u00e3o por 4 horas. Os problemas s\u00e3o os mesmos. Ainda \u00e9 c\u00f3digo. E ainda \u00e9 um trabalho colaborativo. Ficamos atolados com pull requests e lidando com os mesmos conflitos de mesclagem do bash, por exemplo. <\/p>\n<p><\/p>\n<p>Atualmente, estou observando muito ativamente toda essa quest\u00e3o do programar infraestrutura de forma bonita. Estou usando o Pulumi na infraestrutura. \u00c9 programa\u00e7\u00e3o pura. \u00c9 ainda mais atraente, porque tenho todas as capacidades da linguagem de programa\u00e7\u00e3o, ou seja, usei os mesmos ifs para criar toggles bonitos e tudo ficou bem. Ou seja, minha mudan\u00e7a j\u00e1 est\u00e1 no master. Todos j\u00e1 a veem. Outros engenheiros est\u00e3o cientes disso. J\u00e1 influenciou em algo. Mas, ao mesmo tempo, n\u00e3o foi ativado para todas as infraestruturas. Foi ativado para meus ambientes de teste, por exemplo. Portanto, respondendo sua pergunta mais uma vez, \u00e9 necess\u00e1rio. Isso definitivamente simplifica a vida para n\u00f3s, engenheiros que trabalham com c\u00f3digo. <\/p>\n<p><\/p>\n<p><em>Algu\u00e9m tem mais perguntas?<\/em> <\/p>\n<p><\/p>\n<p>Eu tenho uma pergunta. Quero continuar a discuss\u00e3o com Oleg. No geral, acho que voc\u00ea est\u00e1 certo, se uma tarefa leva um m\u00eas, voc\u00ea tem um problema com a arquitetura, tem um problema com an\u00e1lise, decomposi\u00e7\u00e3o, planejamento, etc. Mas tenho a sensa\u00e7\u00e3o de que, se voc\u00ea come\u00e7ar a tentar viver de acordo com a Integra\u00e7\u00e3o Cont\u00ednua, come\u00e7ar\u00e1 a corrigir as dores do planejamento, porque n\u00e3o h\u00e1 como escapar disso. <\/p>\n<p><\/p>\n<p><em>(Oleg) Sim, \u00e9 isso mesmo. Em termos de esfor\u00e7o, essa pr\u00e1tica \u00e9 compar\u00e1vel a qualquer outra pr\u00e1tica s\u00e9ria que muda a cultura. O mais dif\u00edcil de superar s\u00e3o os h\u00e1bitos, especialmente os maus h\u00e1bitos. E se para implementar essa pr\u00e1tica for necess\u00e1ria uma mudan\u00e7a significativa nos h\u00e1bitos dos outros: desenvolvedores, ger\u00eancia, gerente de produ\u00e7\u00e3o, voc\u00ea pode esperar surpresas.<\/em> <\/p>\n<p><\/p>\n<p><em>Quais podem ser essas surpresas? Suponha que voc\u00ea decidiu que vai integrar mais frequentemente. E na integra\u00e7\u00e3o, voc\u00ea tem algumas outras coisas ligadas, como artefatos. E na sua empresa, por exemplo, h\u00e1 uma pol\u00edtica de que cada artefato deve ser de alguma forma contabilizado em algum sistema de armazenamento de artefatos. E isso leva algum tempo. A pessoa precisa marcar que, como gerente de lan\u00e7amento, ela verificou esse artefato para estar pronto para ser levado \u00e0 produ\u00e7\u00e3o. Se isso leva de 5 a 10 a 15 minutos, mas voc\u00ea faz uma implementa\u00e7\u00e3o uma vez por semana, perder meia hora uma vez por semana n\u00e3o \u00e9 um grande \u00f4nus.<\/em> <\/p>\n<p><\/p>\n<p><em>Se voc\u00ea est\u00e1 fazendo Continuous Integration 10 vezes por dia, ent\u00e3o precisa multiplicar 10 por 30 minutos. E isso ultrapassa a quantidade de tempo de trabalho desse gerente de lan\u00e7amento. Ele simplesmente fica cansado de fazer isso. Existem custos constantes envolvidos em certas pr\u00e1ticas. E \u00e9 isso.<\/em> <\/p>\n<p><\/p>\n<p><em>E voc\u00ea precisa ou cancelar essa regra para parar de fazer essa imbecilidade, ou seja, voc\u00ea n\u00e3o atribui manualmente uma grada\u00e7\u00e3o de conformidade de algo a algo. Voc\u00ea confia totalmente em um conjunto automatizado de testes de prontid\u00e3o.<\/em> <\/p>\n<p><\/p>\n<p><em>E se voc\u00ea precisa de alguma prova de algu\u00e9m para que o chefe assine, e voc\u00ea n\u00e3o entra na produ\u00e7\u00e3o sem que o Vasya diga que ele permite, etc. \u2013 toda essa bobagem se interp\u00f5e nas pr\u00e1ticas. Porque se h\u00e1 atividades associadas a um \u00f4nus, tudo aumenta 100 vezes. Portanto, a mudan\u00e7a muitas vezes n\u00e3o ser\u00e1 recebida de forma positiva por todos. Porque \u00e9 dif\u00edcil corrigir os h\u00e1bitos das pessoas.<\/em> <\/p>\n<p><\/p>\n<p><em>Quando uma pessoa faz um trabalho habitual, ela o realiza praticamente sem pensar. A carga cognitiva \u00e9 igual a zero. Ela apenas executa com base no que j\u00e1 est\u00e1 pronto, j\u00e1 tem uma lista de verifica\u00e7\u00e3o em mente, ela j\u00e1 fez isso mil vezes. E assim que voc\u00ea chega e diz: 'Vamos cancelar essa pr\u00e1tica e a partir de segunda-feira implementaremos uma nova', para ele isso se torna uma carga cognitiva pesada. E essa carga surge imediatamente para todos.<\/em> <\/p>\n<p><\/p>\n<p><em>Portanto, a coisa mais simples, embora esta lux\u00faria nem todos possam se permitir, \u00e9 o que sempre fa\u00e7o. Quando um novo projeto \u00e9 iniciado, geralmente todas as pr\u00e1ticas n\u00e3o testadas s\u00e3o imediatamente incorporadas ao projeto. Enquanto o projeto \u00e9 jovem, n\u00e3o corremos muitos riscos. N\u00e3o h\u00e1 produ\u00e7\u00e3o, n\u00e3o h\u00e1 nada a desmoronar. Ent\u00e3o, podemos usar isso como uma pr\u00e1tica. Esta abordagem funciona. No entanto, nem todas as empresas t\u00eam a oportunidade de iniciar esses projetos com frequ\u00eancia. Embora isso tamb\u00e9m seja um pouco estranho, porque agora \u00e9 uma verdadeira transforma\u00e7\u00e3o digital, todos devem iniciar experimentos para acompanhar a concorr\u00eancia.<\/em> <\/p>\n<p><\/p>\n<p>Aqui voc\u00ea se depara com o fato de que primeiro deve haver um entendimento do que \u00e9 necess\u00e1rio fazer. O mundo n\u00e3o \u00e9 perfeito, a produ\u00e7\u00e3o tamb\u00e9m n\u00e3o \u00e9 perfeita. <\/p>\n<p><\/p>\n<p><em>Sim, essas coisas est\u00e3o interligadas.<\/em><\/p>\n<p><\/p>\n<p>Os neg\u00f3cios tamb\u00e9m nem sempre entendem que precisam ir por esse caminho. <\/p>\n<p><\/p>\n<p><em>H\u00e1 uma situa\u00e7\u00e3o em que nenhuma mudan\u00e7a \u00e9 poss\u00edvel. \u00c9 uma situa\u00e7\u00e3o em que a equipe est\u00e1 sob press\u00e3o constante. A equipe j\u00e1 est\u00e1 bastante esgotada. Ela n\u00e3o tem nenhum tempo de sobra para experimentos. Eles est\u00e3o produzoindo funcionalidades o dia todo. E a ger\u00eancia quer cada vez mais funcionalidades. \u00c0s vezes, na verdade, nada muda. A equipe pode apenas ser informada de que amanh\u00e3 far\u00e3o da mesma forma que fizeram ontem, apenas precisam entregar um pouco mais de funcionalidades. Nesse sentido, nenhuma transi\u00e7\u00e3o para novas pr\u00e1ticas \u00e9 poss\u00edvel. Esta \u00e9 uma situa\u00e7\u00e3o cl\u00e1ssica onde n\u00e3o h\u00e1 tempo para afiar o machado, \u00e9 preciso cortar \u00e1rvores, por isso se usa um machado cego. Aqui n\u00e3o h\u00e1 conselhos simples.<\/em> <\/p>\n<p><\/p>\n<p><em>(Dmitry) Vou ler um esclarecimento do chat: \"Mas \u00e9 necess\u00e1rio um grande cobertura de testes em diferentes n\u00edveis. Quanto tempo \u00e9 dedicado aos testes? \u00c9 meio caro, consome muito tempo.\"<\/em><\/p>\n<p><\/p>\n<p><em>(Oleg) Este \u00e9 um equ\u00edvoco cl\u00e1ssico. Deve haver testes suficientes para que voc\u00ea mesmo tenha confian\u00e7a. Continuous Integration n\u00e3o \u00e9 algo onde primeiro 100% dos testes s\u00e3o realizados e, s\u00f3 ent\u00e3o, voc\u00ea come\u00e7a a aplicar essa pr\u00e1tica. Continuous Integration reduz sua carga cognitiva, pois cada uma das mudan\u00e7as que voc\u00ea v\u00ea \u00e9 t\u00e3o \u00f3bvia que voc\u00ea entende se vai quebrar algo ou n\u00e3o, mesmo sem testes. Voc\u00ea pode testar isso mentalmente rapidamente, porque s\u00e3o pequenas mudan\u00e7as. Mesmo que voc\u00ea tenha apenas testadores manuais, \u00e9 mais f\u00e1cil para eles. Voc\u00ea lan\u00e7ou e disse: 'Veja, n\u00e3o quebrou nada?'. Eles verificaram e disseram: 'N\u00e3o, n\u00e3o quebrou'. Porque o testador sabe onde olhar. Voc\u00ea tem um commit relacionado a um fragmento de c\u00f3digo. E isso \u00e9 explorado por um comportamento espec\u00edfico.<\/em><\/p>\n<p><\/p>\n<p>Aqui voc\u00ea, claro, embelezou. <\/p>\n<p><\/p>\n<p><em>(Dmitry) Aqui eu n\u00e3o concordo. Existe a pr\u00e1tica \u2013 desenvolvimento atrav\u00e9s de testes, que justamente vai salvar disso.<\/em> <\/p>\n<p><\/p>\n<p><em>(Oleg) Bem, eu ainda n\u00e3o cheguei a isso. A primeira ilus\u00e3o \u00e9 que voc\u00ea precisa escrever exatamente 100% dos testes ou n\u00e3o deve se envolver em Continuous Integration. Isso n\u00e3o \u00e9 verdade. S\u00e3o duas pr\u00e1ticas paralelas. E elas n\u00e3o dependem diretamente uma da outra. Sua cobertura de testes deve ser ideal. Ideal significa que voc\u00ea mesmo tem confian\u00e7a de que a qualidade do master, na qual ficou ap\u00f3s o commit, permite que voc\u00ea pressione o bot\u00e3o 'Deploy' com seguran\u00e7a na sexta-feira \u00e0 noite, mesmo b\u00eabado. Como voc\u00ea alcan\u00e7a isso? Atrav\u00e9s de revis\u00f5es, cobertura e um bom monitoramento.<\/em> <\/p>\n<p><\/p>\n<p><em>Um bom monitoramento \u00e9 indistingu\u00edvel de testes. Se voc\u00ea roda os testes uma vez no pre-prod, ent\u00e3o eles verificam todos os seus cen\u00e1rios de usu\u00e1rio uma vez e s\u00f3. Mas se voc\u00ea os executa em um ciclo infinito, ent\u00e3o isso \u00e9 o seu sistema de monitoramento que continuamente testa \u2013 caiu ou n\u00e3o caiu. Nesse caso, a diferen\u00e7a \u00e9 apenas entre uma execu\u00e7\u00e3o ou m\u00faltiplas. Um conjunto muito bom de testes \u2026, que s\u00e3o executados infinitamente, \u00e9 monitoramento. E o monitoramento adequado deve ser assim.<\/em> <\/p>\n<p><\/p>\n<p><em>E, portanto, como exatamente voc\u00ea alcan\u00e7ar\u00e1 esse estado, quando voc\u00ea implantar na sexta-feira \u00e0 noite e ir para casa, \u00e9 outra quest\u00e3o. Pode ser que voc\u00ea seja apenas um verdadeiro destemido.<\/em> <\/p>\n<p><\/p>\n<p>Vamos voltar um pouco ao Continuous Integration. N\u00f3s nos desviamos para uma pr\u00e1tica um pouco mais complicada. <\/p>\n<p><\/p>\n<p><em>E a segunda ilus\u00e3o \u00e9 que o MVP, dizem, deve ser feito rapidamente, ent\u00e3o os testes n\u00e3o s\u00e3o necess\u00e1rios. N\u00e3o \u00e9 bem assim. O fato \u00e9 que quando voc\u00ea escreve uma user story para o MVP, voc\u00ea pode desenvolv\u00ea-la de forma improvisada, ou seja, ouviu que h\u00e1 uma user story e imediatamente come\u00e7ou a codific\u00e1-la, ou trabalhar com TDD. E com TDD, como a pr\u00e1tica mostra, n\u00e3o leva mais tempo, ou seja, os testes s\u00e3o um efeito colateral. A pr\u00e1tica de TDD n\u00e3o se trata de testar. Apesar de se chamar Test Driven Development, na verdade n\u00e3o se trata de testes. \u00c9 mais uma abordagem arquitetural. \u00c9 uma maneira de escrever exatamente o que \u00e9 necess\u00e1rio e evitar escrever o que n\u00e3o \u00e9. Esta pr\u00e1tica foca na pr\u00f3xima itera\u00e7\u00e3o do seu desenvolvimento de ideias em termos de cria\u00e7\u00e3o da arquitetura da aplica\u00e7\u00e3o.<\/em> <\/p>\n<p><\/p>\n<p><em>Portanto, n\u00e3o \u00e9 t\u00e3o f\u00e1cil se livrar dessas ilus\u00f5es. MVP e testes n\u00e3o se contradizem. Na verdade, se voc\u00ea fizer o MVP seguindo a pr\u00e1tica de TDD, far\u00e1 isso melhor e mais r\u00e1pido do que se o fizer sem essa pr\u00e1tica, de forma improvisada.<\/em><\/p>\n<p><\/p>\n<p>\u00c9 uma ideia muito n\u00e3o \u00f3bvia e complicada. Quando voc\u00ea ouve que agora vai escrever mais testes e, ao mesmo tempo, vai fazer algo mais r\u00e1pido, isso soa absolutamente inadequado. <\/p>\n<p><\/p>\n<p><em>(Dmitry) Aqui muitos, quando falam de MVP, \u00e9 que a gente tem pregui\u00e7a de escrever algo de qualidade. E essas s\u00e3o, de fato, coisas diferentes. N\u00e3o devemos transformar o MVP em algo ruim que n\u00e3o funciona.<\/em> <\/p>\n<p><\/p>\n<p>Sim, voc\u00ea est\u00e1 certo.<\/p>\n<p><\/p>\n<p><em>E ent\u00e3o, de repente, o MVP vai para produ\u00e7\u00e3o.<\/em><\/p>\n<p><\/p>\n<p>Para sempre. <\/p>\n<p><\/p>\n<p>E TDD soa muito estranho quando voc\u00ea ouve que est\u00e1 escrevendo testes e aparentemente est\u00e1 fazendo mais trabalho. Isso soa muito esquisito, mas na verdade acaba sendo mais r\u00e1pido e mais bonito. Quando voc\u00ea escreve um teste, j\u00e1 est\u00e1 pensando muito sobre qual c\u00f3digo e como ser\u00e1 chamado, al\u00e9m de qual comportamento esperamos dele. Voc\u00ea n\u00e3o diz apenas que escreveu uma fun\u00e7\u00e3o que faz algo. Voc\u00ea primeiro pensa sobre quais condi\u00e7\u00f5es ela ter\u00e1, como ser\u00e1 chamada. Voc\u00ea cobre isso com testes e a partir disso entende como as interfaces do seu c\u00f3digo v\u00e3o parecer. Isso impacta muito na arquitetura. Seu c\u00f3digo se torna automaticamente mais modular, porque voc\u00ea primeiro tenta entender como vai test\u00e1-lo e s\u00f3 depois o escreve. <\/p>\n<p><\/p>\n<p>A minha experi\u00eancia com TDD foi assim: em algum momento contratei um mentor em Ruby, quando ainda era programador Ruby. Ele disse: \u201cVamos fazer TDD\u201d. Pensei: \u201cPoxa, agora vou ter que escrever mais coisas\u201d. E combinamos que durante duas semanas eu escreveria todo o c\u00f3digo funcional em Python utilizando TDD. Ap\u00f3s duas semanas percebi que n\u00e3o queria voltar atr\u00e1s. Ao tentar aplicar isso em todos os lugares, percebi o quanto ficou mais f\u00e1cil at\u00e9 para pensar. Mas isso n\u00e3o \u00e9 \u00f3bvio, ent\u00e3o recomendo a todos que, se acham que TDD \u00e9 complicado, demorado e desnecess\u00e1rio, tentem se manter firmes nisso por apenas duas semanas. Para mim, foram suficientes.<\/p>\n<p><\/p>\n<p><em>(Dmitry) Podemos desenvolver essa ideia do ponto de vista da opera\u00e7\u00e3o da infraestrutura. Antes de lan\u00e7armos algo novo, fazemos monitoramento e depois colocamos em pr\u00e1tica. Nesse caso, o monitoramento se torna um teste normal. E h\u00e1 desenvolvimento por meio do monitoramento. Mas quase todos dizem que isso \u00e9 demorado, que d\u00e1 trabalho, e acabam fazendo um esbo\u00e7o tempor\u00e1rio. Se fizermos um monitoramento adequado, entendemos o estado do sistema CI. E no sistema CI, h\u00e1 muito monitoramento. N\u00f3s compreendemos o estado do sistema e o que h\u00e1 dentro dele. E durante o desenvolvimento, fazemos exatamente o sistema para que ele atinja o estado desejado.<\/em> <\/p>\n<p><\/p>\n<p><em>Essas pr\u00e1ticas s\u00e3o conhecidas h\u00e1 bastante tempo. Discutimos isso h\u00e1 cerca de 4 anos. Mas em 4 anos, praticamente nada mudou.<\/em> <\/p>\n<p><\/p>\n<p><em>Mas nesta nota, proponho encerrar a discuss\u00e3o oficial.<\/em><\/p>\n<p><\/p>\n<p>V\u00eddeo (inserido como elemento de m\u00eddia, mas por algum motivo n\u00e3o funciona):<\/p>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/zZ3qXVN3Oic\">https:\/\/youtu.be\/zZ3qXVN3Oic<\/a><\/noindex><br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/518406\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041e\u0431\u0441\u0443\u0434\u0438\u043c \u043f\u043e\u0447\u0435\u043c\u0443 CI-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 CI \u2013 \u044d\u0442\u043e \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u043e \u0440\u0430\u0437\u043d\u043e\u0435. \u041a\u0430\u043a\u0443\u044e \u0431\u043e\u043b\u044c CI \u043f\u0440\u0438\u0437\u0432\u0430\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c, \u043e\u0442\u043a\u0443\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0438\u0434\u0435\u044f, \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0447\u0442\u043e \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u044c \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Jenkins. \u041c\u044b\u0441\u043b\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u043a\u043b\u0430\u0434 \u043f\u0440\u043e Continuous Integration \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0435\u0449\u0435 \u0433\u043e\u0434 \u043d\u0430\u0437\u0430\u0434, \u043a\u043e\u0433\u0434\u0430 \u044f \u0445\u043e\u0434\u0438\u043b \u043f\u043e \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u0438\u0441\u043a\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u0443. \u041f\u043e\u043e\u0431\u0449\u0430\u043b\u0441\u044f [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":93886,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-93885","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.3 - aioseo.com -->\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\/pt\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\udd47Continuous Integration \u043a\u0430\u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u0430 \u043d\u0435 Jenkins. \u0410\u043d\u0434\u0440\u0435\u0439 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u043e\u0432 | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov\" \/>\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-09-10T17:42:23+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-09-10T17:42:23+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\udd47Integra\u00e7\u00e3o Cont\u00ednua como pr\u00e1tica, e n\u00e3o Jenkins. Andrey Alexandrov | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\udd47Continuous Integration \u043a\u0430\u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u0430 \u043d\u0435 Jenkins. \u0410\u043d\u0434\u0440\u0435\u0439 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u043e\u0432 | ProHoster","og:url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov","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-09-10T17:42:23+00:00","article:modified_time":"2020-09-10T17:42:23+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"93885","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 11:37:31","updated":"2022-09-27 15:57:30","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/93885","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=93885"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/93885\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/93886"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=93885"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=93885"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=93885"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}