Technology

Automatizando o Deploy de Aplicações React com Azure DevOps e AWS S3

Published: October 9, 2025

Recentemente, como parte do meu Plano de Desenvolvimento Individual (PDI) na empresa, tive o objetivo de aprofundar meus conhecimentos em práticas de DevOps aplicadas ao frontend. O foco era dominar o processo de implantação contínua (CI/CD) que utilizamos no projeto: uma aplicação React com build gerenciado pelo Vite, versionada no Azure DevOps e hospedada como site estático na AWS S3.

Agora vou compartilhar um guia prático e consolidado desse processo. O objetivo é apresentar uma arquitetura de deploy robusta, eficiente e totalmente automatizada, onde cada push para a branch principal resulta em uma nova versão da aplicação no ar, sem intervenção manual.

Arquitetura da Solução

Para construir este pipeline, utilizei três componentes principais:

  • AWS S3 (Simple Storage Service): Utilizado para hospedar os arquivos estáticos (HTML, CSS, JS) gerados pelo build do React/Vite. Sua configuração de "Static website hosting" é ideal para essa finalidade.
  • Azure DevOps (Pipelines): Orquestrador do processo de CI/CD. Ele é responsável por detectar alterações no código, executar o build da aplicação e, por fim, realizar o deploy dos artefatos no S3.
  • AWS IAM (Identity and Access Management): Garante a comunicação segura entre o Azure DevOps e a AWS, concedendo ao pipeline permissões específicas e limitadas para interagir com o bucket S3.

Pontos de Atenção na Configuração

Durante a implementação, dois pontos se mostraram cruciais para o sucesso do pipeline e merecem destaque:

  1. Necessidade do AWS Toolkit: O Azure DevOps, por padrão, não possui tarefas nativas para interagir com todos os serviços da AWS. É fundamental instalar a extensão "AWS Toolkit for Azure DevOps" via Marketplace. Ela adiciona um conjunto de tarefas essenciais, incluindo a S3Upload, que utilizamos para enviar os arquivos ao bucket.
  2. Ambiguidade de Tarefas: Em ambientes que utilizam múltiplas extensões, é possível que ocorram conflitos de nome entre tarefas. Caso outra extensão instalada também ofereça uma task chamada S3Upload, o pipeline falhará com um erro de ambiguidade. A solução é utilizar o identificador completo e explícito da tarefa no arquivo YAML, como AmazonWebServices.aws-vsts-tools.S3Upload.S3Upload@1, para garantir que o orquestrador execute a ferramenta correta.

Implementando o Pipeline de Deploy

A seguir, apresento os passos detalhados para replicar essa automação.

Passo 1: Configuração do AWS S3

  1. Criação do Bucket: No console da AWS, crie um novo bucket S3. Escolha um nome único e a região desejada. Na seção de permissões, desmarque a opção "Block all public access".
  2. Hospedagem de Site Estático: Navegue até as propriedades do bucket, encontre a opção "Static website hosting" e habilite-a. Configure index.html como "Index document".
  3. Política de Bucket: Para permitir que os usuários acessem o site, aplique uma política de acesso público na aba "Permissions". A política a seguir permite a leitura (s3:GetObject) de todos os objetos do bucket.JSON
1{
2    "Version": "2012-10-17",
3    "Statement": [
4        {
5            "Sid": "PublicReadGetObject",
6            "Effect": "Allow",
7            "Principal": "*",
8            "Action": "s3:GetObject",
9            "Resource": "arn:aws:s3:::SEU-NOME-DE-BUCKET/*"
10        }
11    ]
12}

Passo 2: Configuração do Azure DevOps

  1. Projeto e Repositório: Crie um projeto no Azure DevOps e envie o código-fonte da sua aplicação React para o Azure Repos.
  2. Conexão de Serviço (Service Connection):
    • Na AWS, crie um usuário IAM com acesso programático e anexe a política AmazonS3FullAccess (ou uma política mais restrita, se preferir). Guarde o ID da Chave de Acesso e a Chave de Acesso Secreta.
    • No Azure DevOps, em "Project Settings" > "Service connections", crie uma nova conexão do tipo AWS. Insira as credenciais do usuário IAM geradas e dê um nome para a conexão (ex: AWS_S3_Connection).

Passo 3: Criação do Pipeline YAML

Na raiz do seu repositório, crie o arquivo azure-pipelines.yml com o código abaixo. Este arquivo define todas as etapas do processo de build e deploy.

azure-pipelines.yml
1# Define o gatilho: qualquer push na branch 'main' inicia o pipeline
2trigger:
3- main
4
5# Define a imagem da máquina virtual que executará os jobs
6pool:
7  vmImage: 'ubuntu-latest'
8
9stages:
10# Estágio 1: Build da Aplicação
11- stage: Build
12  displayName: 'Build da Aplicação React'
13  jobs:
14  - job: BuildJob
15    steps:
16    # Instala a versão do Node.js especificada
17    - task: NodeTool@0
18      inputs:
19        versionSpec: '22.x'
20      displayName: 'Instalar Node.js'
21
22    # Executa 'npm install' para baixar as dependências
23    - script: npm install
24      displayName: 'Instalar dependências (npm install)'
25
26    # Executa o script de build que gera os arquivos estáticos na pasta 'dist'
27    - script: npm run build
28      displayName: 'Build do projeto (npm run build)'
29
30    # Publica a pasta 'dist' como um artefato, para ser usada no próximo estágio
31    - task: PublishBuildArtifacts@1
32      inputs:
33        PathtoPublish: 'dist'
34        ArtifactName: 'drop'
35        publishLocation: 'Container'
36
37# Estágio 2: Deploy dos Artefatos
38- stage: Deploy
39  displayName: 'Deploy no AWS S3'
40  dependsOn: Build # Garante que o estágio de Deploy só execute após o sucesso do Build
41  jobs:
42  - job: DeployJob
43    steps:
44    # Baixa o artefato ('drop') publicado pelo estágio de Build
45    - task: DownloadBuildArtifacts@1
46      inputs:
47        buildType: 'current'
48        downloadType: 'single'
49        artifactName: 'drop'
50        downloadPath: '$(System.ArtifactsDirectory)'
51
52    # Utiliza a tarefa do AWS Toolkit com seu nome completo para evitar ambiguidades
53    - task: AmazonWebServices.aws-vsts-tools.S3Upload.S3Upload@1
54      inputs:
55        awsCredentials: 'AWS_S3_Connection'    # Nome da Service Connection criada
56        regionName: 'sa-east-1'                 # Região do bucket S3
57        bucketName: 'seu-nome-de-bucket'        # Nome do bucket S3
58        sourceFolder: '$(System.ArtifactsDirectory)/drop'
59        cleanBucket: true # Recomendado: remove arquivos antigos do bucket antes do upload

Conclusão

A implementação de um pipeline de CI/CD robusto é um marco importante para qualquer equipe de desenvolvimento. Ela não apenas otimiza o fluxo de entrega, mas também introduz um padrão de qualidade e confiabilidade, garantindo que cada alteração passe por um processo validado antes de chegar ao usuário final. Concluir este projeto como parte do meu PDI foi uma experiência valiosa, solidificando conceitos essenciais de DevOps que são diretamente aplicáveis no dia a dia.