Integração e implantação contínuas para Python com ações do GitHub
Criar software é uma conquista que vale a pena comemorar. Mas o software nunca é estático. Bugs precisam ser corrigidos, recursos precisam ser adicionados e a segurança exige atualizações regulares. No cenário atual, com o domínio das metodologias ágeis, os sistemas DevOps robustos são cruciais para gerenciar uma base de código em evolução. É aí que o GitHub Actions brilha, capacitando os desenvolvedores Python a automatizar fluxos de trabalho e garantir que seus projetos se adaptem perfeitamente às mudanças.
GitHub Actions para Python capacita os desenvolvedores a automatizar fluxos de trabalho com eficiência. Isso permite que as equipes mantenham a qualidade do software enquanto se adaptam às mudanças constantes.
Os sistemas de Integração Contínua e Implantação Contínua (CI/CD) ajudam a produzir software bem testado e de alta qualidade e a simplificar a implantação. GitHub Actions torna CI/CD acessível a todos, permitindo automação e customização de fluxos de trabalho diretamente em seu repositório. Este serviço gratuito permite que os desenvolvedores executem seus processos de desenvolvimento de software com eficiência, melhorando a produtividade e a confiabilidade do código.
Neste tutorial, você aprenderá a:
- Use ações github e fluxos de trabalho
- Automatize linting, teste e implantação de um projeto Python
- credenciais seguras usadas para automação
- Automatize atualizações de segurança e dependências
Este tutorial usará uma base de código existente, Real Python Reader, como ponto de partida para a criação de um pipeline de CI/CD. Você pode bifurcar o código do Real Python Reader no GitHub para acompanhar. Certifique-se de desmarcar a opção Copiar apenas o branch master
ao bifurcar. Alternativamente, se preferir, você pode construir seu próprio Real Python Reader usando um tutorial anterior.
Para tirar o máximo proveito deste tutorial, você deve se sentir confortável com pip
, criando pacotes de python, git e ter alguma familiaridade com a sintaxe da YAML.
Antes de se aprofundar no GitHub Actions, pode ser útil dar um passo atrás e aprender sobre os benefícios do CI/CD. Isso ajudará você a entender os tipos de problemas que o GitHub Actions pode resolver.
Desbloqueando os benefícios do CI/CD
Integração Contínua (CI) e Implantação Contínua (CD), comumente conhecidas como CI/CD, são práticas essenciais no desenvolvimento de software moderno. Essas práticas automatizam a integração de alterações de código, a execução de testes e a implantação de aplicações. Isso ajuda as equipes e colaboradores de código aberto a entregar alterações de código com mais frequência, de forma confiável e estruturada.
Além disso, ao publicar pacotes Python de código aberto, o CI/CD garantirá que todas as solicitações pull (PRs) e contribuições para o seu pacote atenderão às necessidades do projeto, ao mesmo tempo que padronizam a qualidade do código.
Observação: para saber mais sobre o que é uma solicitação pull e como criá-la, você pode ler a documentação oficial do GitHub.
Implantações mais frequentes com alterações menores de código reduzem o risco de mudanças de ruptura não intencionais que podem ocorrer com liberações maiores e mais complexas. Por exemplo, embora os desenvolvedores possam formatar todo o código usando as mesmas ferramentas e regras de linha, a política pode impedir que o PRS seja mesclado se os testes do código não passarem.
Na próxima seção, você aprenderá como os fluxos de trabalho do GitHub podem ajudá -lo a implementar o CI/CD em um repositório hospedado no GitHub.
Explorando fluxos de trabalho do GitHub
Os fluxos de trabalho do GitHub são um recurso poderoso do GitHub Actions. Eles permitem que você defina fluxos de trabalho de automação personalizados para seus repositórios. Se você deseja construir, testar ou implantar seu código, os fluxos de trabalho do GitHub fornecem uma solução flexível e personalizável que qualquer projeto no GitHub pode usar gratuitamente, seja o repositório público ou privado.
Embora existam muitos provedores de CI/CD, o GitHub Actions se tornou o padrão entre os projetos de código aberto no GitHub devido ao seu ecossistema expansivo, flexibilidade e baixo ou nenhum custo.
Anatomia de um arquivo de fluxo de trabalho
Os arquivos de fluxo de trabalho são arquivos YAML declaradamente escritos com uma estrutura predefinida que deve ser seguida para que um fluxo de trabalho seja executado com sucesso. Seus arquivos de fluxo de trabalho da YAML são armazenados e definidos em uma pasta .github/workflows/
no diretório raiz do seu projeto.
Sua pasta de fluxo de trabalho pode ter vários arquivos de fluxo de trabalho, cada um dos quais executará uma determinada tarefa. Você pode nomear esses arquivos de fluxo de trabalho como desejar. No entanto, por uma questão de simplicidade e legibilidade, é prática comum nomeá-los de acordo com as tarefas que realizam, como test.yml
.
Cada arquivo possui alguns elementos necessários, mas muitos, muitos mais opcionais. A documentação das ações do GitHub é completa e bem escrita, portanto, verifique-a depois de terminar de ler este tutorial.
Há três partes principais que compõem a maior parte de um arquivo de fluxo de trabalho: gatilhos, tarefas e etapas. Você abordará isso nas próximas seções.
Fluxo de trabalho gatilhos
Um gatilho é um evento que faz com que um fluxo de trabalho seja executado. Existem muitos tipos de gatilhos. Os mais comuns são aqueles que ocorrem em A:
- Solicitação pull
- empurrado commit para o ramo padrão
- Commit marcado
- Acionador manual
- Solicitação por outro fluxo de trabalho
- Nova edição sendo aberta
Você também pode querer restringir os gatilhos, limitando -o a uma ramificação ou conjunto específico de arquivos. Aqui está um exemplo simples de um gatilho que executa um fluxo de trabalho em qualquer empurre para o ramo principal:
on:
push:
branches:
- main
Para obter informações detalhadas sobre os gatilhos não abordados neste tutorial, você pode conferir a documentação oficial.
Agora que você sabe como os eventos acionam os fluxos de trabalho, é hora de explorar o próximo componente de um arquivo de fluxo de trabalho: trabalhos.
Trabalhos de fluxo de trabalho
Cada fluxo de trabalho possui uma única seção
, que é o contêiner para a carne e as batatas do fluxo de trabalho. Um fluxo de trabalho pode incluir um ou mais trabalhos que ele será executado e cada trabalho pode conter uma ou mais etapas.
Aqui está um exemplo de como seria esta seção sem nenhuma etapa:
# ...
jobs:
my_first_job:
name: My first job
my_second_job:
name: My second job
Ao criar um trabalho, a primeira coisa a fazer é definir o executor que você deseja usar para executar seu trabalho. Um runner
é uma máquina virtual (VM) hospedada no GitHub que executa seus trabalhos para você. O GitHub provisionará e desprovisionará a VM para que você não precise se preocupar em manter qualquer infraestrutura para seu CI/CD.
Existem vários sistemas operacionais suportados disponíveis. Você pode encontrar a lista completa de executores hospedados no GitHub na documentação.
Observação: executores auto-hospedados também são uma opção se as versões gratuitas e ilimitadas não atenderem às suas necessidades. Este tutorial não cobre executores auto-hospedados, mas você pode encontrar informações detalhadas sobre o uso de executores auto-hospedados na documentação oficial.
Definir um corredor leva apenas uma única linha de YAML:
# ...
jobs:
my_first_job:
name: My first job
runs-on: ubuntu-latest
# ...
my_second_job:
name: My second job
runs-on: windows-latest
# ...
No exemplo acima, my_first_job
será executado dentro de uma vm ubuntu e my_second_job
será executado dentro de uma vm Windows. Ambos usam o sufixo -latest
neste caso, mas você também pode especificar a versão exata do sistema operacional-por exemplo, ubuntu-20.24
, desde que seja um suporte suportado versão.
Etapas do fluxo de trabalho
As etapas são a parte principal de um trabalho. Como você provavelmente já deve ter adivinhado, as etapas declaram as ações que precisam ser executadas ao executar o fluxo de trabalho. Isso pode incluir tarefas como instalar o Python, executar testes, lintar seu código ou usar outra ação do GitHub.
Assim como seu código Python, tarefas comuns e repetíveis podem ser abstraídas em fluxos de trabalho separados e reutilizadas. Isso significa que você pode e deve usar ações do GitHub de outras pessoas em seus próprios fluxos de trabalho, semelhante ao que faria ao importar uma biblioteca Python, para economizar tempo na reimplementação dessa funcionalidade.
Na próxima seção, você verá como usar outras ações do GitHub e como encontrá -las.
Usando ações do GitHub para Python
Embora os fluxos de trabalho façam parte das ações do GitHub, os fluxos de trabalho também podem conter ações do GitHub. Em outras palavras, você pode usar as ações de outras pessoas ou organização em seu fluxo de trabalho. De fato, é uma prática comum e altamente incentivada a usar as ações do GitHub existentes em seus arquivos de fluxo de trabalho. Essa prática economiza tempo e esforço, aproveitando as funcionalidades pré-construídas.
Se você tiver uma tarefa específica para realizar, provavelmente haverá uma ação do GitHub disponível para fazê-la. Você pode encontrar ações relevantes do GitHub no GitHub Marketplace, que você verá a seguir.
Explorando o GitHub Marketplace
O Github Marketplace é um repositório on -line de todas as ações que as pessoas podem usar em seus próprios fluxos de trabalho. Github, fornecedores de terceiros e indivíduos construem e mantêm essas ações do GitHub. Qualquer pessoa pode usar o modelo de ação do Github para criar sua própria ação e hospedá -la no mercado.
Isso levou a uma vasta gama de ações do GitHub disponíveis para quase todos os tipos de automação de tarefas imagináveis. Todas as ações no GitHub Marketplace são de código aberto e de uso gratuito.
Na próxima seção, você analisará duas ações do GitHub que você usará para cada projeto Python.
Incluindo ações em fluxos de trabalho
Cada fluxo de trabalho baseado em Python que você cria precisa não apenas transferir seu repositório atual para o ambiente de fluxo de trabalho, mas também instalar e configurar o Python. Felizmente, o GitHub tem ações oficiais do GitHub para ajudar em ambas as tarefas:
# ...
jobs:
my_first_job:
name: My first job
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- run: python -m pip install -r requirements.txt
No exemplo acima, você pode ver que o primeiro passo em steps
é usar a ação oficial checkout
. Esta ação faz check-out do código do seu repositório no espaço de trabalho atual do GitHub, permitindo que seu fluxo de trabalho o acesse. O @4
seguinte ao checkout
é um especificador de versão, indicando qual versão da ação usar. A partir de agora, a versão mais recente é a v4.2.2, portanto você pode consultá-la usando esta sintaxe para especificar a versão principal mais recente.
A segunda etapa deste exemplo configura o Python no ambiente. Novamente, este exemplo usa a ação oficial do GitHub para fazer isso devido ao seu apoio e desenvolvimento contínuos. A maioria das ações, se não todas, tem configurações extras que você pode adicionar à etapa.
A documentação da ação Setup Python contém a lista completa de configurações. Por enquanto, o mínimo que você precisa para instalar o Python em seu ambiente de fluxo de trabalho é declarar qual versão do Python você deseja instalar.
Na etapa final do exemplo, você usa o comando executar
. Este comando permite que você execute qualquer comando Bash
ou PowerShell
, dependendo de qual corredor você está usando para a etapa. Nesse caso, você está instalando as dependências do projeto no arquivo de requisitos.
Felizmente, você pode ver como as ações poderosas podem ser. Com muito pouco código e esforço, você tem uma maneira reprodutível de configurar um ambiente pronto para criar, testar e implantar seu projeto Python.
Agora você tem uma compreensão básica da estrutura de um arquivo de fluxo de trabalho e de como criar seu primeiro fluxo de trabalho para um projeto. Na próxima seção, você fará exatamente isso com um exemplo do mundo real.
Criando seu primeiro fluxo de trabalho
É hora de seguir as etapas de adição de CI/CD a um projeto existente do mundo real, o Real Python Reader. Antes de adicionar fluxos de trabalho para testar e implantar este pacote, você deve primeiro começar com o linting.
Um linter é uma ferramenta que analisa seu código e procura erros, problemas estilísticos e construções suspeitas. O linhagem permite abordar os problemas e melhorar sua qualidade de código antes de compartilhá -lo com outras pessoas. Ao iniciar seu CI/CD com o LING, você garantirá que seu código seja limpo e legível antes de implantar o pacote no Pypi.
Observação: se linting é um conceito novo para você, então você pode aprender mais sobre ele lendo sobre Ruff, um linter Python moderno.
Para este fluxo de trabalho, você usará Ruff para limpar o código Python. Mas se ainda não o fez, primeiro bifurque o repositório, incluindo todas as ramificações, e depois clone-o. Certifique-se de substituir seu-nome de usuário pelo seu nome de usuário do GitHub:
$ git clone git@github.com:your-username/reader.git
$ cd reader/
$ git checkout github-actions-tutorial
$ mkdir -p .github/workflows/
Depois de clonar o repositório bifurcado e alterar seu diretório de trabalho atual, você precisará alternar para a filial pré-existente denominada github-ação-tutorial
. Se essa ramificação não estiver disponível, provavelmente você esqueceu de desmarcar a opção copiar a opção mestre somente ao formar. Nesse caso, você deve excluir o garfo, voltar ao repositório original, bifurá -lo novamente e garantir que você inclua todas as filiais desta vez.
Depois de mudar com sucesso para a ramificação correta, crie uma pasta para armazenar seus fluxos de trabalho. Esta pasta deve ser chamada de Flóis de trabalho/
e ser um subdiretório da pasta .github/
.
NOTA: Quando você bifurcar um repositório com ações do GitHub existente, você pode ver um aviso solicitando que você os habilite depois de clicar na guia Ações do seu repositório bifurcado. Este é um recurso de segurança. Ao confirmar que deseja ativar as ações, você não terá problemas após o restante deste tutorial.
Agora você está pronto para criar seu primeiro fluxo de trabalho onde definirá seus gatilhos, configurará o ambiente e instalará o Ruff. Para começar, você pode definir seus gatilhos no arquivo lint.yml
:
name: Lint Python Code
on:
pull_request:
branches:
- master
push:
branches:
- master
workflow_dispatch:
Mesmo que não seja necessário, é considerado uma prática recomendada dar a cada um dos seus fluxos de trabalho um nome claro e legível por humanos. Este nome aparecerá na coluna esquerda da guia Ações no seu repositório GitHub. Ajuda a identificar os fluxos de trabalho disponíveis e filtrar através das execuções anteriores do fluxo de trabalho:
Depois de definir o nome, você pode mudar seu foco para os gatilhos para este fluxo de trabalho. No código acima, existem três gatilhos diferentes definidos que podem iniciar o fluxo de trabalho:
- Abrindo um pedido de tração
- Empurrando compromissos locais
- Despachando o fluxo de trabalho manualmente
Os dois primeiros acionarão o fluxo de trabalho em qualquer evento de solicitação push ou pull na ramificação master
. Isso significa que qualquer alteração no código acionará a execução desse fluxo de trabalho, seja você enviando diretamente para master
ou usando uma solicitação pull para mesclar o código na ramificação master
em seu repositório.
Nota: Este fluxo de trabalho é acionado por eventos na ramificação mestre
enquanto você está trabalhando em outra ramificação. Se você deseja ver a ação entrar em vigor imediatamente após pressionar seus compromissos ao Github, considere adicionar github-Atações-tutorial
à lista de ramificações monitoradas pelo fluxo de trabalho.
Não é óbvio o que o gatilho final faz. De acordo com a documentação, é comumente usado para executar novamente um fluxo de trabalho que falhou por motivos não relacionados a alterações de código, como uma chave de API expirada. No entanto, o gatilho workflow_dispatch
funciona apenas quando o arquivo de fluxo de trabalho está na ramificação padrão.
Com os gatilhos definidos, é hora de prosseguir para a próxima etapa na criação do arquivo de fluxo de trabalho, que é definir os trabalhos e configurar o ambiente:
name: Lint Python Code
on:
pull_request:
branches:
- master
push:
branches:
- master
workflow_dispatch:
jobs:
lint: # The name of the job
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: "pip"
A maior parte desse código deve parecer familiar a partir de exemplos anteriores, mas existem algumas pequenas diferenças. Primeiro, você nomeou o trabalho Lint
para descrever o que ele faz. Este é apenas um nome, para que você possa escolher qualquer nome que desejar, desde que ele adere à sintaxe da YAML. Você também definiu o corredor que usará para esse fluxo de trabalho como ubuntu-Latest
.
Em seguida, você notará que a ação Setup-Python
agora está configurada para armazenar em cache as dependências do PIP de quaisquer pacotes instalados. Isso ajuda a acelerar seu fluxo de trabalho em execuções futuras se as versões de um pacote forem iguais. Em vez de puxá -los da Pypi, ele usará as versões em cache.
Nota: Para saber mais sobre como você pode usar o cache em seus fluxos de trabalho, você pode conferir a documentação do GitHub.
Agora que seu fluxo de trabalho possui um gatilho e corredor definidos e, com o seu código e o Python instalado, é hora de instalar o Ruff e executá -lo para fingir o código. Você pode fazer isso adicionando mais duas etapas ao seu trabalho Lint
:
name: Lint Python Code
on:
pull_request:
branches:
- master
push:
branches:
- master
workflow_dispatch:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: "pip"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install ruff
- name: Run Ruff
run: ruff check --output-format=github
Nas duas últimas etapas do trabalho Lint
, você usa o comando execute
que você viu anteriormente. Como parte da sintaxe da YAML, você notará um símbolo de tubo ( |
) na segunda linha. Isso indica uma string multi-line. O comando Executar
interpretará as seguintes linhas como comandos separados e os executará em sequência.
Depois de instalar o Ruff, o fluxo de trabalho finalmente termina executando o Ruff para procurar erros de linha. Com este comando, você pode especificar que deseja que a saída seja otimizada para executar em um fluxo de trabalho github
com a tag -output-format
.
Observação: se você usa Ruff e tem suas próprias configurações fora do padrão, você pode substituir essas duas últimas etapas pela ação GitHub do próprio Ruff.
Parabéns! Você concluiu seu primeiro fluxo de trabalho. Depois que esse fluxo de trabalho estiver comprometido com o seu repositório e empurrado, o GitHub executará automaticamente esse fluxo de trabalho de linha quando a condição de gatilho for atendida. Você também pode acionar esse fluxo de trabalho manualmente a qualquer momento no site do GitHub. Para fazer isso, vá para a guia Ações no seu repositório, selecione o fluxo de trabalho desejado do lado esquerdo e clique em Execute o fluxo de trabalho :
Agora que você tem um fluxo de trabalho e entende como os fluxos de trabalho funcionam, é hora de criar um que execute a suíte de teste no Real Python Reader.
Criando um fluxo de trabalho de teste automatizado
Agora que você já começou com seu primeiro fluxo de trabalho do GitHub, é hora de ver o que será sem dúvida o mais importante de todos os fluxos de trabalho deste pacote: testes automatizados.
O Real Python Reader usa pytest
como sua estrutura de teste. E, dado o que você já aprendeu sobre as ações do GitHub, você pode até ver como pode editar o fluxo de trabalho de linha para transformá -lo em um fluxo de trabalho de teste. Afinal, você seguirá as mesmas etapas para se preparar para executar pytest
. É importante observar que, ao testar um pacote de software, você deve testá -lo em todas as versões suportadas do Python.
Mas primeiro, como acontece com todos os fluxos de trabalho do GitHub, você precisa declarar os gatilhos para o fluxo de trabalho de teste:
name: Run Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_call:
workflow_dispatch:
Grande parte do exposto acima é o mesmo do fluxo de trabalho de linha anterior, mas com uma diferença - agora há um novo gatilho, workflow_call
. Muito parecido com workflow_dispatch
, workflow_call
é um gatilho predefinido que permite que outros fluxos de trabalho acionem esse fluxo de trabalho.
Isso significa que se você tiver um fluxo de trabalho no futuro que também exija a aprovação dos testes, em vez de repetir o código, você poderá solicitar ao novo fluxo de trabalho que use esse fluxo de trabalho de teste. O fluxo de trabalho acionará esse fluxo de trabalho de teste como uma de suas etapas e garantirá que ele seja aprovado antes de passar para as outras etapas do trabalho. Portanto, chega de repetições e você pode manter seus fluxos de trabalho mais curtos e diretos.
Embora você não use esse método de reutilização do fluxo de trabalho no seu fluxo de trabalho test.yml
, você conseguiria isso da mesma maneira que chama outras ações do GitHub em seu arquivo de fluxo de trabalho, usando o usa
palavra -chave:
# Github-username/repo/path/to/workflow@version
- uses: realpython/reader/.github/workflows/test.yml@master
Aqui, você pode ver que pode reutilizar um fluxo de trabalho passando uma string semelhante a um caminho para usa
. Ele deve começar com o nome de usuário e o nome do repositório do github, seguido pelo caminho para o arquivo de fluxo de trabalho que você deseja usar. @Master
Diz o novo fluxo de trabalho que você deseja usar a versão do fluxo de trabalho de teste da ramificação mestre
. E agora, você pode ver como as ações poderosas podem ser. Reutilizar os fluxos de trabalho é uma enorme vantagem das ações do GitHub.
Agora que você definiu os gatilhos para o fluxo de trabalho de teste, é hora de abordar a questão: como você testa em várias versões do Python? Na próxima seção, você verá como pode definir suas etapas uma vez e executá -las várias vezes, com cada execução em uma versão diferente do Python.
Teste em múltiplas versões de Python
No fluxo de trabalho do linting, você usou a ação setup-python
em suas etapas
para configurar o Python 3.13 na instância do Ubuntu, que ficou assim:
# ...
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: "pip"
# ...
# ...
Infelizmente, você não pode simplesmente adicionar uma lista de versões Python a python-version
e ser feito. O que você precisa é de uma matriz para testar em várias versões do Python.
Para citar a documentação oficial:
Uma estratégia de matriz permite usar variáveis em uma única definição de trabalho para criar automaticamente várias execuções de trabalho que são baseadas nas combinações das variáveis. Por exemplo, você pode usar uma estratégia de matriz para testar seu código em várias versões de um idioma ou em vários sistemas operacionais. (Fonte)
Resumindo, quaisquer variáveis que você definir em sua matriz
executarão as mesmas etapas do trabalho, mas usando essas variáveis. Aqui, você deseja executar em diferentes versões do Python, mas também pode usar isso para executar ou construir seu código em diferentes sistemas operacionais.
Declarar uma estratégia é relativamente simples. Antes de definir suas etapas, mas como parte de seu trabalho, você pode definir a estratégia necessária:
name: Run Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_call:
workflow_dispatch:
jobs:
testing:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
Como você pode ver, você está declarando uma variável python-version
, que é uma matriz de números de versão. Ótimo, esta é a primeira parte feita! A segunda parte é informar a ação Setup-Python
que você deseja usar essas versões usando uma sintaxe de variável especial:
name: Run Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_call:
workflow_dispatch:
jobs:
testing:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
A etapa de configuração do Python do fluxo de trabalho agora tem duas alterações. O primeiro é o nome adicionado
na etapa. Como você aprendeu anteriormente, isso não é necessário, mas o ajudará a identificar qual versão do Python falhou ao referenciar a versão Python em nome da etapa. Isso é útil, dado que esta etapa será executada para cinco versões diferentes do Python.
A segunda mudança é que, em vez de codificar o número da versão na parte with: python-version
de setup-python
, agora você pode consultar o python- versão
definida na matriz.
O GitHub possui alguns contextos especiais que você pode acessar como parte de seus fluxos de trabalho. Matriz é uma delas. Ao definir a matriz como parte da estratégia, python-version
tornou-se agora uma propriedade do contexto da matriz. Isso significa que você pode acessar qualquer variável definida como parte da matriz com a sintaxe de ponto (.
), por exemplo, matrix.python-version
.
Embora isso não seja algo que precisa ser feito para o Real Python Reader, você pode fazer o mesmo com diferentes versões do SO. Por exemplo:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
Você poderia então usar a mesma notação de ponto para acessar a variável os
definida na matriz com matrix.os
.
Agora que você sabe usar uma matriz para executar suas etapas declarativamente usando uma versão diferente do Python, é hora de concluir o fluxo de trabalho de teste na íntegra.
Finalizando o fluxo de trabalho de teste
Existem apenas mais algumas etapas necessárias para concluir o fluxo de trabalho. Agora que o Python está instalado, o fluxo de trabalho precisará instalar as dependências do desenvolvedor e, finalmente, executar pytest
.
O pacote Real Python Reader usa um arquivo de configuração pyProject.toml
para declarar suas dependências. Ele também possui dependências opcionais do desenvolvedor, que incluem pytest
. Você pode instalá -los da mesma maneira que instalou o Ruff anteriormente, usando o comando run
:
name: Run Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_call:
workflow_dispatch:
jobs:
testing:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install .[dev]
Esta etapa é tudo que você precisa para instalar as dependências necessárias. A única etapa restante é executar pytest
:
name: Run Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_call:
workflow_dispatch:
jobs:
testing:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install .[dev]
- name: Run Pytest
run: pytest
Neste ponto, você tem um fluxo de trabalho de linha e teste que é acionado sempre que um evento de PR ou push ocorre no mestre. Em seguida, você voltará sua atenção para a parte do CD do CI/CD e aprenderá como você pode publicar automaticamente um pacote no Pypi.
Publicando seu pacote automaticamente no PyPI
O terceiro fluxo de trabalho completa o que a maioria das pessoas vê como um pipeline mínimo de IC/CD. Esse terceiro fluxo de trabalho fornece uma maneira reprodutível e consistente de construir e publicar um pacote. O pacote Real Python Reader utiliza a biblioteca Build
usada em python para gerar arquivos de distribuição Python, que podem ser implantados no PyPI.
Quando os fluxos de trabalho ficam um pouco mais complicados e têm várias etapas ou trabalhos, é recomendável que você escreva as etapas e o fluxo. Isso o ajudará a executar todas as etapas na ordem correta para que as ações do GitHub que você usa sejam configuradas corretamente desde o início. Isso economizará seu tempo posteriormente, ajudando a evitar possíveis bugs em seu fluxo de trabalho de construção.
Aqui estão as etapas do fluxo de trabalho para o arquivo implant.yml
:
- Configure o ambiente instalando o Python e criando dependências
- Construa o pacote colocando arquivos de saída em uma pasta
dist/
- Publique os arquivos de distribuição no PyPI
- Crie uma versão do GitHub se publicada com sucesso
Na próxima seção, você enfrentará os dois primeiros itens da lista e terá boa parte do seu fluxo de trabalho escrito.
Configurando e construindo o pacote
Tal como acontece com os dois fluxos de trabalho anteriores, a primeira etapa é definir os acionadores do fluxo de trabalho. Você viu alguns gatilhos comuns que giram em torno de fluxos de trabalho típicos de desenvolvedores, mas liberar automaticamente a cada novo PR ou push para o branch principal não é ideal para o Real Python Reader.
Faz mais sentido alterar a versão do pacote após várias solicitações pull, correções de bugs ou após adicionar novos recursos. A maneira moderna de acionar tal lançamento após um aumento de versão é usar o melhor amigo do desenvolvedor, o Git.
O Git permite que você marque um compromisso para denotar um ponto notável no tempo no desenvolvimento do software. Esta geralmente é a ferramenta de escolha para definir uma nova versão. As ações do GitHub têm suporte interno para o uso de tags Git como gatilhos através das tags
Palavra-chave:
name: Publish to PyPI
on:
push:
tags:
- "*.*.*"
Como você pode ver aqui, os gatilhos também suportam padrões glob. Portanto, um asterisco (*
) pode corresponder a qualquer caractere em uma sequência. O padrão descrito acima corresponderá a qualquer caractere seguido por um ponto decimal (.
), outro caractere, outro ponto decimal e, finalmente, outro caractere.
Isso significa que o 1.0.0 é uma correspondência válida, como é 2.5.60. Isso corresponde ao versão semântica usada pelo Real Python Reader. Você também pode usar v*.*.*
Em vez disso, se preferir. Portanto, suas tags git devem começar com um v
, que significa versão . Por exemplo, v1.0.0 seria uma tag válida.
Para acionar esse fluxo de trabalho, você marcaria um compromisso com o nome da versão:
$ git tag -a "1.0.0" -m "1.0.0"
$ git push --tags
Empurrando sua nova tag para o GitHub, acionará esse fluxo de trabalho. Em seguida, você configurará o ambiente e instalará as dependências:
name: Publish to PyPI
on:
push:
tags:
- "*.*.*"
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install .[build]
- name: Build package
run: python -m build
Primeiro, você define o trabalho publica
e instala o Python 3.13 em uma VM Ubuntu. A próxima etapa instala as dependências de construção do Real Python Reader. Na última etapa, você usa o mesmo comando run
que você usou antes, mas desta vez, em vez de executar o Ruff ou pytest
, você criará o Real Python Reader pacote. Por padrão, build
colocará os arquivos de distribuição em uma pasta chamada dist
.
Excelente! Você implementou as duas primeiras partes principais do plano de fluxo de trabalho. Antes de implantar no PyPI, você deve saber como manter seu token de API PyPI seguro.
Mantendo seus segredos seguros
Como você aprendeu anteriormente, os fluxos de trabalho têm acesso a contextos especiais como matrix
. Outro contexto ao qual todos os fluxos de trabalho têm acesso são o contexto Secrets
. Ao armazenar dados confidenciais como um segredo repositório , você pode garantir que nunca vaze acidentalmente chaves da API, senhas ou outras credenciais. Seu fluxo de trabalho pode acessar essas credenciais confidenciais usando o contexto Secrets
.
Você pode adicionar segredos ao seu repositório no site do GitHub. Depois de adicioná -los, você não pode visualizá -los ou editá -los. Você só pode substituí -los por um novo valor. É uma boa ideia revisar a documentação do GitHub para ver como adicionar segredos no site do Github. Os documentos oficiais são atualizados continuamente com qualquer alteração da interface do usuário, tornando -os a melhor fonte para aprender a usar esse recurso do GitHub.
Implantando seu pacote
Depois de proteger sua chave da API como um segredo do GitHub, você pode acessá -la no fluxo de trabalho:
name: Publish to PyPI
on:
push:
tags:
- "*.*.*"
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install .[build]
- name: Build package
run: python -m build
- name: Test publish package
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
repository-url: https://test.pypi.org/legacy/
- name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
Nesta etapa, você pode usar a ação oficial do Github da Python Packaging Authority (Pypa), que gerencia Pypi. Esta ação do GitHub faz a maior parte do trabalho e só precisa de uma referência ao seu token da API PYPI. Novamente, por padrão, ele procurará na sua pasta dist
para qualquer nova versão de um pacote para fazer upload.
Em vez de usar um nome de usuário e senha tradicionais para se autenticar para o Pypi, é melhor prática usar um token de API com escopo para versões automáticas.
Como você está usando um token de API e não há nome de usuário, usar __token__
como nome de usuário informa ao GitHub Action que a autenticação de token está sendo usada. Assim como na estratégia de matriz anterior, você pode usar a notação de ponto para acessar o contexto secreto, como em secrets.PYPI_API_TOKEN
.
O nome do segredo quando armazenado no GitHub não importa, desde que faça sentido para você. O segredo do GitHub é denominado PYPI_API_TOKEN
, então você faz referência a ele dentro do fluxo de trabalho usando esse nome.
Você deve ter notado que o fluxo de trabalho inclui uma etapa de teste antes da publicação do pacote no Pypi. Esta etapa é quase idêntica à etapa de publicação, com uma diferença importante: você precisará fornecer um repositório-url
para substituir o URL padrão e empurrar o pacote para test.pypi.org.
Usar TestPyPI é uma excelente maneira de garantir que seu pacote seja compilado e versionado corretamente. Ele permite identificar e resolver quaisquer problemas potenciais que possam causar problemas ao publicar no repositório principal do PyPI.
Se você estiver acompanhando seu próprio fork do repositório e pretende enviar sua versão para o PyPI, será necessário atualizar o nome do projeto para um nome exclusivo. Se você não atualizar o nome do projeto, receberá um erro HTTP 403 ao tentar carregá-lo. Isso ocorre porque você não tem permissão para publicar o pacote realpython-reader
no PyPI. Atualizar o nome do projeto permitirá que você publique sua própria versão.
Por exemplo, você poderia adicionar seu nome de usuário como prefixo ao nome do projeto:
[build-system]
requires = ["setuptools>=61.0.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "username-realpython-reader"
# ...
Há apenas mais uma etapa do fluxo de trabalho para ser concluída: criar uma versão do GitHub para promover e depois compartilhar a versão diretamente. Antes de fazer isso, você aprenderá sobre as variáveis de ambiente do GitHub.
Acessando variáveis de ambiente do GitHub
Para publicar uma versão em um repositório GitHub, é necessário um token GitHub. Você pode ter usado isso antes, se já usou a API GitHub. Dado o risco de segurança do uso de tokens pessoais do GitHub em fluxos de trabalho, o GitHub cria um token somente leitura no contexto de segredos por padrão. Isso significa que você sempre terá acesso a ele se precisar.
Além disso, todo Runner do Github inclui a prática do Github CLI por padrão. Isso torna a execução de determinadas tarefas, como criar uma versão, muito mais simples. A CLI do GitHub tem muitas maneiras de autenticar o usuário, uma das quais é definindo uma variável de ambiente chamada github_token
.
Você pode ver onde isso vai dar. O token GitHub fornecido pode ser usado para acessar a CLI e, em última análise, criar uma maneira perfeita de criar a versão GitHub. Esta seria a aparência no fluxo de trabalho:
name: Publish to PyPI
on:
push:
tags:
- "*.*.*"
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install .[build]
- name: Build package
run: python -m build
- name: Test publish package
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
repository-url: https://test.pypi.org/legacy/
- name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create ${{ github.ref_name }} ./dist/* --generate-notes
Você verá que nas linhas 39 e 40, o fluxo de trabalho atribui especificamente o token GitHub do contexto de segredos a uma variável de ambiente chamada GITHUB_TOKEN
. Quaisquer valores-chave definidos em env
serão definidos como variáveis de ambiente para a etapa atual. Isso significa que quando você executa o GitHub CLI (gh
), ele terá acesso ao token por meio da variável de ambiente atribuída. A CLI do GitHub não pode acessar diretamente o próprio contexto de segredos.
O GitHub também permite acessar um contexto especial chamado github
. O fluxo de trabalho faz referência ao atributo ref_name
no contexto github
. Isso é definido nos documentos do Github da seguinte forma:
O nome de referência curto da ramificação ou tag que acionou a execução do fluxo de trabalho. (Fonte)
Portanto, github.ref_name
será substituído pelo atributo que acionou o fluxo de trabalho, que neste caso é o nome da tag git.
O comando gh
acima criará uma versão com o mesmo nome da tag usada para acionar a versão, fará upload de todos os arquivos de ./dist
e gerará automaticamente notas de versão. Essas notas de lançamento incluem quaisquer PRs que os desenvolvedores fundiram desde que criaram o último lançamento, dando o devido crédito aos autores com links e nomes de usuário por suas contribuições.
Você pode adicionar quaisquer detalhes ausentes às notas de versão. Lembre-se de que as versões podem ser editadas após a criação se você precisar incluir informações adicionais, como avisos de descontinuação.
Parabéns! Agora você tem linting, testes e implantação automatizados. Você pode marcar seu commit mais recente e o fluxo de trabalho de implantação final deverá ser executado com sucesso:
Agora que o Real Python Reader tem um pipeline de CI/CD para garantir que quaisquer alterações futuras na base de código sejam robustas e usem código legível e consistente, você pode adicionar mais um fluxo de trabalho ao Real Python Reader. A cereja no topo do nosso bolo CI/CD, por assim dizer.
Na próxima seção, você aprenderá como configurar o Dependabot para automatizar atualizações de segurança e dependências.
Automatizando atualizações de segurança e dependência
Assim como o código Python, seus fluxos de trabalho do GitHub precisam ser mantidos e atualizados. Além disso, as bibliotecas nas quais o código do Real Python Reader depende estão sempre mudando e atualizando, por isso é difícil manter e gerenciar dependências.
Pode ser particularmente difícil manter-se informado sobre quaisquer atualizações de segurança lançadas por suas dependências se você não estiver acompanhando ativamente o projeto no GitHub ou nas redes sociais. Felizmente, o GitHub tem uma ferramenta útil para ajudar com ambos os problemas. Entre no Dependabot!
O DependBot é uma ferramenta de automação que não apenas o notificará de uma vulnerabilidade de segurança em suas dependências, mas, se configurada, criará automaticamente um PR para atualizar e corrigir o problema para você. Tudo o que você precisa fazer é revisar o PR e a mesclagem automatizados. Com o DependBot, manter seu pacote atualizado e livre de vulnerabilidades de segurança conhecido é rápido e fácil, economizando tempo que você pode usar para melhorar seu código ou adicionar novos recursos.
Você pode configurar o DependeBot para atender às necessidades do seu projeto. Aqui, o pacote Real Python Reader possui requisitos bastante básicos. Os dois objetivos são:
- Para ser notificado quando houver uma atualização de dependência disponível.
- Para ajudar a manter os outros fluxos de trabalho atualizados.
Esses requisitos são definidos em um arquivo de configuração chamado dependabot.yml
. Ao contrário dos outros fluxos de trabalho, o arquivo dependabot.yml
vive na própria pasta .github
, não em .github/workflows
.
Como esse arquivo tem apenas doze linhas de comprimento e agora você está mais familiarizado com a sintaxe da YAML, você pode dar uma olhada na configuração final do Dependabot:
---
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
A propriedade version
é uma parte obrigatória do arquivo. É aqui que você definirá a versão do Dependabot a ser usada, e a versão 2 é a mais recente. Outra seção obrigatória são as atualizações
. É para onde vai a maior parte da configuração. Cada atualização define o ecossistema de pacotes a ser verificado, juntamente com informações básicas sobre em qual diretório o Dependabot deve pesquisar e com que frequência.
Para a primeira atualização, o Dependabot verificará arquivos comuns onde as dependências pip
são normalmente declaradas, como requirements.txt
, pyproject.toml
e outros . Como o Real Python Reader possui um arquivo pyproject.toml
no diretório raiz, o Dependabot é instruído a procurar lá, conforme indicado pela barra ("/"
).
Com que frequência você deseja ser notificado sobre as atualizações de dependência depende de você. Cada projeto terá seus próprios requisitos. No entanto, tê -lo declarado no YAML significa que, se você achar a cadência demais ou não o suficiente, é uma mudança rápida e simples de fazer. Por enquanto, você pode usar semanalmente
.
O segundo item na lista updates
é para github-actions
. É isso mesmo, o Dependabot também verificará as ações do GitHub usadas em qualquer fluxo de trabalho no repositório, como setup-python
, para versões mais recentes! Isso torna automático o acompanhamento das versões mais recentes do GitHub Actions e é uma coisa a menos para você se preocupar.
Observação: há muito mais definições de configuração que você pode usar com o Dependabot, incluindo a opção de marcar automaticamente os usuários do GitHub para revisão quando ele cria um PR. Para obter mais informações sobre outras opções de configuração, consulte os documentos oficiais do GitHub.
Com essa configuração no lugar, o DependBot verá e verificará seu repositório uma vez por semana para ver se há alguma atualização que você pode fazer nas dependências ou em seus fluxos de trabalho. Ele criará um PR com uma correção automaticamente. Esses PRs da DependBot também executarão seus outros fluxos de trabalho para garantir que as alterações da Dependabot passem suas verificações de linha e teste. Double Win!
PRÓXIMOS PASSOS
Existem muitas outras tarefas que você pode automatizar à medida que seu repositório cresce, como triagem, rotulagem, gerenciamento de problemas obsoleta, adição de revisores ao PRS e muito mais.
Além disso, lembre -se de que as ações do GitHub são apenas um fornecedor de CI/CD. Se o seu projeto estiver hospedado no Github, as ações do GitHub poderão simplificar as coisas para você. Se o seu código estiver em outra plataforma ou você deseja experimentar alternativas, aqui está uma pequena lista de outros provedores de IC/CD:
- Gitlab
- Oleodutos do Azure
- Círculo CI
- Travis CI
Se você já usa um desses provedores ou um que não está listado, sinta-se à vontade para comentar nos comentários e compartilhar suas experiências.
Conclusão
Agora você sabe como implementar um pipeline de CI/CD robusto para um projeto Python usando GitHub Actions. Embora o objetivo deste tutorial fosse aprender como adicionar CI/CD a uma base de código existente, esperamos que agora você saiba o suficiente para trabalhar com seus próprios projetos e pacotes e criar seus próprios fluxos de trabalho do zero.
Neste tutorial, você aprendeu como:
- Use ações github e fluxos de trabalho
- Automatize linha, teste e implantação de um projeto Python
- Credenciais seguras usadas para automação
- Automatize atualizações de segurança e dependências
Ao automatizar esses processos, você melhorou significativamente a manutenção e a confiabilidade do seu projeto. Agora você tem uma maneira consistente de garantir a qualidade do código, executar testes e implantar novas versões com uma intervenção manual mínima.
Lembre-se de que CI/CD é um processo iterativo. À medida que seu projeto cresce e evolui, pode ser necessário ajustar seus fluxos de trabalho ou adicionar novos. A flexibilidade do GitHub Actions permite que você se adapte facilmente às mudanças nos requisitos.
Com essas ferramentas e práticas implementadas, você estará bem equipado para gerenciar e dimensionar seus projetos Python com eficiência.