Passo 11: Utilizando Branches no Código

5.0 version
Maintained

Utilizando Branches no Código

Existem muitas formas de organizar o fluxo de trabalho das mudanças no código em um projeto. Mas trabalhar diretamente na branch master do Git e implantar diretamente em produção sem testes provavelmente não é a melhor.

Testar não se trata apenas de testes unitários ou funcionais, mas também de verificar o comportamento da aplicação com dados de produção. Se você ou seus stakeholders puderem navegar pela aplicação exatamente como ela será implantada para os usuários finais, isso se tornará uma grande vantagem e permitirá que você implante com confiança. É especialmente poderoso quando pessoas não técnicas podem validar novas funcionalidades.

Continuaremos a fazer todo o trabalho na branch master do Git nos próximos passos, por uma questão de simplicidade e para evitar repetições, mas vamos ver como isso poderia funcionar melhor.

Adotando um Fluxo de Trabalho para o Git

Um possível fluxo de trabalho é criar uma branch para cada nova funcionalidade ou correção de bug. É simples e eficiente.

Descrevendo a Sua Infraestrutura

Talvez você ainda não tenha percebido, mas ter a infraestrutura armazenada em arquivos junto ao código ajuda muito. O Docker e a SymfonyCloud usam arquivos de configuração para descrever a infraestrutura do projeto. Quando um novo recurso precisa de um serviço adicional, as mudanças no código e na infraestrutura fazem parte do mesmo patch.

Criando Branches

O fluxo de trabalho começa com a criação de uma branch no Git:

1
$ git branch -D sessions-in-redis || true
1
$ git checkout -b sessions-in-redis

Este comando cria uma branch sessions-in-redis a partir da branch master. Ele faz um fork do código e da configuração da infraestrutura.

Armazenando Sessões no Redis

Como você pode ter adivinhado pelo nome da branch, nós queremos mudar o armazenamento de sessão do sistema de arquivos para um armazenamento do Redis.

Os passos necessários para tornar isso realidade são típicos:

  1. Criar uma branch no Git;
  2. Atualizar a configuração do Symfony se necessário;
  3. Escrever e/ou atualizar algum código, se necessário;
  4. Atualizar a configuração do PHP (adicionar a extensão PHP Redis);
  5. Atualizar a infraestrutura no Docker e na SymfonyCloud (adicionar o serviço Redis);
  6. Testar localmente;
  7. Testar remotamente;
  8. Fazer o merge da branch na master;
  9. Implantar em produção;
  10. Remover a branch.

Todas as alterações necessárias para os passos 2 a 5 podem ser feitas em um patch:

patch_file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
--- a/.symfony.cloud.yaml
+++ b/.symfony.cloud.yaml
@@ -15,8 +15,13 @@ runtime:
 build:
     flavor: none

+variables:
+    php-ext:
+        redis: 5.3.1
+
 relationships:
     database: "db:postgresql"
+    redis: "rediscache:redis"

 web:
     locations:
--- a/.symfony/services.yaml
+++ b/.symfony/services.yaml
@@ -2,3 +2,6 @@ db:
     type: postgresql:11
     disk: 1024
     size: S
+
+rediscache:
+    type: redis:5.0
--- a/config/packages/framework.yaml
+++ b/config/packages/framework.yaml
@@ -7,7 +7,7 @@ framework:
     # Enables session support. Note that the session will ONLY be started if you read or write from it.
     # Remove or comment this section to explicitly disable session support.
     session:
-        handler_id: null
+        handler_id: '%env(REDIS_URL)%'
         cookie_secure: auto
         cookie_samesite: lax

--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -8,3 +8,7 @@ services:
             POSTGRES_PASSWORD: main
             POSTGRES_DB: main
         ports: [5432]
+
+    redis:
+        image: redis:5-alpine
+        ports: [6379]

Não é lindo?

“Reinicie” o Docker para iniciar o serviço Redis:

1
2
$ docker-compose stop
$ docker-compose up -d

Vou deixá-lo testar localmente navegando no site. Como não há mudanças visuais e como ainda não estamos usando sessões, tudo deve funcionar como antes.

Implantando uma Branch

Antes de implantarmos em produção, devemos testar a branch na mesma infraestrutura que a de produção. Devemos também validar que tudo funciona corretamente no ambiente prod do Symfony (o site local usou o ambiente dev do Symfony).

Primeiro, certifique-se de fazer o commit das suas alterações na nova branch:

1
2
$ git add .
$ git commit -m'Configure redis sessions'

Agora, vamos criar um ambiente SymfonyCloud com base na branch do Git:

1
$ symfony env:delete sessions-in-redis --no-interaction
1
$ symfony env:create

Este comando cria um novo ambiente da seguinte forma:

  • A branch herda o código e a infraestrutura da branch atual do Git (sessions-in-redis);
  • Os dados provêm do ambiente master (também conhecido como produção), tirando um snapshot consistente de todos os dados de serviço, incluindo arquivos (que o usuário fez upload, por exemplo) e bancos de dados;
  • Um novo cluster dedicado é criado para implantar o código, os dados e a infraestrutura.

Como a implantação segue as mesmas etapas da implantação para produção, as migrações do banco de dados também serão executadas. Essa é uma ótima forma de validar se as migrações funcionam com os dados de produção.

Os ambientes que não são master são muito semelhantes ao master, exceto por algumas pequenas diferenças: por exemplo, os e-mails não são enviados por padrão.

Após a conclusão da implantação, abra a nova branch em um navegador:

1
$ symfony open:remote

Note que todos os comandos da SymfonyCloud funcionam na branch atual do Git. Esse comando abre a URL da aplicação implantada para a branch sessions-in-redis; a URL será semelhante a https://sessions-in-redis-xxx.eu.s5y.io/.

Teste o site nesse novo ambiente, você deve ver todos os dados que você criou no ambiente master.

Se você adicionar mais conferências no ambiente master, elas não aparecerão no ambiente sessions-in-redis e vice-versa. Os ambientes são independentes e isolados.

Se o código evoluir no master, você sempre pode fazer o rebase da branch do Git e implantar a versão atualizada, resolvendo os conflitos tanto para o código quanto para a infraestrutura.

Você pode até mesmo sincronizar os dados do master de volta para o ambiente sessions-in-redis:

1
$ symfony env:sync

Depurando Implantações de Produção antes da Implantação

Por padrão, todos os ambientes SymfonyCloud usam as mesmas configurações do ambiente master/prod (também conhecido como ambiente prod do Symfony). Isso permite que você teste a aplicação em condições reais. Isso lhe dá a sensação de desenvolver e testar diretamente em servidores de produção, mas sem os riscos associados. Isso me lembra os bons velhos tempos quando fazíamos a implantação via FTP.

Em caso de problema, você pode querer mudar para o ambiente dev do Symfony:

1
$ symfony env:debug

Quando terminar, volte para as configurações de produção:

1
$ symfony env:debug --off

Aviso

Nunca habilite o ambiente dev e nunca habilite o Profiler do Symfony na branch master; isso tornaria sua aplicação muito lenta e abriria muitas vulnerabilidades sérias de segurança.

Testando Implantações de Produção antes da Implantação

Ter acesso à próxima versão do site com dados de produção abre muitas oportunidades: desde testes visuais de regressão até testes de desempenho. O Blackfire é a ferramenta perfeita para o trabalho.

Consulte a etapa sobre “Desempenho” para saber mais sobre como você pode usar o Blackfire para testar o seu código antes de implantar.

Fazendo Merge para Produção

Quando você estiver satisfeito com as alterações na branch, faça o merge do código e da infraestrutura de volta para a branch master do Git:

1
2
$ git checkout master
$ git merge sessions-in-redis

E implante:

1
$ symfony deploy

Ao implantar, apenas as alterações de código e infraestrutura são enviadas para a SymfonyCloud; os dados não são afetados de forma alguma.

Pondo as Coisas em Ordem

Por fim, ponha as coisas em ordem removendo a branch Git e o ambiente SymfonyCloud:

1
2
$ git branch -d sessions-in-redis
$ symfony env:delete --env=sessions-in-redis --no-interaction

  • « Previous Passo 10: Construindo a Interface de Usuário
  • Next » Passo 12: Escutando Eventos

This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.