Beleza pessoal, então para a gente começar aqui nosso laboratório, a primeira coisa que a gente vai fazer é logar aqui no GitHub e fazer a criação de um novo repositório. o item imagine a privacidade vai ser pública e eu vou inicializar com um arquivo de um ridme também tá bom a gente pode criar aqui nosso repositório repositório criado através de um terminal aqui vou criar um outro diretório que vai se chamar fullcycle opa já existe não tem nada dentro dele a gente vai clonar aqui nosso repositório e vamos inicializar esse diretório com o nosso repositório do git com o vs code no meu caso aqui você pode utilizar a ideia da sua preferência beleza vs code inicializado a gente já tem aqui a nossa idéia aberta ea primeira coisa que a gente vai fazer aqui é criar os nossos arquivos que a gente vai utilizar para nossa demo tá então o primeiro arquivo que a gente vai criar aqui vai ser um arquivo chamado app.py. Ele vai ter aqui esse conteúdo. Então a gente está basicamente aqui utilizando o Flask para subir uma API. A gente vai ter aqui uma rota de homepage, uma rota no barra times e uma rota aqui também no barra campeonatos, ambos vão suportar aqui os métodos de get e post tá, para a gente poder simular aqui nosso nossa pipeline, a gente também tá fazendo aqui uma uma tratativa para a página não encontrada E está inicializando aqui a nossa aplicação na porta 9000 Certo? O que mais que a gente vai ter aqui, turma? A gente também vai criar um arquivo de requirements.txt esse arquivo vai ser utilizado para a gente mapear aqui todas as nossas dependências então aqui são as dependências que nossa aplicação vai precisar essas duas últimas aqui pra gente rodar teste e o que nos leva também o nosso terceiro arquivo aqui, que vai ser um arquivo que eu vou dar um nome aqui de test-app.py. E o que a gente vai ter nesse arquivo? Basicamente, os testes unitários ali do nosso código, né? Então, teste teste conexão a gente testando aqui por exemplo fazer um get no barra times um get aqui no campeonatos fazer post né post mesma coisa então basicamente são os testes unitários aqui que a gente vai utilizar pra nossa demonstração tá certo bom uma vez que esses esses arquivos estão todos criados antes da gente poder começar aqui tipo ter a pipeline e tudo mais vamos só validar que está tudo funcionando bem, né? Então, eu vou abrir aqui um terminal e vou inicializar esse carinha para a gente validar que está funcionando bem. É importante você saber que eu já tenho o Python instalado aqui, então, se a gente digitar aqui, a gente consegue validar aqui, eu tenho a versão do Python já aprovisionada no meu ambiente, provavelmente eu já tenho aqui também os meus arquivos de dependência, então antes da gente poder inicializar a gente tem que ter as dependências locais né no meu caso aqui a gente pode resolver fazendo comandinho pip install menos menos no cache menos r requirements e no meu caso aqui ele falou que eu já tenho todas as dependências baixadas, então beleza, tudo certo, já que eu tenho tudo regularizado, agora eu posso basicamente inicializar aqui o nosso app, então ele já inicializou aqui, subiu aqui na porta 9000, se a gente abrir um outro terminalzinho aqui, subiu aqui na porta 9000 se a gente abrir um outro terminalzinho aqui a gente pode validar aqui essa porta 9000 ela já está no ar então a gente tem aqui a porta 9000 nosso processo Python rodando nesse PID fazendo o bind nessa porta Então a gente tem aqui a porta 9000, nosso processo Python rodando nesse PID, fazendo o bind nessa porta. E aí para a gente poder fazer aqui a validação, se está tudo funcionando bem, a gente pode fazer um curl. Vou chamar aqui o localhost na nossa porta. E a gente tem aqui a mensagem de bem-vindo como deveria acontecer conforme a gente colocou aqui certo a gente pode fazer o que aqui também a gente pode bater no barra times retorna nada para gente porque a gente não tem nenhum dado né a gente não tem nenhum dado, né? A gente não fez absolutamente nada ainda. E também o campeonatos. Também está vazio. Certo. Vamos testar inserir alguma informação dentro dessa aplicaçãozinha, né? Então, eu vou pegar aqui, por exemplo, minha chamada no barra times. E aí a gente vai colocar aqui um menos x post menos h content type application json certo menos d e aqui a gente vai passar o nosso o nosso body então o nosso body vai ser basicamente a e a gente vai passar aqui que que ele tá pedindo a gente não tem nenhuma especificação aqui né então a gente vai passar aqui por exemplo o nome colocar em minúsculo o value pode ser o oriêntias o papo eu vou passar aqui também um país a gente vai colocar aqui por exemplo brasil certo vamos ver se funciona beleza deu a mensagem aqui de time adicionado com sucesso se a gente fizer agora um novo clube tem que ver essa mensagem aqui pra gente ele está aqui bonitinho legal a gente vale do que está funcionando o local, né? Tipo, está funcionando bem. Vamos parar nosso app aqui. Se a gente rodar novamente aqui o netstat, a gente vai ver que não tem mais nenhuma porta em listing, né? Então, beleza, realmente está parado. O que mais que a gente pode fazer aqui, tá, turma? Dos arquivos que a gente tem aqui dentro, uma das coisas que a gente também pode fazer é rodar os testes unitários, né? Então, no meu caso aqui eu já tenho o PyTest instalado, se você não tiver aí, você pode instalar com o pip tá? então se a gente rodar aqui um pytest local, ele já reconhece que esse arquivo de teste aqui é o nosso arquivo que tem 6 testes escritos e aí ele passou aqui, né, todos os assertions que a gente escreveu estão funcionando bem o que a gente pode fazer para saber se cá está funcionando bacana também né a gente pode mudar aqui por exemplo sei lá sejam bem vindos né no plural isso já faria com que nosso teste quebrasse vamos testar aqui beleza né tipo ele já tá falando aqui que veio para ele não sejam bem-vindos mas que na verdade ele tava esperando aqui um não seja bem-vindo então nosso assertion deu um erro bacana vamos voltar aqui nosso nosso arquivo vou dar novamente legal tá funcionando bem então a gente já sabe aqui que funcionalmente falando o nossa aplicação tá funcionando bacana o que mais que a gente tem que testar aqui bom pensando que a gente está construindo uma pipeline de container, a gente deveria conseguir também fazer tudo isso de forma local, para saber que não está tendo nenhum tipo de erro, não é um problema na pipeline em si. Então vamos trabalhar nisso. Para isso o que a gente precisa fazer? Deixa eu só apagar esses dois arquivos desses diretórios de teste. Beleza, se a gente quiser a gente pode até apagar esse readme também. Então, beleza. O que a gente precisa fazer aqui agora? A gente precisa basicamente ter um arquivo de docker file né então a gente vai criar aqui um arquivo de docker file e o que que eu vou ter nesse arquivo eu vou ter basicamente um from utilizando uma imagem aqui com python 3.12 eu vou trabalhar aqui no diretório barra app dentro do nosso container vou fazer aqui um copy do source para dentro desse barra app vou rodar aqui as minhas dependências, vou fazer a exposição da porta 9000 e vou já rodar um comandinho aqui que é o Python instanciando o nosso app. Para isso daqui funcionar e para a gente conseguir ter uma boa separação também, uma boa organização aqui do nosso repositório, aqui do nosso repositório, eu vou criar então esse diretório, né? Search, para a gente conseguir ter todo o nosso código fonte lá dentro. Assim a gente consegue ter uma boa separação dos nossos arquivos. Beleza. Se a gente olhar aqui agora da forma que está escrito o nosso Dockerfile, parece bacana, né? A gente vai fazer um source aqui, vai fazer um copy do nosso diretório src para dentro do container. Vamos testar. Bom, para isso a gente pode utilizar o comando docker build "-t", o build que a gente vai utilizar aqui vai ser a python image, vou dar o mesmo nome do repositório que a gente criou, então vou colocar aqui python image e eu vou dar uma versão aqui de 1.0.0 certo? e vou colocar aqui um ponto que é onde está aqui referenciando o meu arquivo de dockerfile vamos ver se funciona beleza, deu um erro aqui, o que ele falou? Ele não conseguiu achar o arquivo de requirements. Eu escrevi errado? Vamos ver aqui. escrever errado beleza vamos rodar novamente legal conseguiu achar o nosso arquivo agora de requirements está baixando as dependências massa se a gente fizer o comandinho aqui docker images a gente tem que conseguir visualizar Nossa imagem aqui, Python image, certo? Que foi criada aqui há 9 segundos atrás. Bom, legal. Conseguimos buildar, né? Nossa imagem. E agora a gente deveria conseguir fazer esse mesmo teste que a gente fez só referenciando o Python local, basicamente colocando o nosso container para ser executado, para a gente validar que está funcionando bem também. Para isso, a gente pode executar aqui o comandinho docker run, menos p, a porta que a gente vai expor no nosso host, eu vou colocar 9000 que facilita aqui para gente a porta que está sendo exposta no container certo vou colocar um menos de de taxa e vou colocar aqui também a nossa imagem que é a python a imagem e uma de 100 certo? vamos executar legal, está dando um erro de login aqui deixa eu fazer login no meu docker hub ah, entendi na verdade ele está tentando fazer um docker ele está tentando baixar essa imagem do docker hub, mas porque eu passei errado, se a gente olhar aqui o docker images, faltou um vezinho, então ele está tentando buscar isso lá do nosso registro remoto, quando na verdade eu já tenho essa imagem local. Então deixa eu corrigir aqui coloquei um v100 beleza se a gente der um docker ps limpar aqui a gente consegue ver nossa imagem rodando sendo executada se a gente fizer aquele mesmo comandinho a gente vai conseguir visualizar que a gente tem uma porta aqui em listing né tá um pouquinho diferente porque agora essa porta está sendo feito o binding aqui através de um container mas se a gente fizer aquele teste do curl a gente deveria conseguir ter o mesmo resultado né então se a gente chamar aqui por exemplo times e se a gente não chamar nada não seja bem vindo e agora vou fazer a mesma inserção, vamos bater aqui no nosso Teams, legal, agora a gente já conseguiu validar aqui, está tudo funcionando bacana, de forma local, a gente está pronto para a gente conseguir iniciar aqui a construção dos nossos workflows, para a gente conseguir ter tudo isso daqui de forma automatizada né eu vou dar só uma limpada no meu ambiente então vamos pegar aqui a o que o ps o down docker stop em passar um container o aig id beleza parou e agora eu consigo fazer um docker rm aqui pra deixar o meu ambiente bacana né se a gente fizer o mesmo teste agora tentar fazer um carro aqui a gente consegue validar que a porta está fora né não tem nada rodando nessa porta consequentemente a gente vai tomar eu sei que tentar fazer qualquer coisa legal bom vamos iniciar agora a construção dos nossos workflows, para isso a gente precisa seguir uma estrutura específica de diretório, primeira coisa que a gente vai fazer aqui é a criação de um novo diretório que vai ter o nome de GitHub, dentro desse diretório GitHub a gente vai ter um diretório chamado Workflows e dentro desse diretório Workflows é onde a gente vai ter os nossos arquivos de Workflow nesse caso aqui a gente vai fazer uma pipe um pouco mais simplificada não vou seguir nenhum modelo de git flow mas vai dar para pegar o mesmo modelo assim vocês vão perceber que tipo é basicamente a gente fazer a mesma coisa só vai ter algumas promoções de código adicionais então nesse caso aqui eu vou ter basicamente dois workflows que a gente vai executar de fato, tá? Um que vai ser um feature barra fix, né? Sempre que a gente criar qualquer branch que comece com um prefixo, tem um prefixo ali, feature ou fix, a gente vai rodar algumas etapas de validação, que basicamente é o que a gente fez local aqui, tá? E aí, beleza. Tipo, tipo putz passou com sucesso a gente vai abrir automaticamente um PR de promoção do código para mim e a gente vai executar algumas etapas adicionais quando a gente for gerar a imagem de fato, né? Putz, beleza, validou, passou com sucesso ali. A gente consegue ter a garantia de que a imagem está ok, tem teste funcional, tem teste unitário. Nesse momento, daria para a gente rodar, tipo, teste integrado, por exemplo, né? Se a gente tivesse outros tipos de teste, a gente poderia colocar para ser executados também. E aí, beleza, passou tudo com sucesso a gente faz a promoção desse código para algum registro né aí pode ser alguns pode ser o resto do GitHub pode ser o próprio docker-hub pode ser algum registro privado tipo uma CR uma e CR da vida então tanto faz vai mudar um pouquinho o nosso código aqui, mas vocês vão perceber que é basicamente a mesma coisa no final do dia a gente só vai precisar ali das informações pra gente conseguir fazer a autenticação e o restante do código aqui, ele é muito parecido então beleza a gente vai criar aqui o nosso primeiro nosso primeiro workflow esse workflow vou dar um nome aqui de 0-feature em emul e acho que a gente também já pode criar aqui o nosso segundo workflow que vai ser o workflow para a main beleza o que a gente tem aqui agora? a gente já tem uma estrutura onde a gente tem um docker file a gente tem o nosso código fonte e a gente começou a construir aqui os nossos workflows para a gente executar aqui etapas de forma automatizada. Beleza, bom, primeira coisa que a gente precisa fazer aqui, a gente vai dar um nome, então então o nome desse workflow aqui vai ser feature barra fix branch beleza a gente vai criar uma trigger o que é essa trigger? basicamente o que vai ser o que a gente vai estar observando de evento para a gente poder iniciar esse Workflow. A gente pode utilizar algum Trigger tipo Workflow Dispatch, onde a gente dispara esse Workflow de forma manual. A gente pode disparar esse Work quando alguém fizer por exemplo um code review, então se vamos supor que a gente coloca para ser feito um code review quando alguém aprovar tipo esse code review, a gente consegue já disparar esse workflow ah não, a gente consegue disparar esse workflow quando a gente tiver um merge de algum pull request. Então, existem diversas triggers que a gente consegue trabalhar aqui. Inclusive, é possível até a gente abrir PR de um para o outro, de um repositório para o outro. Enfim, tem algumas possibilidades aqui nesse sentido. de um repositório para o outro, enfim, tem algumas possibilidades aqui nesse sentido, mas no nosso caso a gente vai basicamente trabalhar com um push, né, para alguma branch que tenha o prefixo de featurefix. Então nesse caso aqui a gente vai começar com um on, o que? caso aqui a gente vai começar com um ou o que um push das brancas que inicie com E Fix Beleza? Esse vai ser nosso trigger Bom, então sempre que eu tiver algum push nessas brands Eu vou disparar esse workflow E quando eu disparar esse workflow eu vou fazer alguma coisa Que coisas que eu vou fazer? Basicamente eu vou Inicializar os meus jobs tá é que eu vou fazer aqui tá turma eu já vou aproveitar para criar um terceiro arquivo vai mapear todas as ações que eu preciso fazer relacionadas ao meu CI. Tipo, sei lá, rodar os testes unitários, rodar minimamente algum tipo de lint, fazer algumas validações mais básicas para entender se o meu código está ok ou não e para eu não precisar mapear todas essas ações dentro dos meus jobs e esse arquivo ficar extremamente grande e difícil de dar manutenção eu vou separar isso em um outro arquivo. Isso vai ficar um pouquinho mais claro mais pra frente também, mas a gente basicamente separa o que a gente chama dos Reusables Workflows, a gente vai criar como se fosse um Reusable Workflow, só que esse Reusable vai acabar ficando meio que local, mas em uma empresa grande, tipo em um fluxo corporativo, você vai ter repositórios centralizados, onde algum time, por exemplo, o time de DevOps, vai centralizar a manutenção desses reusable workflows, e aí você vai ter, por exemplo, vamos pensar assim, as etapas de CI de um container em Java são diferentes de um container em Python que são diferentes de um container em Go. Então, minimamente você deveria ter um reusable que enderece essas especificidades e aí muito provavelmente você vai ter um reusable de Go, um reusable de Java, um reusable de Python. E algumas outras etapas, elas são mais genéricas. Então, por exemplo, quando você vai fazer um push de uma imagem de container para algum registry, é sempre a mesma coisa. Você está pegando o seu artefato, que é a imagem de container pra algum registry é sempre a mesma coisa, né? Tipo, você tá pegando o seu artefato que é a imagem de container e fazendo um push. Então você consegue centralizar esse tipo de ação em um único reusable e aí facilita quando você tiver que dar manutenção porque se a gente tivesse tipo, é... sempre nesse formato que é o que a gente vai fazer aqui, né? Tipo, tudo local. Imagina, tipo, sempre nesse formato que é o que a gente vai fazer aqui, né, tipo, tudo local, imagina, tipo, puta, encontrei um bug, ou sei lá, a ferramenta evoluiu, né, ou alguma action evoluiu, tipo, cara, a gente consegue, enfim, fazer a mesma coisa mais rápido, imagina a complexidade que seria pra gente conseguir alterar todos os repositórios que a gente tem dentro da corporação, então assim, é meio inviável. Então a gente sempre faz dessa forma, tá? A gente já vai trabalhar meio que nesse modelo de reusable workflow, só que esses reusables eles vão ficar locais. A única diferença é que no Empresa Grande, esses reusables eles vão ficar centralizados e a gente simplesmente vai fazer a referência desses repositórios passando o endereço do GitHub deles, tá? Tão simples quanto isso, não vai mudar absolutamente nada, é realmente só essa diferença. Então, beleza. Antes da gente continuar a declaração aqui dos jobs, vamos criar então esse novo arquivo, né? então esse novo arquivo né e esse arquivo vou dar um nome aqui de python ci, vamos dar o nome de python-ci-emo beleza é que que a gente precisa fazer aqui na nossa feature? A gente basicamente vai dar um nome para esse job. Então eu vou dar um nome aqui de Python CI. Não precisa ser o mesmo nome que está aqui embaixo, pode ser qualquer nome aqui. E aí a gente vai referenciar aqui o arquivo que a gente vai utilizar, que tem todas as especificações ali dos steps, os jobs e os steps que a gente vai chamar. E aí nesse caso aqui, a gente vai chamar de forma local. Então vai ser ponto barra, que é o nosso diretório a gente tá trabalhando GitHub traço workflows traço o nome da o arquivo que a gente tá chamando então nesse caso python-ci.eml beleza e aí a gente também vai passar aqui secrets e a gente vai utilizar aqui o inhenit tá que basicamente é tipo tudo que a gente tiver declarando de secret dentro desse arquivo eu simplesmente vou herdar, tá bom? Tem como a gente passar a fazer overrides, enfim, a gente vai mostrar um pouquinho aqui para vocês agora. Mas pensando em workflow de feature, vai ser só isso, tá? É tão simples quanto isso. A gente vai ter um trigger que vai ser tipo em um push de uma branch que vai disparar aqui um job esse job se chama python ci que vai utilizar esse arquivo aqui pra rodar, tipo, ter o mapeamento de todos os steps, os jobs e os steps que vão ser executados e as secrets elas vão trabalhar de forma é em hirant aqui, tá beleza vamos pegar então aqui nosso arquivinho de de forma em hirant aqui beleza vamos pegar então aqui nosso arquivinho de python ci que como que a gente vai começar a declarar ele aqui primeira coisa, a gente vai dar um nome eu vou chamar aqui de python ci Python CI beleza a gente vai fazer aqui também a referência de algumas permissões então eu vou colocar essas permissões aqui ah mineiro, putz como que você sabe que são essas permissões a gente consegue consultar diversas permissões deixa eu abrir uma é uma imagem aqui it hub.com GitHub.com GitHub Actions Vamos colocar aqui, ó, Permissions. Beleza. Se a gente vier aqui em Permissions, a gente consegue ter diversas permissions e o que cada um desses caras aqui fazem e permitem, tipo, pra que a gente consiga trabalhar dentro da nossa action então imagina o seguinte né por exemplo eu preciso é sei lá tipo fazer com que vamos pegar um legal aqui ó eu preciso com que meu meu reusable né ele vai criar um PR pra mim, pô então você já sabe que você vai precisar aqui de permissão de pull request com write né ah você precisa ler alguma informação de um pull request que tipo tá aberto ou fechado dentro do repositório porque você tem algum fluxo específico que precisa disso. Puta, beleza. Então, você vai precisar passar um pull request com um read para você poder trabalhar, senão você vai acabar tomando erro de permissão, tá bom? Mas voltando aqui para o nosso contexto o nosso contexto então a gente vai passar aqui todas as permissões que a gente precisa tá é E aí eu vou passar algumas coisas aqui que é de novo né minha Trigger então minha Trigger aqui começa com um nesse caso como esse cara é um reusable workflow ele a trigger dele né é justamente um workflow call né E aí eu consigo passar alguns inputs lá dentro desse reusable. O que são esses inputs? Imagina que basicamente é como se a gente estivesse declarando variáveis, onde a gente vai conseguir customizar esses valores quando a gente estiver referenciando eles. Então, eu já tenho alguns reusables configurados aqui. Ou, perdão, eu já tenho alguns usables é configurados aqui ou perdão já tem alguns inputs e deixa eu já colocar eles aqui e aí imagina o seguinte né um input que é interessante né a gente sempre deixar declarado é esse Ransom que que que é esse Ransom? Basicamente é o Runner que a gente, o flavor, o tier de Runner que a gente vai escolher para executar nossa Action. Nesse caso eu tô deixando como Ubuntu Latest e Latest como Default já, mas vamos supor que a gente tivesse com runners privados a gente tivesse ali, tipo, trabalhando com sei lá, com o Tekton, tivesse alguma outra ferramenta ali, tipo, pra gente ter runners customizados dentro da corporação e a gente conseguisse declarar outros tipos de runner aqui dentro o default seria Ubuntu latest, mas a gente poderia por exemplo se declarar outros tipos de runner aqui dentro. O default seria o Ubuntu latest, mas a gente poderia, por exemplo, passar aqui dentro do nosso workflow, passar aqui um if, e aí a gente consegue falar aqui, cara, tipo cara tipo putz eu quero customizar esse runzone então a gente coloca dentro desse if aqui por exemplo um runzone e aí eu falo assim putz XPTO né tipo a label aqui que eu vou utilizar para fazer o override daquela informação que eu estou declarando dentro do nosso reusable, tá? Nesse caso, não, a gente vai utilizar o runner default mesmo, que é o Ubuntu latest, tá? O que eu estou fazendo aqui também, além disso, né? Eu estou declarando aonde que vai ficar o meu dockerfile path. declarando aonde que vai ficar o meu dockerfile path então suponha que alguém quer vir aqui e mudar tipo não quer deixar o dockerfile na raiz tá bom é isso é possível né por padrão a gente vai buscar sempre na raiz tá e aí a gente consegue trabalhar até com diferentes docker files, né, se a gente quiser, por exemplo, mudando os workflows aqui, né, se a gente quiser testar, enfim, se isso fizer sentido, né, pra algum teste. E a gente também tá deixando um input pra esse settings file, que a gente já já vai criar e aí vai ficar um pouquinho mais claro porque que a gente tá deixando um input para esse settings file que a gente já já vai criar e vai ficar um pouquinho mais claro porque que a gente tá deixando esse cara aqui declarado já tá bom beleza que mais que a gente vai fazer aqui tá a gente vai começar a declarar os nossos jobs né então a gente tem aqui a nossos jobs eu vou colocar aqui o nosso primeiro job vai se chamar se a imagem ele vai ter um nem e se a imagem também o ranzon o runzon que esse cara vai utilizar vai ser justamente uma referência do input que a gente já está deixando como como como default então aqui eu não preciso vir aqui né e declarar por exemplo o ubuntu latest aí pô imagina que daqui a pouco a gente tem um um Open PR né aí tipo que vai ser um novo job aí imagina o seguinte né Apesar de que esse cara aqui não acho que não é obrigatório tá a gente pode deixar sem se quebrar se se for o caso, a gente pode voltar. Mas imagina o seguinte, a gente vai ter que vir aqui e colocar, tipo, novamente, né, um runzone. E aí, se esse cara aqui, tipo, for customizado um, for rodar com um runner e outro com outro, ok. Mas, na maioria das vezes, a gente executa sempre com o mesmo runner e aí se um dia mudar a gente vai ter que mudar um monte de lugar né esse código então a gente geralmente só referencia tipo o input que a gente tem aqui pra isso a gente pode referenciar simplesmente colocando inputs, ponto e o nome do input que a gente declarou, runs on. Dessa forma aqui, a gente herda o valor que está declarado, e isso é válido para todos os outros valores que a gente declarar aqui dentro do nosso workflow, beleza? Legal. do nosso workflow, beleza? legal eu já tenho uma declaração aqui deixa eu apagar esse cara eu já tenho aqui uma declaração do meu do meu primeiro job que vai ser o de CI de image e aí os jobs, ele tem os steps que rodam dentro dele, né? Então a gente vai começar a declarar aqui os nossos steps. E aí, a gente vai basicamente seguir a mesma síntese que a gente declarou lá, por exemplo, no nosso arquivo de feature. A gente vai passar um use, e a primeira coisa que a gente vai fazer é rodar um actions barra checkout arroba v4. Putz, mineiro, cara, de onde veio isso? Vamos voltar lá para o Google. Se a gente pegar esse cara aqui e jogar no Google, o que vocês vão encontrar? Diversas actions existe um marketplace inclusive né de actions onde a gente não precisa se preocupar em construir uma lógica tipo esse cara basicamente já vai fazer um check out tipo para dentro do nosso repositório aqui da branch que a gente estiver utilizando corrente a gente consegue utilizar alguns inputs também né se a gente quiser customizar o comportamento default enfim a gente vai utilizar isso daqui com bastante frequência então basicamente essa é uma é uma action oficial do GitHub onde a gente faz um GitHub check out onde a gente faz um git check out tá tão simples quanto isso e aí a gente vai colocar aqui o nosso o segundo step Deixa eu arrumar a orientação aqui bonitinha Beleza O que é esse segundo step? Basicamente, o que a gente vai fazer aqui, tá? A gente vai, através dessa action Tá? A gente vai ler um arquivo de emol e a gente vai transformar esse arquivo de emol, os valores dele, a chave valor dele, em outputs dentro da nossa action. Por que a gente faz isso? Basicamente a gente quer ter uma certa flexibilidade aqui Em algumas coisas que a gente for customizar Então vamos criar aqui por exemplo nosso arquivinho de settings E nosso arquivo de settings a gente vai declarar algumas coisas aqui o que eu quero declarar aqui, bom coisas que podem mudar conforme as pessoas estiverem executando, né ou tipo, putz, a aplicação estiver executando, distintas aplicações estiverem executando essa pipeline é o registro, certo? Então, o registro é uma informação que pode ser alterada. No meu caso aqui, eu vou passar o meu registro. Vai ser o meu repositório do GitHub. O que mais? O repository, certo? tá é que mais é o repositor certo então o repositor e basicamente vai ser o cara que eu vou utilizar quando eu quiser fazer o meu meu push ali né eu vou dar o nome aqui de python e eu também vou colocar aqui uma customização caso alguém queira, sei lá, tipo, se eu quero ter o meu arquivo de requirements em um outro path, sei lá, enfim, eu não gostei dessa organização de deixar o meu arquivo de requirements junto, Eu não gostei dessa organização de deixar o meu arquivo de requirements junto. Então, a gente também consegue customizar aqui passando um dependencies path. Nesse caso aqui, eu vou deixar o valor que já está por padrão. Beleza. Inclusive, isso daqui poderia ser até um input, né, se a gente quisesse. A gente consegue, por exemplo, falar assim, cara, tipo, declarar um input que vai ser o dependency path, e aí quando a gente, tipo, entrar num step específico pra fazer esse tipo de validação, a gente colocar a ordem de precedência, né, então, ah, primeiro olha se tá, tipo, declarado no input, não tá declarado, tipo, olha pro valor que tá declarado em settings, não está declarado, olha para o valor que está declarado em settings, não está declarado, utiliza um valor default. Dá para fazer esse tipo de coisa também. No nosso caso aqui a gente vai deixar um pouco mais simples. Então, basicamente o que eu estou fazendo aqui? Eu estou rodando essa action e aí eu tô passando aqui o arquivo que eu quero ler para poder fazer o par se desse arquivo e transformar esses valores aqui todos em output tá é bom então beleza tipo a gente já concluiu aqui nosso segundo step e mais o que eu preciso fazer aqui turma eu vou precisar fazer um setup do python, né então imagina que esse runner ele pode ou não ter python nesse caso aqui eu vou já instalar um Python na versão 3.12, isso daqui é algo que a gente também consegue deixar, por exemplo, customizável, né? Então, ah, supondo que, pô, eu quero trabalhar com Python sei lá, 3.10, beleza, tipo, a gente consegue deixar uma nova linha aqui, né? Que vai ser tipo, sei lá 310 beleza tipo a gente consegue deixar um uma nova linha aqui né que vai ser tipo sei lá python version e a gente pode falar que esse python version é 310 e aí aqui basicamente a gente vai conseguir referenciar o output para a gente poder mudar esse valor. Nesse caso aqui eu não vou mexer, vou deixar assim mesmo. beleza e aí o que eu vou fazer aqui eu vou criar mais um step que vai ser um step de instalação das dependências né que eu vou fazer aqui instalar o pip certo e com o pip eu vou executar aquele mesmo comandinho que a gente executou local. E o que eu vou fazer aqui, turma? Vejam só, né? Aqui, eu já estou utilizando um pouco do que a gente capturou nesse segundo step. Como que eu referencio o valor que foi gerado nesse segundo step? E como você poderia saber disso se você abrir esse cara aqui você vai ver basicamente que ele sempre vai gerar nesse mesmo formato então como que eu referenciou o referência aqui é um step e o nome desse step é o settings pass parcer então esse step em específico eu tô dando um id para ele né eu poderia cuidar qualquer nome aqui eu só teria que referenciar aqui também esse essa action faz o parcer gera os outputs então eu quero buscar os outputs e qual que vai ser o nome do então esse dependências path é justamente o valor que eu declarei aqui tá ah se eu vier aqui colocar path que que vai acontecer a gente vai quebrar o pipeline tá é porque a gente vai tentar ler aqui a gente vai não vai encontrar não vai conseguir instalar as dependências e a gente vai ter erro tá bom? o que mais que eu vou fazer aqui, turma? vou rodar um lint vou rodar um upload dos meus arquivos aqui de teste, certo? E a gente precisa rodar aqui um PyTest também, né? Vamos colocar aqui, nem me e a colocar pai teste e aí a gente já vai ter instalado o pytest porque vai estar aqui no nosso arquivo de requirements, mas de qualquer forma, vamos rodar aqui também, pip install pytest, e a gente vai rodar aqui um pytest e a gente precisa referenciar o nosso arquivo de source né então sempre vai ser aqui um um source beleza beleza então a gente já tem aqui um checkout tem o nosso settings parser instalação do python instalação aqui das nossas dependências um pylinth um pytest a gente faz o piloto aqui dos nossos arquivos de de teste né que foram gerados pensando em linch eu acho que é isso né da forma que está aqui a gente já consegue ter algumas validações que são legais aí pra gente poder fazer o teste que a gente pode fazer aqui agora vamos vamos comitar todo esse código ea gente coloca para executar aqui a nossa primeira action tá abrir aqui o meu terminal beleza beleza vamos dar aqui um nome de short first commit e vamos fazer um push vamos voltar aqui agora para o nosso para o nosso repo se a gente olhar aqui nossa action deu algum erro, beleza vamos ver o que aconteceu o que ele falou aqui workflow is not a linha 9 Ah tá bom o que que ele tá falando aqui basicamente né que a gente está pedindo é pra executar tipo o nosso workflow né de python ciamo ou seja o nosso reusable né ele passa aqui o chacomit e ele fala que a gente está pedindo algumas permissões de write que não estão liberadas, né? Então, basicamente, se a gente olhar aqui, né, nossa linha 9, vamos dar uma explorada aqui para a gente entender. é onde termina aqui nosso nossas permissions né e a gente começa a invocar aqui o nosso o nosso trigo para gente corrigir isso vamos fazer o seguinte tá a gente pode vir aqui em 7 o pop-up actions General E aí a pop actions general certo a gente vai colocar aqui ó a permissão de read e write dos nossos workflows para todos os scopes certo e eu acredito que isso daqui seja suficiente para gente conseguir rodar a nossa action aqui tá bom e a gente também pode marcar esse cara aqui que a gente vai precisar no futuro allow GitHub actions to create in a purple request vamos salvar a gente pode voltar aqui na nossa action e é possível a gente dá um re-run aqui tá turma então a gente pode dar um re-run jobs vamos ver o que acontece parece que inicializou né Então você percebe né Tipo aqui nos jobs o que ele faz Ele mapeia basicamente Aquilo que a gente tinha Colocado nos nossos arquivos né E cada um desses caras Aqui são as nossas São os nossos steps né Então ó beleza tipo ele deu um erro aqui ele falou que não conseguiu encontrar o nosso arquivo ponto sur se vamos dar uma olhadinha aqui que a gente pode estar errando vamos colocar aqui ah tá bom não tem esse ponto né é basicamente só source eu acho que é isso E aí E aí E aí E aí E aí E aí E aí E aí E aí E aí E aí E aí E aí E aí E aí E aí E aí E aí Ah, uma coisa, eu estou na branch main aqui e ele disparou o nosso fluxo, então acho que tem alguma coisa errada com o nosso trigger. Vamos ver se passa legal passou tudo com sucesso e conseguiu rodar o link conseguiu rodar que os testes encontrou